习题 3.1 用适当的using声明,而不用std::前缀,访问标准库中名字的方法,重新编写2.3节的程序,计算一给定数的给定次幂的结果。
解答:修改习题2.11的程序如下:(比较和2.11的区别)
#include <iostream>
using std::cout;
using std::cin;
using std::endl;
int main()
{
cout << "Please enter two numbers:/n"
" (the first nuber as a base and the second number as a exponent)" << endl;
int base;
int exponent;
cin >> base >> exponent;
int result = 1;
for(int cnt = 0; cnt != exponent; ++cnt){
result *= base;
}
cout << "The result of " << base << " of " << exponent << " power is " << result << endl;
return 0;
}
习题 3.2 什么是默认构造函数?
解答:构造函数是类的一个特殊成员函数,定义如果初始化该类的对象。当没有明确指定对象初始化式时,系统将使用默认构造函数。
习题 3.3 列出三种初始化string对象的方法。
解答:
string s2(s1); //将s2初始化为s1的一个副本
string s3(“value”);//将s3初始化为一个字符串字面值常量
string s4(n, ‘c’); //将s4初始化为字符’c’的n个副本
习题 3.4 s和s2的值分别是什么?
string s;
int main(){
string s2;
}
解答:当没有显示初始化string对象时,不管该对象是定义在函数体内还是定义在函数体外,都将调用string的默认构造函数,初始化string对象为空串。所以s和s2的值都为空。
习题 3.5 编写程序实现从标准输入每次读入一行文本。然后改写程序,每次读入一个单词。
解答:
//每次读入一行
string line;
while(getline(cin, line)){
cout << line << endl;
}
改写程序,每次读入一个单词:
string word;
while( cin >> word){
cout << word << endl;
}
习题 3.6 解释string类型的输入操作符和getline函数分别如何处理空白字符。
解答:string类型的输入操作符读取并忽略开头所有的空白字符,读取字符直到再次遇到空白字符。getline并不忽略开头的换行符,只要遇到换行符,它就停止读入并返回。
习题 3.7 编一个程序读入两个string对象,测试它们是否相等。若不相等,则指出两个中哪个较大。接着,改写程序测试它们的长度是否相等,若不相等指出哪个较长。
解答:判断两个中的较大者
string s1,s2;
cout << "Please enter two words:" << endl;
cin >> s1 >> s2;
if(s1 == s2){
cout << "They are the same words." << endl;
}
else if( s1 > s2 ){
cout << s1 << " is greater than " << s2 << endl;
}
else{
cout << s2 << " is greater than " << s1 << endl;
}
判断两者中的较长者
string s1,s2;
cout << "Please enter two words:" << endl;
cin >> s1 >> s2;
if(s1.size() == s2.size()){
cout << "They have the same long." << endl;
}
else if( s1.size() > s2.size() ){
cout << s1 << " is longer than " << s2 << endl;
}
else{
cout << s2 << " is longer than " << s1 << endl;
}
习题 3.8 编一个程序,从标准输入读取多个string对象,把它们连接起来放到一个更大的string对象中。并输出连接后的string对象。接着,改写程序,将连接后相邻string对象以空格隔开。
解答:
没有空格隔开的string:
string s,s1;
cout << "Please enter some words:" << endl;
while( cin >> s1 ){
s += s1;
}
cout << s << endl;
将相邻string对象以空格隔开:
string s,s1;
cout << "Please enter some words:" << endl;
while( cin >> s1 ){
s += s1 + " ";
}
cout << s << endl;
习题 3.9 下列程序实现什么功能?实现合法吗?如果不合法,说明理由。
string s;
cout << s[0] << endl;
解答:这个程序是合法的,输出空字符’/0’。
习题 3.10 编一个程序,从string对象中去掉标点符号。要求输入到程序的字符串必须含有标点符号,输出结果则是去掉标点符号后的string对象。
解答:
string line;
cout << "Please input some words(include punctuation):" << endl;
getline( cin, line );
string result;
for( string::size_type ix = 0; ix != line.size(); ++ ix){
if(!ispunct(line[ix])){
result += line[ix];
}
}
cout << result << endl;
注意头文件要包含 cctype
习题 3.11 下面哪些vector定义不正确?
(a) Vector< vector<int> > ivec;
(b) Vector<string> svec = ivec;
(c) Vector<string> svec(10, “null”);
解答:
(a) 正确的。定义了一个容器的容器。
(b) 错误。ivec不是string类型的容器,不同类型的容器之间不能复制。
(c) 正确。定义了包含10个字符串”null”的容器。
习题 3.12 下列每个vector对象中元素个数是多少?各元素的值是什么?
(a) vector<int> ivec1;
(b) vector<int> ivec2(10);
(c) vector<int> ivec3(10, 42);
(d) vector<string> svec1;
(e) vector<string> svec2(10);
(f) vector<string> svec3(10,”hello”);
解答:
(a) ivec1中没有元素
(b) ivec2中有10个元素,每个元素的值都是0
(c) ivce3中有10个元素,每个元素的值都是42
(d) svec1中没有元素
(e) svec2中有10个元素,第个元素都是空字符串
(f) svec3中有10个元素,每个元素都是字符串”hello”
习题 3.13 读一组整数到vector对象,计算并输出每对相邻元素的和。如果读入元素个数为奇数,则提示用户最后一个元素没有求和,并输出其值。然后修改程序:头尾元素两两配对(第一个和最后一个,第二个和倒数第二个,以此类推),计算每对元素的和,并输出。
解答:
输出相邻元素的和(下标操作实现)
cout << "Please input some numbers:(press enter as end)" << endl;
int num(0);
vector<int> ivec;
while( cin.peek() != '/n' && cin >> num ){
ivec.push_back(num);
}
cout << "The result:" << endl;
int size(ivec.size());
for( vector<int>::size_type ix = 1; ix < size; ix += 2 ){
cout << ivec[ix - 1] + ivec[ix] << " ";
}
if(size % 2 == 1){
cout << "/nThe last number "
<< ivec[size - 1]
<< " is not in the result." << endl;
}
迭代器实现输出相邻两元素的和:
cout << "Please input some numbers:(press enter as end)" << endl;
int num(0);
vector<int> ivec;
while( cin.peek() != '/n' && cin >> num ){
ivec.push_back(num);
}
cout << "The result:" << endl;
for( vector<int>::const_iterator iter = ivec.begin() + 1;
iter < ivec.end(); iter += 2 ){
cout << *(iter -1) + *iter << " ";
}
if(ivec.size() % 2 == 1){
cout << "/nThe last number "
<< *(ivec.end() - 1)
<< " is not in the result." << endl;
}
修改代码,实现头尾两两配对求和(下标操作实现方法):
cout << "Please input some numbers:(press enter as end)" << endl;
int num(0);
vector<int> ivec;
while( cin.peek() != '/n' && cin >> num ){
ivec.push_back(num);
}
cout << "The result:" << endl;
int size = ivec.size();
for( vector<int>::size_type ix = 0;
!ivec.empty() && ix < size - ix -1; ++ ix ){
cout << ivec[ix] + ivec[size - ix - 1] << " ";
}
if(ivec.size() % 2 == 1){
cout << "/nThe middle number "
<< ivec[size / 2]
<< " is not in the result." << endl;
}
迭代器实现方法:
cout << "Please input some numbers:(press enter as end)" << endl;
int num(0);
vector<int> ivec;
while( cin.peek() != '/n' && cin >> num ){
ivec.push_back(num);
}
cout << "The result:" << endl;
for( vector<int>::const_iterator first = ivec.begin(),second = ivec.end();
!ivec.empty() && second - first > 1; ++ first, -- second ){
cout << *first + *(second - 1)<< " ";
}
if(ivec.size() % 2 == 1){
cout << "/nThe middle number "
<< *(ivec.begin() + ivec.size() / 2)
<< " is not in the result." << endl;
}
习题 3.14 读入一段文本到vector对象,每个单词存储为vector中的一个元素。把vector对象中每个单词转化为大写字母。输出vector对象中转化后的元素,每八个单词为一行输出。
解答:此程序中,注意包含头文件cctype
下标操作实现:
cout << "Please input some words:(press enter as end)" << endl;
string word;
vector<string> svec;
while( cin.peek() != '/n' && cin >> word ){
svec.push_back(word);
}
cout << "The result to upper:" << endl;
for( vector<string>::size_type ix = 0;
ix != svec.size(); ++ ix ){
for( string::size_type i = 0; i != svec[ix].size(); ++ i){
svec[ix][i] = toupper(svec[ix][i]);
}
if(ix != 0 && ix % 8 == 0){
cout << endl;
}
cout << svec[ix] << " ";
}
修改程序,用迭代器实现:
cout << "Please input some words:(press enter as end)" << endl;
string word;
vector<string> svec;
while( cin.peek() != '/n' && cin >> word ){
svec.push_back(word);
}
cout << "The result to upper:" << endl;
for( vector<string>::iterator iter = svec.begin();
iter != svec.end(); ++ iter ){
for( string::iterator i = (*iter).begin(); i != (*iter).end(); ++ i){
*i = toupper(*i);
}
if(iter != svec.begin() && ( iter - svec.begin()) % 8 == 0){
cout << endl;
}
cout << *iter << " ";
}
习题 3.15 下面程序合法吗?如果不合法,如何更正?
vector<int> ivec;
ivec[0] = 42;
解答:这是不合法的,下标操作不添加元素。
习题 3.16 列出三种定义vector对象的方法,给定10个元素,每个元素值为42.指出是否还有更好的实现方法,并说明为什么。
解答:
方法一:
vector<int> ivec;
for(int cnt = 0; cnt != 10; ++ cnt){
ivec.push_back(42);
}
方法二:
vector<int> ivec(10);
for(vector<int>::size_type ix = 0; ix != ivec.size(); ++ ix){
ivec[ix] = 42;
}
方法三:
vector<int> ivec(10, 42);
感觉没有比第三种方法更好的实现方法了。
习题 3.17 重做3.3.2节的习题,用迭代器而不是下标操作来访问vector中的元素。
解答:见上节的习题解答。
习题 3.18 编写程序来创建有10个元素的vector对象。用迭代器把每个元素值改为当前值的2倍。
解答:
vector<int> ivec(10, 42);
for(vector<int>::iterator iter = ivec.begin(); iter != ivec.end(); ++ iter){
*iter *= 2;
cout << *iter << endl;
}
习题 3.19 验证习题3.18的程序,输出vector的所有元素。
解答:见习题3.18.
习题 3.20 解释一下在上几题的程序实现中你用了哪种迭代器,并说明原因。
解答:通过上几题的程序可以看到,使用的都是普通的iterator,因为要遍历整个容器和改变容器内对象的值。如果仅仅是遍历容器,可以定义为const_iterator。
习题 3.21 何时使用const迭代器的?又在何时使用const_iterator?解释两者的区别。
解答:如果你希望一个迭代器只指向容器内一个特定的元素,就可以把它定义为const迭代器。如果你不想改变一个容器里元素的值,就可以把指向这个容器的迭代器定义成const_iterator。const迭代器在定义的时候就要指定一个对象,而且定义后不可再指向其它对象,不过可以通过const迭代器改变其指向对象的值。const_iterator可以指向任何一个容器对象,但不能通过const_iterator来更改其指向对象的值。
习题 3.22 如果采用下面的方法来计算mid会产生什么结果?
vector<int>::iterator mid = (vi.begin() + vi.end())/2;
解答:会产生编译错误,迭代器并没有定义两个迭代器的+操作。只可以在迭代器对象上加或减去一个整型值,或者是对两个迭代器作“-”操作,得出两个迭代器之间的距离。
习题 3.23 解释下面每个bitset对象包含的位模式:
(a) bitset<64> bitvec(32);
(b) bitset<32> bv(1010101);
(c) string bstr; cin >> bstr; bitset<8> bv(bstr);
解答:
(a) 整型字面值32的64位二进制位的有序集。
(b) 整型字面值1010101的32位二进制位的有序集。
(c) 保存用户输入的二进制字符串的前8位。
习题 3.24 考虑这样的序列1,2,3,5,8,13,21,并初始化一个将该序列数字所对应的位置置为1的bitset<32>对象。然后换个方法,给定一个空的bitset对象,编写一小段程序把相应的数位设置为1。
解答:
直接初始化
string s("1000000010000100101110");
bitset<32> bv(s);
另一种方法:
bitset<32> bv;
int n1(1),n2(2);
bv.set(n1);
while(n2 <= 32){
bv.set(n2);
int temp = n1 + n2;
n1 = n2;
n2 = temp;
}
作为练习,我们用一个容器保存该序列的值,然后再根据容器内元素的值把bitset对象中的相应位置为1:
bitset<32> bv;
vector<int> ivec(1,1);
ivec.push_back(2);
while(( *(ivec.end() - 1) + *(ivec.end() - 2)) <= 32){
ivec.push_back(*(ivec.end() - 1) + *(ivec.end() - 2));
}
for(vector<int>::const_iterator iter = ivec.begin();
iter != ivec.end(); ++ iter){
bv.set(*iter);
}