C++ Primer 【第四版】第三章 标准库类型

来源:互联网 发布:宋仲基宋慧乔婚礼知乎 编辑:程序博客网 时间:2024/05/01 13:52


习题3.1

用适当的using声明,而不用std::前缀,访问标准库中的名字,重新编写2.3节的程序,计算一给定数的给定次幂的结果。

【解答】

#include<iostream>

usingstd::cin;

usingstd::cout;

intmain()

{

//局部对象

intbase, exponent;

longresult=1;

//读入底数和指数

cout<< "Enter base and exponent:" << endl;

cin>> base >> exponent;

if(exponent < 0) {

cout<< "Exponent can't be smaller than 0" << endl;

return-1;

}

if(exponent > 0) {

//计算底数的指数次方

for(int cnt = 1; cnt <= exponent; ++cnt)

result*= base;

}

cout<< base

<<" raised to the power of "

<<exponent << ": "

<<result << endl;

return0;

}

 

习题3.2

什么是默认构造函数?

【解答】

默认构造函数(default constructor)就是在没有显式提供初始化式时调用的构造函数。它由不带参数的构造函数,或者为所有形参提供默认实参的构造函数定义。如果定义某个类的变量时没有提供初始化式,就会使用默认构造函数。如果用户定义的类中没有显式定义任何构造函数,编译器就会自动为该类生成默认构造函数,称为合成的默认构造函数(synthesized default constructor)。

 

习题3.3

列举出三种初始化string对象的方法。

【解答】

(1)不带初始化式,使用默认构造函数初始化string对象。

(2)使用一个已存在的string对象作为初始化式,将新创建的string 对象初始化为已存在对象的副本。

(3)使用字符串字面值作为初始化式,将新创建的string对象初始化为字符串字面值的副本。

 

习题3.4

ss2的值分别是什么?

strings;

intmain() {

strings2;

}

【解答】

ss2的值均为空字符串。

 

习题3.5

编写程序实现从标准输入每次读入一行文本。然后改写程序,每次读入一个单

词。

【解答】

//从标准输入每次读入一行文本

#include<iostream>

#include<string>

usingnamespace std;

intmain()

{

stringline;

//一次读入一行,直至遇见文件结束符

while(getline(cin, line))

cout<< line << endl; //输出相应行以进行验证

return0;

}

修改后程序如下:

//从标准输入每次读入一个单词

#include<iostream>

#include<string>

usingnamespace std;

intmain()

{

stringword;

//一次读入一个单词,直至遇见文件结束符

while(cin >> word)

cout<< word << endl; //输出相应单词以进行验证

return0;

}

注意,一般而言,应该尽量避免使用using指示而使用using 声明(参见17.2.4

节),因为如果应用程序中使用了多个库,使用using指示引入这些库中定义

的名字空间,容易导致名字冲突。但本书中的程序都只使用了标准库,没有使

用其他库。使用using指示引入名字空间std 中定义的所有名字不会发生名字

冲突。因此为了使得代码更为简洁以节省篇幅,本书的许多代码中都使用了

using指示using namespace std;来引入名字空间std。另外,本题中并未要求

输出,加入输出是为了更清楚地表示读入的结果。本书后面部分有些地方与此

类似处理,不再赘述。

习题3.6

解释string类型的输入操作符和getline 函数分别如何处理空白字符。

【解答】

string类型的输入操作符对空白字符的处理:读取并忽略有效字符(非空白字

符)之前所有的空白字符,然后读取字符直至再次遇到空白字符,读取终止(该

空白字符仍留在输入流中)。

getline函数对空白字符的处理:不忽略行开头的空白字符,读取字符直至遇到

换行符,读取终止并丢弃换行符(换行符从输入流中去掉但并不存储在string

对象中)。

习题3.7

编一个程序读入两个string对象,测试它们是否相等。若不相等,则指出两个

中哪个较大。接着,改写程序测试它们的长度是否相等,若不相等,则指出两

个中哪个较长。

【解答】

测试两个string对象是否相等的程序:

#include<iostream>

#include<string>

usingnamespace std;

intmain()

{

strings1, s2;

//读入两个string对象

cout<< "Enter two strings:" << endl;

C++Primer4版)习题解答

41

cin>> s1 >> s2;

