下面是抽象数据类型字符串序列的C ++类定义:
class Sequence
{
public:
Sequence(); // Create an empty sequence.
bool empty(); // Return true if the sequence is empty, otherwise false.
int size(); // Return the number of items in the sequence.
bool insert(int pos, const std::string& value);
// Insert value into the sequence so that it becomes the item at
// position pos. The original item at position pos and those that
// follow it end up at positions one higher than they were at before.
// Return true if 0 <= pos <= size() and the value could be
// inserted. (It might not be, if the sequence has a fixed capacity,
// e.g., because it's implemented using a fixed-size array.) Otherwise,
// leave the sequence unchanged and return false. Notice that
// if pos is equal to size(), the value is inserted at the end.
bool insert(const std::string& value);
// Let p be the smallest integer such that value <= the item at
// position p in the sequence; if no such item exists (i.e.,
// value > all items in the sequence), let p be size(). Insert
// value into the sequence so that it becomes the item at position
// p. The original item at position p and those that follow it end
// up at positions one higher than before. Return true if the value
// was actually inserted. Return false if the value was not inserted
// (perhaps because the sequence has a fixed capacity and is full).
bool erase(int pos);
// If 0 <= pos < size(), remove the item at position pos from
// the sequence (so that all items that followed this item end up at
// positions one lower than they were at before), and return true.
// Otherwise, leave the sequence unchanged and return false.
int remove(const std::string& value);
// Erase all items from the sequence that == value. Return the
// number of items removed (which will be 0 if no item == value).
bool get(int pos, std::string& value);
// If 0 <= pos < size(), copy into value the item at position pos
// in the sequence and return true. Otherwise, leave value unchanged
// and return false.
bool set(int pos, const std::string& value);
// If 0 <= pos < size(), replace the item at position pos in the
// sequence with value and return true. Otherwise, leave the sequence
// unchanged and return false.
int find(const std::string& value);
// Let p be the smallest integer such that value == the item at
// position p in the sequence; if no such item exists, let p be -1.
// Return p.
void swap(Sequence& other);
// Exchange the contents of this sequence with the other one.
};
这是一个字符串序列的删除函数示例:
Sequence s;
s.insert(0, "a");
s.insert(1, "b");
s.insert(2, "c");
s.insert(3, "b");
s.insert(4, "e");
assert(s.remove("b") == 2);
assert(s.size() == 3);
string x;
assert(s.get(0, x) && x == "a");
assert(s.get(1, x) && x == "c");
assert(s.get(2, x) && x == "e");
这是交换功能的一个例子:
Sequence s1;
s1.insert(0, "paratha");
s1.insert(0, "focaccia");
Sequence s2;
s2.insert(0, "roti");
s1.swap(s2);
assert(s1.size() == 1 && s1.find("roti") == 0 && s2.size() == 2 &&
s2.find("focaccia") == 0 && s2.find("paratha") == 1);
Sequence类的哪些成员函数应该是const成员函数(因为它们不修改Sequence)?我们必须相应地更改班级声明。
如上所述,Sequence类允许客户端使用仅包含 std :: strings 的序列。如果我们要修改类以包含其他类型的项目,例如仅整理或仅双精选,则必须在许多地方进行更改。修改您在上一个问题中生成的类定义,以便在原始定义使用 std :: string 的所有值中使用 typedef - 定义类型。使用 typedef :
的示例typedef int Number; // define Number as a synonym for int
int main()
{
Number total = 0;
Number x;
while (cin >> x)
total += x;
cout << total << endl;
}
修改此代码以对long或double的序列求和。只需要在一个地方进行更改:typedef。要求是使用与 typedef 定义的名称相同的同义词:名称 ItemType ,具有该拼写和大小写。
现在已经定义了一个序列类的接口,其中可以轻松更改项类型,实现类及其所有成员函数,使得序列中的项包含在数据中作为数组的成员。序列必须能够容纳最多DEFAULT_MAX_ITEMS项,其中
const int DEFAULT_MAX_ITEMS = 200;
必须针对无符号长整数序列测试该类。类定义和内联函数定义(如果有)必须包含在名为 Sequence.h 的文件中,非内联函数定义(如果有)必须包含在名为 Sequence.cpp。
可以根据需要添加任何私有数据成员或私有成员函数,但不必在上一个问题中定义的公共接口中添加或删除任何内容,也不允许更改函数签名。唯一的例外是:允许添加带有签名 void dump()const 的公共成员函数。该函数的目的是为了测试目的,它能够调用它来打印有关序列的信息。如果不需要,不必添加此功能,但如果添加,则不得对序列进行任何更改。转储功能不得写入 cout ,但允许写入 cerr 。
Sequence类的实现必须使编译器生成的析构函数,复制构造函数和赋值运算符做正确的事情。必须编写名为 testSequence.cpp 的测试程序,以确保Sequence类实现正常工作。这是一个可能的(不完整的)测试程序:
#include "Sequence.h"
#include <iostream>
#include <cassert>
using namespace std;
int main()
{
Sequence s;
assert(s.empty());
assert(s.find(42) == -1);
s.insert(42);
assert(s.size() == 1 && s.find(42) == 0);
cout << "Passed all tests" << endl;
}
现在(仅)必须更改Sequence.h中的typedef,以便Sequence现在包含 std :: strings 。除非必要时添加 #include ,否则不得对 Sequence.h 和 Sequence.cpp 进行其他更改。可以验证实现是否正确构建并且正常使用此替代主程序(这不是对正确性的完整测试):
#include "Sequence.h"
#include <iostream>
#include <cassert>
using namespace std;
int main()
{
Sequence s;
assert(s.empty());
assert(s.find("laobing") == -1);
s.insert("laobing");
assert(s.size() == 1 && s.find("laobing") == 0);
cout << "Passed all tests" << endl;
}
Sequence.h 和 Sequence.cpp 代码可能需要在彼此之间翻转才能修复几次,以便对这些文件进行必要的更改更改序列的项类型是 Sequence.h 中的typedef。 (当任务完成后,请使用它们以使项目类型为无符号长。)
除 Sequence.h 中的typedef语句外,unsigned和long一词不得出现在 Sequence.h 或 Sequence.cpp 中。除 #include 的上下文外,单词字符串不得出现在 Sequence.h 或 Sequence.cpp 中。
(实施说明:交换功能可在不创建任何附加阵列或附加序列的情况下实现)
现在该类已经实现了,必须编写一些使用它的客户端代码。实现以下使用无符号long序列的类:
#include "Sequence.h"
#include <limits>
const unsigned long NO_SCORE = std::numeric_limits<unsigned long>::max();
class ScoreList
{
public:
ScoreList(); // Create an empty score list.
bool add(unsigned long score);
// If the score is valid (a value from 0 to 100) and the score list
// has room for it, add it to the score list and return true.
// Otherwise, leave the score list unchanged and return false.
bool remove(unsigned long score);
// Remove one instance of the specified score from the score list.
// Return true if a score was removed; otherwise false.
int size() const; // Return the number of scores in the list.
unsigned long minimum() const;
// Return the lowest score in the score list. If the list is
// empty, return NO_SCORE.
unsigned long maximum() const;
// Return the highest score in the score list. If the list is
// empty, return NO_SCORE.
private:
// Some of your code goes here.
};
ScoreList实现必须使用Sequence类型的数据成员,该成员使用typedef ItemType 作为 unsigned long 的同义词。除了更改一行(Sequence.h中的typedef)之外,不必对为问题3生成的 Sequence.h 和 Sequence.cpp 文件进行更改,因此不会必须将成员函数添加到Sequence类中。每个成员函数添加,删除,大小,最小和最大必须尽可能多地委托他们需要执行的工作,以便对成员函数进行排序。 (换句话说,他们不能自己工作,他们可以要求Sequence成员函数来做。)如果编译器生成的析构函数,复制构造函数和ScoreList的赋值运算符不做正确的事情,它们必须是宣布并实施。构造一个程序来测试ScoreList类。这些文件应命名为 ScoreList.h,ScoreList.cpp和testScoreList.cpp。
和 时不得出现在 ScoreList.h 或 ScoreList.cpp 中,但是如果需要, ScoreList :: minimum 和 ScoreList :: maximum 的实现。字符[(方括号)和*不得出现在 StudentMultiset.h 或 StudentMultiset.cpp 中,但评论中除外(如果需要)。如果不需要, ScoreList.h 和 ScoreList.cpp 中的无符号长到 ItemType 不需要进行任何更改如此。
现在已经创建了基于数组的序列类型,其大小在编译时是固定的,必须更改实现以使用动态分配的对象数组。必须复制为问题3生成的三个文件,命名新文件newSequence.h,newSequence.cpp和testnewSequence.cpp。必须通过添加另一个构造函数或修改现有构造函数来更新这些文件,以便客户端可以执行以下操作:
Sequence a(1000); // a can hold at most 1000 items
Sequence b(5); // b can hold at most 5 items
Sequence c; // b can hold at most DEFAULT_MAX_ITEMS items
ItemType v = some value of the appropriate type;
// No failures inserting 5 items into b
for (int k = 0; k < 5; k++)
assert(b.insert(v));
// Failure if we try to insert a sixth item into b
assert(!b.insert(v));
// When two Sequences' contents are swapped, their capacities are
// swapped as well:
a.swap(b);
assert(!a.insert(v) && b.insert(v));
由于编译器生成的析构函数,复制构造函数和赋值运算符不再正确,它们必须被声明(作为公共成员)并实现。不必对您的类的公共接口进行其他更改。 (允许对私有成员和成员函数的实现进行更改或添加。)必须更改 swap 函数的实现,以便在交换两个序列时执行语句的次数无论序列中有多少项,都是一样的。 (例如,如果 swap 函数导致循环访问序列中的每个项目,则会满足此要求,因为循环的所有迭代执行的语句数量取决于数量序列中的项目。)
字符[(空方括号)不得出现在 newSequence.h 中(但在 newSequence.cpp 中可以正常使用)。
必须测试Sequence类的新实现。 (即使文件名为 newSequence.h ,其中定义的类名仍必须序列)
验证ScoreList类是否仍适用于此新版本的Sequence。除了#include&#34; newSequence.h &#34;之外,ScoreList类不需要以任何方式更改或实现。而不是&#34; Sequence.h&#34; 。 (在ScoreList.h和ScoreList.cpp完成之前,请确保所有#includes to&#34; Sequence.h&#34;都已恢复,而不是&#34; newSequence.h&#34;)
任务#1-5的要求:
每个头文件 Sequence.h,ScoreList.h和newSequence.h 必须具有适当的包含保护。在要运行和测试的文件中,Sequence.h和newSequence.h中的typedef必须将ItemType定义为unsigned long的同义词。
如果创建了由 Sequence.h,Sequence.cpp和testSequence.cpp 组成的项目,则必须在Visual C ++下成功构建。
如果创建了由 Sequence.h,Sequence.cpp,ScoreList.h,ScoreList.cpp和testScoreList.cpp 组成的项目,则必须在Visual C ++下成功构建。
如果创建了由 newSequence.h,newSequence.cpp和testnewSequence.cpp 组成的项目,则必须在Visual C ++下成功构建。
如果创建的项目由 newSequence.h,newSequence.cpp和testSequence.cpp 组成,那么在testSequence.cpp中只有 #include&#34; Sequence.h&# 34; 更改为 #include&#34; newSequence.h&#34; ,项目必须在Visual C ++下成功构建。 (如果尝试这样做,请确保在运行 testSequence.h 之前将#include返回更改为&#34; Sequence.h&#34; 。)
除名称以test开头的文件之外的文件可能包含从cin读取任何内容或将任何内容写入cout的代码,但对于问题5,采用整数参数的构造函数的实现可能会写入消息并退出程序,如果整数是负数。任何文件都可以写入cerr(可能用于调试目的);写入cerr的任何输出都将被忽略。
Sequence和ScoreList的每个成员函数都必须有一个实现。如果无法正确实现函数,则其实现必须至少成功构建。
如果将 #include 添加到创建的 Sequence.h ,请更改序列的项类型的typedef以指定 std ::字符串作为项目类型,不对 Sequence.cpp 进行更改,编译 Sequence.cpp ,并将其链接到包含以下内容的文件:
#include "Sequence.h"
#include <string>
#include <iostream>
#include <cassert>
using namespace std;
void test()
{
Sequence s;
assert(s.insert(0, "lavash"));
assert(s.insert(0, "tortilla"));
assert(s.size() == 2);
ItemType x = "injera";
assert(s.get(0, x) && x == "tortilla");
assert(s.get(1, x) && x == "lavash");
}
int main()
{
test();
cout << "Passed all tests" << endl;
}
链接必须成功。当生成的可执行文件运行时,它必须写通过所有测试,而不是 cout ,并正常终止。
如果成功实现了上述目标,则更改序列项目类型的typedef以指定 unsigned long 作为项目类型而不进行任何其他更改,重新编译序列。 cpp ,并将其链接到包含以下内容的文件:
#include "Sequence.h"
#include <iostream>
#include <cassert>
using namespace std;
void test()
{
Sequence s;
assert(s.insert(0, 10));
assert(s.insert(0, 20));
assert(s.size() == 2);
ItemType x = 999;
assert(s.get(0, x) && x == 20);
assert(s.get(1, x) && x == 10);
}
int main()
{
test();
cout << "Passed all tests" << endl;
}
链接必须成功。当生成的可执行文件运行时,它必须写通过所有测试,而不是 cout ,并正常终止。
如果将 #include 添加到 newSequence.h ,请更改序列的项类型的typedef以指定 std :: string 作为项目类型,不对 newSequence.cpp 进行更改,编译 newSequence.cpp ,并将其链接到包含以下内容的文件:
#include "newSequence.h"
#include <string>
#include <iostream>
#include <cassert>
using namespace std;
void test()
{
Sequence s;
assert(s.insert(0, "lavash"));
assert(s.insert(0, "tortilla"));
assert(s.size() == 2);
ItemType x = "injera";
assert(s.get(0, x) && x == "tortilla");
assert(s.get(1, x) && x == "lavash");
}
int main()
{
test();
cout << "Passed all tests" << endl;
}
链接必须成功。当生成的可执行文件运行时,它必须写通过所有测试,而不是 cout ,并正常终止。
如果成功实现了上述目标,则更改序列项目类型的typedef以指定 unsigned long 作为项目类型而不进行任何其他更改,重新编译 newSequence。 cpp ,并将其链接到包含
的文件 #include "newSequence.h"
#include <iostream>
#include <cassert>
using namespace std;
void test()
{
Sequence s;
assert(s.insert(0, 10));
assert(s.insert(0, 20));
assert(s.size() == 2);
ItemType x = 999;
assert(s.get(0, x) && x == 20);
assert(s.get(1, x) && x == 10);
}
int main()
{
test();
cout << "Passed all tests" << endl;
}
链接必须成功。当生成的可执行文件运行时,它必须写通过所有测试,而不是 cout ,并正常终止。