赞
踩
编译软件为 vs2015。
对于下面的程序任务, vector、deque、和 list 哪种容器最为适合?解释你选择的理由、如果没有哪一种容器优于其他容器,也请解释理由。
(a)读取固定数量的单词,将他们按字典顺序插入到容器中。我们将在下一章看到关联容器更适合这个问题。
(b)读取未知数量的单词,总是将新单词插入到末尾。删除操作在头部进行。
(c)从一个文件读取未知数量的整数。将这些数排序,然后将它们打印到标准输出。
解答:
(a)由于需要按照字母顺序排列,所以会出现在容器中间插入数据的操作,所以选择 list 更合适。
(b)根据要求是在头部和尾部两端进行插入和删除的操作,选择 deque 更合适,并且在两端的插入和删除操作很快。
(c)选择 vector,不需要插入和删除操作,其次若程序中有很多小的元素,也不宜选择 list 和 forward_list。
定义一个 list 对象,其元素类型是 int 的 deque。
解答:
- #include <list>
- #include <deque>
- using namespace std;
-
- int main()
- {
- list<deque<int>> lis;
- return 0;
- }
构成迭代器范围的迭代器有何限制?
解答:
它们指向同一个容器中的元素,或者是容器最后一个元素之后的位置;
我们可以通过递增 begin 来达到 end,即 end 不能在 begin 之前。
编写函数,接受一对指向 vector<int> 的迭代器和一个 int 值。在两个迭代器指定的范围中查找给定的值,返回一个布尔值来指出是否找到。
解答:
- #include <iostream>
- #include <vector>
- using namespace std;
-
- bool func(vector<int>::iterator beg, vector<int>::iterator end, int value)
- {
- for (auto iter = beg; iter != end; iter++)
- if (*iter == value)
- return true;
- return false;
- }
-
- int main()
- {
- vector<int> vec{ 1,2,3,4,5,6,7 };
- auto beg = vec.begin();
- auto end = vec.end();
- int value = 3;
- func(beg, end, value);
- system("pause");
- return 0;
- }
重写上一题的函数,返回一个迭代器指向的元素。注意,程序必须处理未找到给定值的情况。
解答:
- #include <iostream>
- #include <vector>
- using namespace std;
-
- vector<int>::iterator func(vector<int>::iterator beg, vector<int>::iterator end, int value)
- {
- for (auto iter = beg; iter != end; iter++)
- if (*iter == value)
- return iter;
- return end;
-
- }
-
- int main()
- {
- vector<int> vec{ 1,2,3,4,5,6,7 };
- auto beg = vec.begin();
- auto end = vec.end();
- int value = 3;
- auto result = func(beg, end, value);
-
- if (result != end) //处理未找到给定值的情况
- {
- cout << *result << endl;
- }
- else
- {
- cout << "not found" << endl;
- }
- system("pause");
- return 0;
- }
下面的程序有何错误?你应该如何修改它?
list<nt> list1;
list<int>::iterator iter1 = list1.begin(), iter2 = list1.end();
while(iter1<iter2) { /*......*/ }
解答:
迭代器的 "<" 运算符只能用于 string、vector、deque、 和 array,不能用于 list,应该修改为 while(iter1 != iter2)。
为了索引 int 的 vector 中的元素,应该使用什么类型?
解答:
vector<int>::size_type
为了读取 string 的 list 中的元素,应该使用什么类型?如果写入 list,又该使用什么类型?
解答:
如果只是读取元素,可以设置为 const 类型,即 list<string>::const_iterator。
需要向 list 中写入元素,则应该为 list<string>::iterator。
begin 和 cbegin 有什么不同?
解答:
begin 函数当且仅当 a.begin() 中 a 是常量类型时,返回 const_iterator,否则返回 iterator。而 cbegin 则是返回 const_iterator。
下面4个对象分别是什么类型?
vector<int> v1;
const vector<int> v2;
auto it1 = v1.begin(), it2 = v2.begin();
auto it3 = v1.cbegin(), it4 = v2.cbegin();
解答:
it1 是 vector<int>::iterator;
it2、it3、it4 均为 vector<int>::const_iterator;
对 6 种创建和初始化 vector 对象的方法,每一种给出一个实例。解释每个 vector 包含什么值。
解答:
- #include <vector>
- using namespace std;
-
- int main()
- {
- vector <int> vec1; // 容器中的值为 0
-
- vector <int> vec2(10); // 容器中元素的数量为 10,元素值为 0
-
- vector <int> vec3(5, 1); // 容器中元素数量为 5,元素值均为 1
-
- vector <int> vec4{ 1,2,3,4,5 }; //列表初始化,容器中数值为 1,2,3,4,5
- vector <int> vec4 = { 1,2,3,4,5 }; // 与 vector <int> vec4{ 1,2,3,4,5 } 等价
-
- vector <int> vec5(vec3); // vec5 初始化为 vec3 的拷贝,容器内的值为 5 个 1
- vector <int> vec5 = vec3; // 与 vector<int> vec5(vec3) 等价
-
- vector <int> vec6(vec4.begin(), vec4.end());
- //vec6 初始化为 vec4 的 begin 和 end 范围内元素的拷贝,值为 1,2,3,4,5
-
- }
对于接受一个容器创建其拷贝的构造函数,和接受两个迭代器创建拷贝的构造函数,解释它们的不同。
解答:
对于接受一个容器创建其拷贝的构造函数,需要使得两个容器的容器类型和元素类型都相同,且需要将接收到的容器中的所有元素复制到新创建的容器中。
而对于接受两个迭代器创建拷贝的构造函数,只需要元素的类型相同或者可以转换为新容器中的元素类型,而不需要两个容器的类型相同,此方式对于 array 不适用,同时这种方式可以只复制迭代器指向的范围内的元素。
如何从一个 list<int> 初始化一个 vector<double> ?从一个 vector<int> 又该如何创建?编写代码验证你的答案。
解答:
- #include <vector>
- #include <list>
- #include <iostream>
- using namespace std;
-
- int main()
- {
- list<int> list{ 1,2,3,4,5 };
- vector<int> veci = { 6,7,8,9,0 };
- vector<double> vec1(list.begin(), list.end());
- for (auto &c : vec1)
- cout << c << " ";
- cout << endl;
-
- vector<double> vec2(veci.begin(), veci.end());
- for (auto &c : vec2)
- cout << c << " ";
- cout << endl;
- system("pause");
- return 0;
- }
编写程序,将一个 list 中的 char * 指针(指向 c 风格字符串)元素赋值给一个 vector 中的 string。
解答:
- #include <list>
- #include <vector>
- #include <string>
- #include <iostream>
- using namespace std;
-
- int main()
- {
- list<const char*> list{ "hello", "world", "nice" };
- vector<string> vec;
- vec.assign(list.cbegin(), list.cend());
- for (const auto &c : vec)
- cout << c << " ";
- cout << endl;
- system("pause");
- return 0;
- }
编写程序,判定两个 vector<int> 是否相等。
解答:
- #include <vector>
- #include <iostream>
- using namespace std;
-
- int main()
- {
- vector<int> vec1{ 1,2,3,4,5 };
- vector<int> vec2{ 1,2,4,5 };
- if (vec1 == vec2)
- cout << "vec1 = vec2" << endl;
- else if (vec1 < vec2)
- cout << "vec1 < vec2" << endl;
- else
- cout << "vec1 > vec2" << endl;
- system("pause");
- return 0;
- }
重写上一题的程序,比较一个 list<int> 中的元素和一个 vector<int> 中的元素。
解答:
- #include <vector>
- #include <list>
- #include <iostream>
- using namespace std;
-
- int main()
- {
- vector<int> vec1{ 1,2,3,4,5 };
- list<int> list{ 1,2,4,5 };
- auto begv = vec1.begin(), endv = vec1.end();
- auto begl = list.begin(), end = list.end();
- for (begv != endv; begl != end; begv++, begl++)
- {
- if (*begv == *begl) //逐个判断两个容器中的元素是否相等
- {
- if (begv == endv - 1)
- cout << "equal" << endl;
- continue;
- }
- else
- cout << "not equal" << endl;
- break;
- }
- system("pause");
- return 0;
- }
假定 c1 和 c2 是两个容器,下面的比较操作有何限制(如果有的话)?
if (c1 < c2)
解答:
首先 c1,c2 不能为无序关联容器,因为其不支持 “<” 运算符;其次,c1, c2 必须石向彤的容器类型且元素类型也相同,同时还需要满足容器内元素也支持 “<” 运算符。
编写程序,从标准输入读取 string 序列,存入一个 deque 中。编写一个循环,用迭代器打印 deque 中的元素。
解答:
- #include <iostream>
- #include <deque>
- #include <string>
- using namespace std;
-
- int main()
- {
- string word;
- deque<string> deq;
- cout << "please input your words: " << endl;
- while (cin >> word)
- {
- deq.push_back(word);
- }
- for (auto beg = deq.cbegin(); beg != deq.cend(); beg++)
- cout << *beg << " ";
- cout << endl;
- system("pause");
- return 0;
-
- }
重写上一题的程序,用 list 代替 deque。列出程序要做出哪些改变。
解答:
直接将 deque 替换为 list 即可。
- #include <iostream>
- #include <list>
- #include <string>
- using namespace std;
-
- int main()
- {
- string word;
- list<string> deq;
- cout << "please input your words: " << endl;
- while (cin >> word)
- {
- deq.push_back(word);
- }
- for (auto beg = deq.cbegin(); beg != deq.cend(); beg++)
- cout << *beg << " ";
- cout << endl;
- system("pause");
- return 0;
-
- }
编写程序,从一个 list<int> 拷贝元素到两个 deque 中。值为偶数的所有元素都拷贝到一个 deque 中,而奇数值元素都拷贝到另一个 deque 中。
解答:
- #include <list>
- #include <deque>
- #include <iostream>
- using namespace std;
-
- int main()
- {
- deque<int> even;
- deque<int> odd;
- list<int> list{ 1,2,3,4,5,6,7,8,9 };
- for (auto beg = list.cbegin(); beg != list.cend(); beg++)
- {
- if (*beg % 2 == 0)
- even.push_back(*beg);
- else
- odd.push_back(*beg);
- }
-
- cout << "even number: ";
- for (auto &c : even)
- cout << c << " ";
- cout << endl;
-
- cout << "odd number: ";
- for (auto &c : odd)
- cout << c << " ";
- cout << endl;
- system("pause");
- return 0;
- }
如果我们将第 308 页中使用 insert 返回值将元素添加到 list 中的循环程序改写为将元素插入到 vector 中,分析循环将如何工作。
解答:
第一次调用 insert 会将我们刚刚读入的 string 插入到 iter 所指的元素之前的位置。insert 返回的迭代器将指向这个新元素。我们将此迭代器赋予 iter 并重复循环,读取下一个单词。只要继续有单词读入,每步 while 循环就会将一个新元素插入到 iter 之前,并将 iter 改变为新加入元素的位置。此元素为新的首元素。因此,每步循环将一个新元素插入到 vector 首元素之前的位置。
假设 iv 是一个 int 的 vector,下面的程序存在什么错误?你将如何修改?
vector<int>::iterator iter = iv.begin(), mid = iv.begin() + iv.size()/2;
while (iter != mid)
if(*iter == some_val)
iv.insert(iter, 2*some_val);
解答:
iter 是指向 iv 的迭代器,迭代器不能指向添加元素的目标容器,将会是一个死循环。
其次,在 vector 中使用 insert 操作会引起迭代器、引用和指针失效。
在本节的第一个程序(第 309 页)中,若 c.size() 为 1,则 val、val2、val3 和 val 4的值会是什么?
解答:
它们都是指向容器中的唯一一个值。
编写程序,分别使用 at、下标运算符、front 和 begin 提取一个 vector 中的第一个元素。在一个空 vector 上测试你的程序。
解答:
- #include <iostream>
- #include <vector>
- using namespace std;
-
- int main()
- {
- vector<int> vec{ 1,2,3,4 };
- auto a = vec.at(0);
- auto b = vec[0];
- auto c = *vec.begin();
- auto d = vec.front();
- cout << a << " " << b << " " << c << " " << d << " ";
- cout << endl;
- system("pause");
- return 0;
- }
对于第 312 页中删除一个范围内的元素的程序,如果 elem1 与 elem2 相等会发生什么? 如果 elem2 是尾后迭代器,或者 elem1 和 elem2 皆为尾后迭代器,又会发生什么?
解答:
如果相等则什么也不会发生;
若 elem2 是尾后迭代器,则会删除从 elem1 到 elem2 范围内的所有元素;
若两个均为尾后迭代器则什么也不会发生。
使用下面代码定义的 ia,将 ia 拷贝到一个 vector 和 一个 list 中。使用单迭代器版本的 erase 从 list 中删除奇数元素,从 vector 中删除偶数元素。
int ia[ ] = { 0,1,1,2,3,5,8,13,21,55,89 };
解答:
- #include <iostream>
- #include <vector>
- #include <list>
- using namespace std;
-
- int main()
- {
- int ia[] = { 0,1,1,2,3,5,8,13,21,55,89 };
- vector<int> vec;
- list<int> list;
- for (int i = 0; i != 11; ++i)
- {
- vec.push_back(ia[i]);
- list.push_back(ia[i]);
- }
-
- for (auto beg1 = vec.begin(); beg1 != vec.end();)
- {
- if (*beg1 % 2 == 0)
- beg1 = vec.erase(beg1); //注意要写上 beg1 =
- else
- ++beg1;
- }
-
- for (auto beg2 = list.begin(); beg2 != list.end();)
- {
- if (*beg2 % 2 == 1)
- beg2 = list.erase(beg2);
- else
- ++beg2;
- }
-
- for (auto &c : vec)
- cout << c << " ";
- cout << endl;
-
- for (auto &c : list)
- cout << c << " ";
- cout << endl;
-
- system("pause");
- return 0;
- }
编写程序,查找并删除 forward_list<int> 中的奇数元素。
解答:
- #include <forward_list>
- #include <iostream>
- using namespace std;
-
- int main()
- {
- forward_list<int> flist{ 1,2,3,4,5,6,7,8,9 };
- auto prev = flist.before_begin();
- auto curr = flist.begin();
- while (curr != flist.end())
- {
- if (*curr % 2 == 1)
- curr = flist.erase_after(prev);
- else
- {
- prev = curr;
- ++curr; //两个迭代器都向后移动
- }
- }
- for (auto &c : flist)
- cout << c << " ";
- cout << endl;
- system("pause");
- return 0;
- }
编写函数,接受一个 forward_list<string> 和两个 string 共三个参数。函数应在链表中查找第一个 string,并将第二个 string 插入到紧接着第一个 string 之后的位置。若第一个 string 未在链表中,则将第二个 string 插入到链表末尾。
解答:
- #include <forward_list>
- #include <string>
- #include <iostream>
- using namespace std;
-
- void func(forward_list<string> flist, const string &s1, const string &s2)
- {
- auto prev = flist.before_begin();
- auto size = distance(flist.begin(), flist.end());
-
- for (auto curr = flist.begin(); curr != flist.end(); prev = curr++)
- {
- if (*curr == s1)
- {
- flist.insert_after(curr, s2);
- }
- }
-
- auto ss = distance(flist.begin(), flist.end());
- if ( ss == size)
- {
- flist.insert_after(prev, s2);
- }
-
- for (const auto &c : flist)
- cout << c << " ";
- cout << endl;
- }
-
-
- int main()
- {
- forward_list<string> flist{ "hello", "world" };
- const string &s1 = "hello";
- const string &s2 = "big";
- func(flist, s1, s2);
-
- system("pause");
- return 0;
- }
假定 vec 包含 25 个元素,那么 vec.resize(100) 会做什么?如果接下来调用 vec.resize(10)会做什么?
解答:
首先将会添加 75 个新元素,并且进行值初始化;之后的操作会删除 vec 中后 90 个元素。
接受单个参数的 resize 版本对元素类型有什么限制(如果有的话)?
解答:
如果容器是类类型,且利用 resize 向容器中添加元素,则我们必须提供初始值,或者元素类型必须提供一个默认的构造函数。
第 316 页中删除偶数值元素并复制奇数值元素的程序不能用于 list 或 forward_list。为什么?修改程序,使之也能用于这些类型。
解答:
因为 list 和 forward_list 中迭代器不支持 “+n”,“-n” 运算符。
- #include <list>
- #include <iostream>
- using namespace std;
-
- int main()
- {
- list<int> list{ 0,1,2,3,4,5,6,7,8,9 };
- auto iter = list.begin();
- while (iter != list.end())
- {
- if (*iter % 2 != 0)
- {
- iter = list.insert(iter, *iter);
- iter++;
- iter++; //或者用 advance(iter,2)
- }
- else
- {
- iter = list.erase(iter);
- }
- }
-
- for (auto &c : list)
- cout << c << " ";
- cout << endl;
- system("pause");
- return 0;
- }
在第 316 页的程序中,像下面语句这样调用 insert 是否合法?如果不合法,为什么?
iter = vi.insert (iter, *iter++);
解答:
不合法,循环的最后迭代器会指向尾元素后不存在的位置,是非法的。
在本节最后一个例子中,如果不讲 insert 的结果赋予 begin,将会发生什么?编写程序,去掉此赋值语句,验证你的答案。
解答:
会失效,在向容器添加元素后,如果容器是vector或string,且存储空间被重新分配,则指向容器的迭代器,指针和引用都会失效。
- #include <vector>
- #include <iostream>
- using namespace std;
-
- int main()
- {
- vector<int> v{ 1,2,3,4,5,6 };
- auto begin = v.begin();
- while (begin != v.end())
- {
- ++begin;
- v.insert(begin, 42);
- ++begin;
- }
-
- for (auto &c : v)
- cout << c << " ";
- cout << endl;
- system("pause");
- return 0;
- }
会出现如下错误提示:
假定 vi 是一个保存 int 的容器,其中有偶数值也有奇数值,分析下面循环的行为,然后编写程序验证你的分析是否正确。
iter = vi.begin();
while(iter != vi.end())
{
if (*iter % 2)
iter = vi.insert(iter, *iter);
++iter;
}
解答:
此循环的目的是将容器中的奇数在所在位置之前复制一次,但是由于 insert 返回的是插入值的位置,所以应该将插入值后的迭代器向前移动两个位置。
- #include <vector>
- #include <iostream>
- using namespace std;
-
- int main()
- {
- vector<int> vec{ 1,2,3,4,5,6,7,8,9 };
- auto iter = vec.begin();
- while (iter != vec.end())
- {
- if (*iter % 2)
- {
- iter = vec.insert(iter, *iter);
- iter++;
- }
- iter++;
- }
-
- for (auto &c : vec)
- cout << c << " ";
- cout << endl;
- system("pause");
- return 0;
- }
解释一个 vector 的 capacity 和 size 有何区别。
解答:
size 指它已经保存的元素的数目
capacity 在不分配新的内存空间的前提下它最多可以保存多少元素
一个容器的 capacity 可能小于它的 size 吗?
解答:
capacity 会根据 vector 具体实现时对空间的需求自动分配内存,所以不可能小于 size 的值。
为什么 list 和 array 没有 capacity 成员函数?
解答:
因为 list 不需要连续存储,而 array 在创建时就固定了大小。
编写程序,探究在你的标准库实现中,vector 是如何增长的。
解答:
- #include <vector>
- #include <iostream>
- using namespace std;
-
- int main()
- {
- vector<int> vec{ 1,2,3,4,5 };
- cout << "size: " << vec.size() << endl;
- cout << "capacity: " << vec.capacity() << endl;
- cout << "====================" << endl;
- vec.push_back(6);
- cout << "size: " << vec.size() << endl;
- cout << "capacity: " << vec.capacity() << endl;
- cout << "====================" << endl;
- vec.push_back(7);
- cout << "size: " << vec.size() << endl;
- cout << "capacity: " << vec.capacity() << endl;
- cout << "====================" << endl;
- vec.push_back(8);
- cout << "size: " << vec.size() << endl;
- cout << "capacity: " << vec.capacity() << endl;
- cout << "====================" << endl;
- vec.push_back(9);
- cout << "size: " << vec.size() << endl;
- cout << "capacity: " << vec.capacity() << endl;
- cout << "====================" << endl;
- vec.push_back(10);
- cout << "size: " << vec.size() << endl;
- cout << "capacity: " << vec.capacity() << endl;
- cout << "====================" << endl;
- vec.push_back(11);
- cout << "size: " << vec.size() << endl;
- cout << "capacity: " << vec.capacity() << endl;
- system("pause");
- return 0;
- }
vector<string> svec;
svec.reserve(1024);
string word;
while(cin>>word)
svec.push_back(word);
svec.resize(svec.size()+svec.size()/2);
解答:
创建了一个容器 svec,用 reserve 函数设置分配给容器能容纳 1024 个元素的内存空间, 输入字符串并将字符串加入到容器中,调用 resize 函数调整容器的大小。
如果上一题中的程序读入了 256 个词,在 resize 之后容器的 capacity 可能是多少?如果读入了 512 个、1000 个或 1048 个单词呢?
解答:
number of word | resize | capacity |
256 | 384 | 1024 (根据 reserve(1024)) |
512 | 768 | 1024 |
1000 | 1500 | 2000 (>=1500) |
1048 | 1572 | 2000 (>=1572) |
编写程序,从一个 vector<char> 初始化一个 string。
解答:
- #include <vector>
- #include <string>
- #include <iostream>
- using namespace std;
-
- int main()
- {
- vector<char> vec{ 'h','e','l','l','o' };
- string str(vec.begin(), vec.end());
- cout << str << endl;
- system("pause");
- return 0;
- }
假定你希望每次读取一个字符存入一个 string 中,而且知道最少需要读取 100 个字符,应该如何提高程序的性能?
解答:
由于给容器重新分配内存是一个很耗时的工作,因此在知道至少需要 100 个字符后,可以先调用 reserve() 函数事先确定内存大小,可以提高程序的性能。
编写一个函数,接受三个 string 参数 s、oldVal 和 newVal。使用迭代器及 insert 和 erase 函数将 s 中所有 oldVal 替换为 newVal。测试你的程序,用它替换通用的简写形式,如 “tho” 替换为 “though”,将 “thru” 替换为 “through”。
解答:
- #include <string>
- #include <iostream>
- using namespace std;
-
- void func(string &s, const string &oldVal, const string &newVal)
- {
- auto iter = s.begin();
- while (distance(iter, s.end()) >= distance(oldVal.begin(), oldVal.end()))
- {
- if (string{ iter,iter + oldVal.size() } == oldVal)
- {
- iter = s.erase(iter, iter + oldVal.size()); //先将 oldVal 删除
- iter = s.insert(iter, newVal.cbegin(), newVal.cend()); //在将 newVal 插入
- advance(iter, newVal.size()); //将迭代器移动到新插入的字符串的后一个位置
- }
- else
- {
- iter++;
- }
- }
- }
-
- int main()
- {
- string s{ "To drive straight thru is a foolish, tho courageous act." };
- cout << "====================================================================" << endl;
- cout << s << endl;
- func(s, "tho", "though");
- func(s, "thru", "through");
- cout << s << endl;
- system("pause");
- return 0;
- }
重写上一题的函数,这次使用一个下标和 replace。
解答:
- #include <string>
- #include <iostream>
- using namespace std;
-
- void func(string &s, const string &oldVal, const string &newVal)
- {
- for (string::size_type i = 0; i != s.size(); ++i)
- {
- if (s.substr(i, oldVal.size()) == oldVal) //substr 返回第 i 位置的 oldVal.size() 个字符的拷贝
- {
- s.replace(i, oldVal.size(), newVal);
- i += newVal.size()-1; //指向插入字符串的倒数第二个字符,避免以新插入字符开始的字符串漏掉
- }
- }
- }
-
- int main()
- {
- string s{ "To drive straight thru is a foolish, tho courageous act." };
- cout << "================================================================" << endl;
- cout << s << endl;
- func(s, "tho", "though");
- func(s, "thru", "through");
- cout << s << endl;
-
- string s2{ "HelloloWorld" };
- cout << s2 << endl;
- func(s2, "lo", "la");
- cout << s2 << endl;
- system("pause");
- return 0;
- }
编写一个函数,接受一个表示名字的 string 参数和两个分别表示前缀(如 “Mr.” 或 “Ms”)和后缀(如 “Jr.” 或 “III”)的字符串。使用迭代器及 insert 和 append 函数将前缀和后缀添加到给定名字中,将生成的新 string 返回。
解答:
- #include <string>
- #include <iostream>
- using namespace std;
-
- void func(string &name, const string &pre, const string &suf)
- {
- name.insert(name.begin(), pre.begin(), pre.end());
- name.append(suf); //只能尾部插入
- }
-
- int main()
- {
- string name{ "Mike" };
- cout << name << endl;
- func(name, "Mr.", ".xx");
- cout << name << endl;
- system("pause");
- return 0;
- }
重写上一题的函数,这次使用尾置和长度来管理 string,并只使用 insert。
解答:
- #include <string>
- #include <iostream>
- using namespace std;
-
- void func(string &name, const string &pre, const string &suf)
- {
- name.insert(0, pre);
- name.insert(name.size(), suf);
- }
-
- int main()
- {
- string name{ "Mike" };
- cout << name << endl;
- func(name, "Mr.", ".xx");
- cout << name << endl;
- system("pause");
- return 0;
- }
编写程序,首先查找 string “ab2c3d7R4E6” 中的每个数字字符,然后查找其中的,每个字母字符。编写两个版本的程序,第一个要使用 find_first_of,第二个要使用 find_first_not_of。
解答:
- #include <string>
- #include <iostream>
- using namespace std;
-
- int main()
- {
- string str{ "ab2c3d7R4E6" };
- string numbers{ "0123456789" };
- string characters{ "abcdefghijklmnopqrstuvwxyzABCDEFGHIGKLMNOPQRSTUVWXYZ" };
- cout << "string: " << str << endl;
- cout << "=============================================" << endl;
- for (string::size_type pos = 0; (pos = str.find_first_of(numbers, pos))!=string::npos; ++pos)
- {
- cout << "found number at index: " << pos << ". element is: " << str[pos] << endl;
- }
- cout << "=============================================" << endl;
- for (string::size_type pos = 0; (pos = str.find_first_of(characters, pos))!=string::npos; ++pos)
- {
- cout << "found character at index: " << pos << ". element is: " << str[pos] << endl;
- }
- system("pause");
- return 0;
- }
调用函数 find_first_of()
调用函数 find_first_not_of()
- #include <string>
- #include <iostream>
- using namespace std;
-
- int main()
- {
- string str{ "ab2c3d7R4E6" };
- string numbers{ "0123456789" };
- string characters{ "abcdefghijklmnopqrstuvwxyzABCDEFGHIGKLMNOPQRSTUVWXYZ" };
- cout << "string: " << str << endl;
- cout << "=============================================" << endl;
- for (string::size_type pos = 0; (pos = str.find_first_not_of(characters, pos)) != string::npos; ++pos)
- {
- cout << "found number at index: " << pos << ". element is: " << str[pos] << endl;
- }
- cout << "=============================================" << endl;
- for (string::size_type pos = 0; (pos = str.find_first_not_of(numbers, pos)) != string::npos; ++pos)
- {
- cout << "found character at index: " << pos << ". element is: " << str[pos] << endl;
- }
- system("pause");
- return 0;
- }
假定 name 和 numbers 的定义如 325 页所示, numbers.find(name) 返回什么?
解答:
string::npos
如果一个字母延伸到中线之上,如 d 或 f,则称其有上出头部分(ascender)。如果一个字母延伸到下中线之下,如 p 或 g,则称有下出头部分(descender)。编写程序,读入一个单词文件,输出最长的既不包含上出头部分,也不包含下出头部分的单词。
解答:
- #include <iostream>
- #include <string>
- using namespace std;
-
- int main()
- {
- string str;
- string long_word;
- string lookTable{ "aceimnorsuvwxz" };
- while (cin >> str)
- {
- // 判断条件第一个不在lookTable中的字符不存在,且长度最长
- if (str.find_first_of(lookTable) != string::npos && str.size() > long_word.size())
- long_word = str;
- }
- cout << "the longest word: " << long_word << endl;
- system("pause");
- return 0;
- }
编写程序处理一个 vector<string>,其元素都表示整型值。计算 vector 中所有元素之和。修改程序,使之计算表示浮点值的 string 之和。
解答:
- #include <iostream>
- #include <string>
- #include <vector>
- using namespace std;
-
- int sumInt(vector<string> str)
- {
- int sum = 0;
- for (auto &c : str)
- sum += stoi(c);
- return sum;
- }
-
- float sumFloat(vector<string> str)
- {
- float sum = 0.0;
- for (auto &c : str)
- sum += stof(c);
- return sum;
- }
-
- int main()
- {
- vector<string> stri{ "1","2","3","4","5" };
- vector<string> strf{ "1.1","2.2","3.3","4.4","5.5"};
- cout << "=========================" << endl;
- for (auto &c : stri)
- cout << c << " ";
- cout << endl;
- cout << "sum of int: " << sumInt(stri) << endl;
- cout << "=========================" << endl;
- for (auto &c : strf)
- cout << c << " ";
- cout << endl;
- cout << "sum of float: " << sumFloat(strf) << endl;
- system("pause");
- return 0;
- }
设计一个类,它有三个 unsigned 成员,分别表示年、月和日。为其编写构造函数,接受一个表示日期的 string 参数。你的构造函数应该能处理不同数据格式,如 January 1, 1900、 1/1/1900、 Jan 1 1900等。
解答:
Date.h 文件如下:
- #ifndef DATE_H
- #define DATE_H
-
- #include <string>
- #include <iostream>
- #include <array>
- using namespace std;
- class Date
- {
- public:
- explicit Date(const string &str = "");
- void printf();
-
- unsigned year = 1900;
- unsigned month = 1;
- unsigned day = 1;
-
- private:
- array<string, 12> month_names {"Jan", "Feb", "Mar", "Apr", "May",
- "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"};
-
- unsigned MonthFromName(const string &str);
- };
-
- Date::Date(const string &str)
- {
- if (str.empty())
- return;
- string deli{ " ,/" };
- auto month_day_del_pos = str.find_first_of(deli);
- /*if (month_day_del_pos == string::npos)
- throw invalid_argument("This fomat is not supported now! ");*/
- month = MonthFromName(str.substr(0, month_day_del_pos));
-
- auto day_year_del_pos = str.find_first_of(deli, month_day_del_pos + 1);
- auto day_len = day_year_del_pos - month_day_del_pos - 1;
- day = std::stoi(str.substr(month_day_del_pos + 1, day_len));
- year = std::stoi(str.substr(day_year_del_pos + 1));
- }
-
- void Date::printf()
- {
- cout << year << "-" << month << "-" << day << endl;
- }
-
- unsigned Date::MonthFromName(const string &str)
- {
- if (str.empty())
- return 0;
- if (isdigit(str[0]))
- return stoi(str);
- for (size_t i = 0; i != 12; ++i)
- {
- if (str.find(month_names[i]) != string::npos)
- return i + 1;
- }
- return 0;
- }
-
- #endif //DATE_H
Date.cpp 文件如下:
- #include "Date.h"
-
- int main()
- {
- auto date1 = Date();
- date1.printf();
-
- auto date2 = Date("January 1, 1900");
- date2.printf();
-
- auto date3 = Date("1/1/1900");
- date3.printf();
-
- auto date4 = Date("Jan 1 1900");
- date4.printf();
-
- system("pause");
- return 0;
- }
使用 stack 处理括号化的表达式。当你看到一个左括号,将其记录下来。当你在一个左括号之后看到一个右括号,从 stack 中 pop 对象,直至遇到左括号,将左括号也一起弹出栈。然后将一个值(括号内的运算结果)push 到栈中,表示一个括号化的(子)表达式已经处理完毕,被其运算结果所代替。
解答:
注意 stack 的操作顺序是先进后出。
- #include <stack>
- #include <iostream>
- #include <string>
- using namespace std;
-
- int main()
- {
- string str;
- string answer{ " * " }; //用 * 符号代替括号内内容的和
- cout << "please input your words: " << endl;
- getline(cin, str);
- stack<char> stk;
- int count = 0;
- for (auto &c : str)
- {
- stk.push(c);
- if (c == '(')
- count += 1; //等价于记录的左括号数
- if (count && c == ')')
- {
- while (stk.top() != '(')
- {
- stk.pop(); //若没有遇到左括号则一直弹出
- }
- stk.pop(); //将对应的左括号弹出
- for (auto &s : answer)
- stk.push(s); //将弹出部分的和,这里用 replace 代替压入栈
- --count; //弹出一对括号,计数器减一
- }
- }
-
- string output;
- while (!stk.empty())
- {
- char ch = stk.top();
- output.insert(output.begin(), ch);
- stk.pop();
- }
- cout << output << endl;
-
- system("pause");
- return 0;
- }
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。