//测试两个string对象是否相等

if(s1 == s2)

cout<< "They are equal." << endl;

elseif (s1 > s2)

cout<< "\"" << s1 << "\" is biggerthan"

<<" \"" << s2 << "\"" << endl;

else

cout<< "\"" << s2 << "\" is biggerthan"

<<" \"" << s1 << "\"" << endl;

return0;

}

测试两个string对象的长度是否相等的程序:

#include<iostream>

#include<string>

usingnamespace std;

intmain()

{

strings1, s2;

//读入两个string对象

cout<< "Enter two strings:" << endl;

cin>> s1 >> s2;

//比较两个string对象的长度

string::size_typelen1, len2;

C++Primer4版)习题解答

42

len1= s1.size();

len2= s2.size();

if(len1 == len2)

cout<< "They have same length." << endl;

elseif (len1 > len2)

cout<< "\"" << s1 << "\" is longerthan"

<<" \"" << s2 << "\"" << endl;

else

cout<< "\"" << s2 << "\" is longerthan"

<<" \"" << s1 << "\"" << endl;

return0;

}

习题3.8

编一个程序,从标准输入读取多个string对象,把它们连接起来存放到一个更

大的string对象中,并输出连接后的string 对象。接着,改写程序,将连接

后相邻string对象以空格隔开。

【解答】

#include<iostream>

#include<string>

usingnamespace std;

intmain()

{

stringresult_str, str;

//读入多个string对象并进行连接

C++Primer4版)习题解答

43

cout<< "Enter strings(Ctrl+Z to end):" << endl;

while(cin>>str)

result_str= result_str + str;

//输出连接后的string对象

cout<< "String equal to the concatenation of these strings is:"

<<endl << result_str << endl;

return0;

}

改写后的程序:

#include<iostream>

#include<string>

usingnamespace std;

intmain()

{

stringresult_str, str;

//读入多个string对象并进行连接

cout<< "Enter strings(Ctrl+Z to end):" << endl;

cin>> result_str;//读入第一个string对象,放到结果对象中

while(cin>>str)

result_str= result_str + ' ' + str;

//输出连接后的string对象

cout<< "String equal to the concatenation of these strings is:"

<<endl << result_str << endl;

return0;

C++Primer4版)习题解答

44

}

习题3.9

下列程序实现什么功能?实现合法吗?如果不合法,说明理由。

strings;

cout<< s[0] << endl;

【解答】

该程序段输出string对象s 所对应字符串的第一个字符。

实现不合法。因为s是一个空字符串,其长度为0,因此s[0]是无效的。

注意,在一些编译器(如Microsoft Visual C++ .NET 2003)的实现中,该

程序段并不出现编译错误。

习题3.10

编一个程序,从string对象中去掉标点符号。要求输入到程序的字符串必须含

有标点符号,输出结果则是去掉标点符号后的string对象。

【解答】

#include<iostream>

#include<string>

#include<cctype>

usingnamespace std;

intmain()

{

strings, result_str;

boolhas_punct = false;//用于标记字符串中有无标点

charch;

//输入字符串

C++Primer4版)习题解答

45

cout<< "Enter a string:" << endl;

getline(cin,s);

//处理字符串:去掉其中的标点

for(string::size_type index = 0; index != s.size(); ++index)

{

ch= s[index];

if(ispunct(ch))

has_punct= true;

else

result_str+= ch;

}

if(has_punct)

cout<< "Result:" << endl << result_str <<endl;

else{

cout<< "No punctuation character in the string?!" << endl;

return-1;

}

return0;

}

习题3.11

下面哪些vector定义不正确?

(a)vector< vector<int> > ivec;

(b)vector<string> svec = ivec ;

(c)vector<string> svec(10,"null");

C++Primer4版)习题解答

46

【解答】

(b)不正确。因为svec定义为保存string对象的vector 对象,而ivec

保存vector <int>对象的vector对象(即ivec vector vector),二者

的元素类型不同,所以不能用ivec来初始化svec

习题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)元素个数为0

(b)元素个数为10,各元素的值均为0

(c)元素个数为10,各元素的值均为42

(d)元素个数为0

(e)元素个数为10,各元素的值均为空字符串。

(f)元素个数为10,各元素的值均为"hello"

习题3.13

读一组整数到vector对象,计算并输出每对相邻元素的和。如果读入元素个数

为奇数,则提示用户最后一个元素没有求和,并输出其值。然后修改程序:头

尾元素两两配对(第一个和最后一个,第二个和倒数第二个,以此类推),计

算每对元素的和,并输出。

【解答】

//读一组整数到vector对象,计算并输出每对相邻元素的和

C++Primer4版)习题解答

47

#include<iostream>

#include<vector>

usingnamespace std;

intmain()

{

vector<int>ivec;

intival;

//读入数据到vector对象

cout<< "Enter numbers(Ctrl+Z to end):" << endl;

while(cin>>ival)

ivec.push_back(ival);

//计算相邻元素的和并输出

if(ivec.size() == 0) {

cout<< "No element?!" << endl;

return-1;

}

cout<< "Sum of each pair of adjacent elements in the vector:"

<<endl;

for(vector<int>::size_type ix = 0; ix < ivec.size()-1;

ix= ix + 2) {

cout<< ivec[ix] + ivec[ix+1] << "\t";

if( (ix+1) % 6 == 0) //每行输出6个和

cout<< endl;

}

C++Primer4版)习题解答

48

if(ivec.size() % 2 != 0) //提示最后一个元素没有求和

cout<< endl

<<"The last element is not been summed "

<<"and its value is "

<<ivec[ivec.size()-1] << endl;

return0;

}

修改后的程序:

//读一组整数到vector对象,计算首尾配对元素的和并输出

#include<iostream>

#include<vector>

usingnamespace std;

intmain()

{

vector<int>ivec;

intival;

//读入数据到vector对象

cout<< "Enter numbers:" << endl;

while(cin>>ival)

ivec.push_back(ival);

//计算首尾配对元素的和并输出

if(ivec.size() == 0) {

cout<< "No element?!" << endl;

return-1;

C++Primer4版)习题解答

49

}

cout<< "Sum of each pair of counterpart elements in the vector:"

<<endl;

vector<int>::size_typecnt = 0;

for(vector<int>::size_type first = 0, last = ivec.size() - 1;

first< last; ++first, --last) {

cout<< ivec[first] + ivec[last] << "\t";

++cnt;

if( cnt % 6 == 0) //每行输出6个和

cout<< endl;

}

if(first == last) //提示居中元素没有求和

cout<< endl

<<"The center element is not been summed "

<<"and its value is "

<<ivec[first] << endl;

return0;

}

习题3.14

读入一段文本到vector对象,每个单词存储为vector 中的一个元素。把vector

对象中每个单词转化为大写字母。输出vector对象中转化后的元素,每8 个单

词为一行输出。

【解答】

//读入一段文本到vector对象,每个单词存储为vector 中的一个元素。

C++Primer4版)习题解答

50

//vector对象中每个单词转化为大写字母。

//输出vector对象中转化后的元素,每8个单词为一行输出

#include<iostream>

#include<string>

#include<vector>

#include<cctype>

usingnamespace std;

intmain()

{

vector<string>svec;

stringstr;

//读入文本到vector对象

cout<< "Enter text(Ctrl+Z to end):" << endl;

while(cin>>str)

svec.push_back(str);

//vector对象中每个单词转化为大写字母,并输出

if(svec.size() == 0) {

cout<< "No string?!" << endl;

return-1;

}

cout<< "Transformed elements from the vector:"

<<endl;

for(vector<string>::size_type ix = 0; ix != svec.size(); ++ix) {

C++Primer4版)习题解答

51

for(string::size_type index = 0; index != svec[ix].size();

++index)

if(islower(svec[ix][index]))

//单词中下标为index的字符为小写字母

svec[ix][index]= toupper(svec[ix][index]);

cout<< svec[ix] << " ";

if((ix + 1) % 8 == 0)//8个单词为一行输出

cout<< endl;

}

return0;

}

习题3.15

下面程序合法吗?如果不合法,如何更正?

vector<int>ivec;

ivec[0]= 42;

【解答】

不合法。因为ivec是空的vector 对象,其中不含任何元素,而下标操作只

能用于获取已存在的元素。

更正:将赋值语句改为语句ivec.push_back(42);

习题3.16

列出三种定义vector对象的方法,给定10 个元素,每个元素值为42。指出是

否还有更好的实现方法,并说明为什么。

【解答】

方法一:

vector<int>ivec(10, 42);

C++Primer4版)习题解答

52

方法二:

vector<int>ivec(10);

for(ix = 0; ix < 10; ++ix)

ivec[ix]= 42;

方法三:

vector<int>ivec(10);

for(vector<int>::iterator iter = ivec.begin();

iter!= ivec.end(); ++iter)

*iter= 42;

方法四:

vector<int>ivec;

for(cnt = 1; cnt <= 10; ++cnt)

ivec.push_back(42);

方法五:

vector<int>ivec;

vector<int>::iteratoriter = ivec.end();

for(int i = 0; i != 10; ++i) {

ivec.insert(iter,42);

iter= ivec.end();

}

各种方法都可达到目的,也许最后两种方法更好一些。它们使用标准库中定义

的容器操作在容器中增添元素,无需在定义vector对象时指定容器的大小,比

较灵活而且不容易出错。

习题3.17

C++Primer4版)习题解答

53

重做3.3.2节的习题,用迭代器而不是下标操作来访问vector 中的元素。

【解答】

重做习题3.13如下:

//读一组整数到vector对象,计算并输出每对相邻元素的和

//使用迭代器访问vector中的元素

#include<iostream>

#include<vector>

usingnamespace std;

intmain()

{

vector<int>ivec;

intival;

//读入数据到vector对象

cout<< "Enter numbers(Ctrl+Z to end):" << endl;

while(cin>>ival)

ivec.push_back(ival);

//计算相邻元素的和并输出

if(ivec.size() == 0) {

cout<< "No element?!" << endl;

return-1;

}

cout<< "Sum of each pair of adjacent elements in the vector:"

<<endl;

vector<int>::size_typecnt = 0;

C++Primer4版)习题解答

54

for(vector<int>::iterator iter = ivec.begin();

iter< ivec.end()-1;

iter= iter + 2) {

cout<< *iter + *(iter+1) << "\t";

++cnt;

if( cnt % 6 == 0) //每行输出6个和

cout<< endl;

}

if(ivec.size() % 2 != 0) //提示最后一个元素没有求和

cout<< endl

<<"The last element is not been summed "

<<"and its value is "

<<*(ivec.end()-1) << endl;

return0;

}

//读一组整数到vector对象,计算首尾配对元素的和并输出

//使用迭代器访问vector中的元素

#include<iostream>

#include<vector>

usingnamespace std;

intmain()

{

vector<int>ivec;

intival;

C++Primer4版)习题解答

55

//读入数据到vector对象

cout<< "Enter numbers(Ctrl+Z to end):" << endl;

while(cin>>ival)

ivec.push_back(ival);

//计算首尾配对元素的和并输出

if(ivec.size() == 0) {

cout<< "No element?!" << endl;

return-1;

}

cout<< "Sum of each pair of counterpart elements in the vector:"

<<endl;

vector<int>::size_typecnt=0;

for(vector<int>::iterator first = ivec.begin(),

last= ivec.end() - 1;

first< last;

++first,--last) {

cout<< *first + *last << "\t";

++cnt;

if( cnt % 6 == 0) //每行输出6个和

cout<< endl;

}

if(first == last) //提示居中元素没有求和

cout<< endl

<<"The center element is not been summed "

C++Primer4版)习题解答

56

<<"and its value is "

<<*first << endl;

return0;

}

重做习题3.14如下:

//读入一段文本到vector对象,每个单词存储为vector 中的一个元素。

//vector对象中每个单词转化为大写字母。

//输出vector对象中转化后的元素,每8个单词为一行输出。

//使用迭代器访问vector中的元素

#include<iostream>

#include<string>

#include<vector>

#include<cctype>

usingnamespace std;

intmain()

{

vector<string>svec;

stringstr;

//读入文本到vector对象

cout<< "Enter text(Ctrl+Z to end):" << endl;

while(cin>>str)

svec.push_back(str);

//vector对象中每个单词转化为大写字母,并输出

if(svec.size() == 0) {

C++Primer4版)习题解答

57

cout<< "No string?!" << endl;

return-1;

}

cout<< "Transformed elements from the vector:"

<<endl;

vector<string>::size_typecnt = 0;

for(vector<string>::iterator iter = svec.begin();

iter!= svec.end(); ++iter) {

for(string::size_type index = 0; index != (*iter).size();

++index)

if(islower((*iter)[index]))

//单词中下标为index的字符为小写字母

(*iter)[index]= toupper((*iter)[index]);

cout<< *iter << " ";

++cnt;

if(cnt % 8 == 0)//8个单词为一行输出

cout<< endl;

}

return0;

}

习题3.18

编写程序来创建有10个元素的vector 对象。用迭代器把每个元素值改为当前

值的2倍。

【解答】

C++Primer4版)习题解答

58

//创建有10个元素的vector 对象,

//然后使用迭代器将每个元素值改为当前值的2

#include<iostream>

#include<vector>

usingnamespace std;

intmain()

{

vector<int>ivec(10, 20);//每个元素的值均为20

//将每个元素值改为当前值的2

for(vector<int>::iterator iter = ivec.begin();

iter!= ivec.end(); ++iter)

*iter= (*iter)*2;

return0;

}

习题3.19

验证习题3.18的程序,输出vector 的所有元素。

【解答】

//创建有10个元素的vector 对象,

//然后使用迭代器将每个元素值改为当前值的2倍并输出

#include<iostream>

#include<vector>

usingnamespace std;

intmain()

{

C++Primer4版)习题解答

59

vector<int>ivec(10, 20);//每个元素的值均为20

//将每个元素值改为当前值的2倍并输出

for(vector<int>::iterator iter = ivec.begin();

iter!= ivec.end(); ++iter) {

*iter= (*iter)*2;

cout<< *iter << " ";

}

return0;

}

习题3.20

解释一下在上几个习题的程序实现中你用了哪种迭代器,并说明原因。

【解答】

上述几个习题的程序实现中使用了类型分别为vector<int>::iterator

vector<string>::iterator的迭代器,通过这些迭代器分别访问元素类型为

intstringvector 对象中的元素。

习题3.21

何时使用const迭代器?又在何时使用const_iterator?解释两者的区别。

【解答】

const迭代器是迭代器常量,该迭代器本身的值不能修改,即该迭代器在定义时

需要初始化,而且初始化之后,不能再指向其他元素。若需要指向固定元素的

迭代器,则可以使用const迭代器。

const_iterator是一种迭代器类型,对这种类型的迭代器解引用会得到一个指

const对象的引用,即通过这种迭代器访问到的对象是常量。该对象不能修

改,因此,const_iterator类型只能用于读取容器内的元素,不能修改元素的

值。若只需遍历容器中的元素而无需修改它们,则可以使用const_iterator

习题3.22

如果采用下面的方法来计算mid会产生什么结果?

C++Primer4版)习题解答

60

vector<int>::iteratormid = (vi.begin() + vi.end())/2;

【解答】

将两个迭代器相加的操作是未定义的,因此用这种方法计算mid会出现编译错

误。

习题3.23

解释下面每个bitset对象包含的位模式:

(a)bitset<64> bitvec(32);

(b)bitset<32> bv(1010101);

(c)string bstr; cin >> bstr; bitset<8> bv(bstr);

【解答】

(a)bitvec64个二进制位,(位编号从0 开始)第5位置为1,其余位置均

0

(b)bv32个二进制位,(位编号从0 开始)第0245781113

1416171819位置为1,其余位置均为0。因为十进制数1010101对应的

二进制数为000000000000011110110100110110101

(c)bv8个二进制位,(位编号从0 开始)用读入的字符串的从右至左的8

个字符对bv0~7 位进行初始化。

习题3.24

考虑这样的序列1,2,3,5,8,13,21,并初始化一个将该序列数字所对应的位置设

置为1bitset<32>对象。然后换个方法,给定一个空的bitset对象,编写一

小段程序把相应的数位设置为1

【解答】

bitset<32>对象的初始化:

bitset<32>bv(0x20212e)

方法二:

bitset<32>bv;

intx = 0, y = 1, z;

C++Primer4版)习题解答

61

z= x + y;

while(z <= 21) {

bv.set(z);

x= y;

y= z;

z= x + y;

}

注意,设置为1的数位的位编号符合斐波那契数列的规律。

0 0
原创粉丝点击