C++ Primer 课后答案 冷玉倾情完美呈现
第一章 基本语言
1.1查看所用的编译器文档,了解它所使用的文件命名规范。编译并运行本节的main程序。
答:我所使用的是Dev-C++做练习使用,大多数编译器的文件命名规范:头文件 .h,.hpp;源文件:.c,.cc,.cpp,我所使用的Dev-C++是.h,和.cpp。
1.2修改程序使其返回-1.返回值-1通常作为程序运行失败的指示器。然而不同系统,如何报告main函数运行失败也不同。重新编译再次运行程序,看看你的系统图和处理main函数的运行失败指示器。
答:我所用的windows操作系统不报告运行失败信息,因此返回-1,和返回0没有区别,但输入echo %ERRORLEVEL%命令,系统显示返回值为0。
1.3 编写一个程序,在标准输出上打印“Hello,World”。
答:
#include <iostream>
//using namespace std;
int main()
{
std::cout<<"Hello,World"<<std::endl;
system("pause");
return 0;
}
1.4 我们的程序利用内置的加法操作符“+”来产生两个数的和。编写程序,使用乘法操作符“*”产生两个数的积。
答:
#include <iostream>
//using namespace std;
int main()
{
int a=2;
int b=4;
int c=0;
c=a*b;
std::cout<<c<<std::endl;
system("pause");
return 0;
}
1.5 我们的程序使用了一条较长的输出语句,重写程序,使用单独的语句打印每一个操作数。
答:
#include <iostream>
//using namespace std;
int main()
{
int v1=10,v2=100;
//std::cout<<"The sum of "<<v1<<"and"<<v2<<"is"<<v1+v2<<std::endl;
std::cout<<"The sum of ";
std::cout<<v1;
std::cout<<"and";
std::cout<<v2;
std::cout<<"is";
std::cout<<v1+v2;
std::cout<<std::endl;
system("pause");
return 0;
}
1.6届时下面的程序段:
std::cout<<"The sum of "<<v1;
<<"and"<<v2;
<<"is"<<v1+v2
<<std::endl;
这段代码合法吗?如果合法,为什么,如果不合法,又为什么?
答:不合法,因为这段代码是四个单独的语句,除了第一条语句外,其它三条都不合法,因为 “<<” 没有操作符的左操作符,“<<”是标准的输出操作符,接受两个参数,左操作符必须是ostream的类型(输出流类型)。操作符将其右操作数写到左操作数的ostream对象。
(endl操作符,具有换行和刷新缓冲区的功能,通过刷新缓冲区,用户可立即看到写入到流中的输出。)
1.7 编译有不正确嵌套注视的程序。
答:
#include <iostream>
//using namespace std;
int main()
{
int v1=10,v2=100;
//std::cout<<"The sum of "<<v1<<"and"<<v2<<"is"<<v1+v2<<std::endl;
/* std::cout<<"The sum of ";
std::co*/ut<<v1;
std::cout<<"and";
std::cout<<v2;*/*/
std::cout<<"is";
std::cout<<v1+v2;
std::cout<<std::endl;
system("pause");
return 0;
}
编译上述具有错误嵌套的程序,错误百出,/**/是成对出现,但禁止嵌套的。
1.8 指出下列输出语句哪些(如果有)是合法的。
std::cout<<"/*";
std::cout<<"*/";
std::cout<</*"*/"*/;
预测结果,然后编译包含上述三条语句的程序,检查你的答案。纠正遇到的错误。
答:
第一行和第二行是合法的,第三行不合法,可以将第三行改为:std::cout<</*"*/"*/";。或者改为:std::cout<<"/*""*/""*/";
1.9 下列循环做什么?sum的最终值是多少?
int sum =0 ;
for(int i = -100;i<=100;++i)
sum+=i;
答:0.
1.10 用for循环编程,求从50到100的所有自然数的和,然后用whie循环重该程序。
答:
#include <iostream>
using namespace std;
int main()
{
int sum =0 ;
int i=50;
for(;i<=100;++i)
sum+=i;
cout<<sum<<endl;
sum =0 ;
i--;
while(i!=49)
{
sum+=i;
--i;
}
cout<<sum<<endl;
system("pause");
return 0;
}
1.11 用while循环编程,输出10到0递减的自然数。然后用for循环重写该程序。
答:
#include <iostream>
using namespace std;
int main()
{
int sum =0 ;
int i=10,h=10;
for(;i>=0;--i)
cout<<i<<" ";
cout<<endl;
while(h>=0)
{
cout<<h<<" ";
--h;
}
system("pause");
return 0;
}
1.12对比前面两个习题中所写的循环。两种形式各有何忧点。
答:for循环中,循环次数可以确定,while不能直接确定,while循环用一个判断语句来执行循环,无须知道循环次数,for循环中控制变量和条件写在了一起,比较直观,但while循环条理更清晰易懂,两种可以互相转换,各有所长。
1.13 编译器不同,理解其诊断内容的难易程度也不同。编写程序,包含本节“再谈编译”部分讨论的那些常见的错误。研究编译器产生的信息,这样你在编译更复杂的程序遇到这些信息时就不会陌生。
答:对于编译过程中出现的错误,观察错误提示,通常提示,变量声明,定义,语句异常,不匹配的函数调用和未声明的函数,等等。敲的代码多了自然而然就可以根据错误信息对应的那一行附近进行查找。对于运行过程中出现的错误,一般是内存泄漏导致的程序崩溃的问题较多,需要对程序进行断点调试,看看是哪一步出了错。
1.14 如果输入值相等,本节展示的程序将产生什么问题?
答:sum的值即变为输入的值。
1.15 用两个相等的值作为输入编译并运行本节中的程序,将实际输出与你在上一题中所做的预测相比较,解释实际结果和你预计的结果之间不相符之处。
答:sum of 4 to 4 inclusive is 4;与上题预测结果一样。
原因在于,for(int i=lower;i<=upper;++i)
Sum+=i;
本循环执行一次就结束了。
1.16 编写程序,输出用户输入的两个数中的较大者。
答:
#include <iostream>
using namespace std;
int main()
{
int first,second;
cin>>first>>second;
cout<<(first>second? first:second)<<endl;
system("pause");
return 0;
}
1.17 编写程序,要求用户属于一组数,输出信息说明其中有多少个负数。
答:
#include <iostream>
using namespace std;
int main()
{
int count = 0;
int first;
while(cin>>first)
{
if(first<0)
++count;
}
cout<<count<<endl;
system("pause");
return 0;
}
1.18 编写程序,提示用户输入两个数并将这两个数的范围内的每个数写到标准输出。
答:
#include <iostream>
using namespace std;
int main()
{
int start,end;
cin>>start>>end;
if(start>end)
{
int temp=start;
start = end;
end =temp;
}
int t=0;
while(start<end-1)
{
cout<<++start<<" ";
++t;
if(t%10==0)
cout<<endl;
}
system("pause");
return 0;
}
1.19 如果上题给定数1000和2000,程序将产生什么结果?修改程序,是每行输出不超过10个数。
答:上题已经充分考虑到了输入,1000,2000,运行程序查看结果。
1.20 编写程序,求用户范围内的数的和,省略设置上界和下界的if测试。假定输入数是7和3,按照这个顺序,预测程序运行结果。然后按照给定的数是7和3运行程序,看结果是否与你预测的相符。如果不相符,反复研究关于for和while循环的讨论知道弄清楚期中的原因。
答:
求用户范围内的数的和,假如输入时不判断开始数是否大于结束的数,则当这种情况发生时,就如题中所说的7&3,则输出为0,假如判断后并交换start与end的值则,答案为25。
1.21 本书配套网站(http://www.awprofessional.com/cpp_primer)的第一章的代码目录下有Sales_item.h源文件。复制该文件到你的工作目录。编写程序,循环遍历一组书的销售交易,读入每笔交易并将交易写至标准输出。
答:
#include <iostream>
using namespace std;
#include "Salesitem.h"
int main()
{ Sales_item item;
//输入像这样: 0-201-78345-x 3 20.0
while(cin>>item)
{
cout<<item<<endl;
}
system("pause");
return 0;
}
1.22 编写程序,读入两个具有相同的ISBN的Sales_item对象并产生它们的和。
答:
#include <iostream>
using namespace std;
#include "Salesitem.h"
int main()
{ Sales_item item1,item2;
//输入像这样: 0-201-78345-x 3 20.0 0-201-78345-x 12 23.0
cin>>item1>>item2;
cout<<item1+item2<<endl;
system("pause");
return 0;
}
1.23 编写程序,读入几个具有相同ISBN交易输出所有交易的和。
答:
#include <iostream>
using namespace std;
#include "Salesitem.h"
int main()
{ Sales_item item1,item2;
//输入像这样: 0-201-78345-x 3 20.0 0-201-78345-x 12 23.0 0-201-78345-x 12 23.0
cin>>item1>>item2;
cout<<item1+item2<<endl;
system("pause");
return 0;
}
1.24 编写程序,读入几笔不同的交易。对于每笔新读入的交易,要确定它的ISBN是否和以前的交易的ISBN一样,并且记下每一个ISBN的交易总数。通过给定多笔不同的交易来测试程序。这些交易必须代表多个不同的ISBN,但是每个ISBN的记录应分在同一组。
答:
#include <iostream>
using namespace std;
#include "Salesitem.h"
int main()
{ Sales_item item1,item2;
int count=1;
//输入像这样: 0-201-78345-x 3 20.0 0-201-78345-x 12 23.0
cin>>item1;
while(cin>>item2)
{
if(item1.same_isbn(item2))
++count;
else
{
cout<<count<<endl;
item1=item2;
count=1;
}
}
cout<<count<<endl;
// cout<<item1+item2<<endl;
system("pause");
return 0;
}
1.25 使用源自本书配套网站的Sales_item.h头文件,编译并执行本节给出的书店程序。
答:
#include <iostream>
using namespace std;
#include "Salesitem.h"
int main()
{ Sales_item item1,item2;
int count=1;
//输入像这样: 0-201-78345-x 3 20.0 0-201-78345-x 12 23.0
cin>>item1;
while(cin>>item2)
{
if(item1.same_isbn(item2))
item1 = item1+item2;
else
{
cout<<item1<<endl;
item1=item2;
}
}
cout<<item1<<endl;
// cout<<item1+item2<<endl;
system("pause");
return 0;
}
本程序有些不妥,当两个相同的ISBN输入时不是连续的输入时,程序无法将两个相同的ISBN的条目相加,只会输出两个ISBN的数目,而实际上两个是一样的ISBN。
1.26 在书店程序中我们使用了加法操作符,而不是复合赋值操作符,将trans加到total中,为什么我们不使用复合赋值操作符?
答:实际上Sales_item只重载了“=”和“+”两个操作符,所以不能使用+=操作符,其实完全可以利用“+”,“=”,重载“+=”操作符。重载指重新定义某个函数,或者操作符,使其具有新的参数类型。
第三章 标准库类型
3.1 用适当的using声明,而不用std::前缀,访问标准库中名字的方法,重新编写2.3节的程序,计算一给定数的给定次幂的结果。
答:
#include <iostream>
using namespace std;
int main()
{
int base,exponent;
int result=1;
cin>>base>>exponent;
for(int i=0;i!=exponent;++i)
result*=base;
cout<<result<<endl;
system("pause");
return 0;
}
3.2 什么是默认构造函数?
答:默认构造函数没有参数的构造函数,在声明对象时调用默认构造函数,假如没有默认构造函数是不允许声明一个没有参数的对象的。 例如 :string s1,与string s1("adad");
第一个调用的是默认构造函数,第二个是带有参数的构造函数。假如任何一个构造函数没有被定义,则上述两种声明变量的方式都是错误的。
3.3 列举出三种初始化string对象的方法?
答:string s1;string s2("pause");string s3(s2);string s4(4,'c');
3.4 s和s2的值分别是什么?
String s;
int main() { string s2;}
答:空字符。
3.5 编写程序实现从标准输入每次读入一行文本。然后改写程序,每次读入一个单词。
答:
#include <iostream>
using namespace std;
string s;
int main()
{
string s1;
while(cin>>s1)//while(getline(cin,s1))
cout<<s1<<endl;
system("pause");
return 0;
}
3.6 解释string类型的输入操作符和getline函数分别如何处理空白字符。
答:string类型的输入操作符对空白字符的处理:读取并忽略有效字符(非空白字符)之前所有的空白字符,然后读取字符直至再次遇到空白字符,读取终止(该空白字符仍留在输入流中)。 Getline函数对空白字符的处理:只对换行前的操作符进行读取,并最终丢弃换行符。
3.7 编写一个程序读入两个string对象,测试它们是否相等。若不相等,则指出两个中哪个较大。接着,改写程序测试它们的长度是否相等,若不相等指出哪个较长。
答:
#include <iostream>
#include <string>
using namespace std;
int main()
{
string s1,s2;
cin>>s1>>s2;
cout<<(s1>s2?s1:s2)<<endl;
string::size_type s1Long = s1.size();
string::size_type s2Long = s2.size();
if(s1Long==s2Long)
cout<<s1Long<<endl;
else
cout<<(s1Long > s2Long ? s1Long : s2Long)<<endl;
system("pause");
return 0;
}
3.8 编一个程序,从标准输入读取多个string对象,把它们连接起来存放到一个更大的string对象中。并输出连接后的string对象。接着,改写程序,将连接后相邻string对象以空格隔开。
答:
#include <iostream>
#include <string>
using namespace std;
int main()
{
string s1,s2;
while(cin>>s1)
s2+=s1;//+" ";
cout<<s2<<endl;
system("pause");
return 0;
}
3.9 下列程序实现什么功能实现合法吗?如果不合法,说明理由。
string s;
cout<<s[0]<<endl;
答:不合法,s为空,s[0]不存在,但是这个和编译器有关,在DEV_C++中编译不出错误提示。
3.10 编写一个程序,从string对象中去掉标点符号。要求输入到程序的字符串必须含有标点符号,输出结果则是去掉标点符号的string对象。
答:
#include <iostream>
#include <string>
using namespace std;
int main()
{
string s("sfjs..,,fs!!!!");
for(string::iterator i = s.begin(); i!=s.end();++i)
{ if(ispunct(*i))
{
s.erase(i);
--i;
}
}
cout<<s<<endl;
system("pause");
return 0;
}
3.11 下面哪些vector定义不正确?
(a) vector<vector<int> > ivec;
(b) vector<string> svec = ivec;
(c) vector<string> svec(10,"null");
答:(b) 不正确,svec与ivec存储数据类型不同
3.12 下列每个vector对象中元素个数是多少?各元素值是什么?
(a) vector<int> ivec1;
(b) vector<int> ivec2(10);
(c) vector<int> ivec(10,42);
(d) vector<string> svec2(10);
(e) vector<string> svec2(10);
(f) vector<string> svec3(10,"hello");
答:(a) 0个元素,0
(b) 10个元素,0
(c) 10个元素,42
(d) 0个元素,空字符串
(e) 10个元素,空字符串
(f) 10个"hello",字符串
3.13 读一组整数到vector对象,计算并输出每个相邻元素的和。如果读入元素个数为奇数,则提示用户最后一个元素没有求和,并输出其值。然后修改程序:头尾元素两两配对(第一个和最后一个,第二个和倒数第二个,以此类推),计算每个元素的和,并输出。
答:相邻相加
#include <iostream>
#include <vector>
using namespace std;
int main()
{
vector<int> ivec;
int temp;
while(cin>>temp)
ivec.push_back(temp);
for(int i=0;i<ivec.size()-1;i+=2)
{
//cout<<ivec.size()<<endl;
cout<<ivec[i]+ivec[i+1]<<endl;
}
if(ivec.size()%2==1)
cout<<ivec[ivec.size()-1]<<endl;
system("pause");
return 0;
}
对称相加
for(int i=0,j=ivec.size()-1;i<j;++i,--j )
{
cout<<ivec[i]+ivec[j]<<endl;
}
3.14 读入一段文本到vector对象,每个单词存储为vector中的一个元素。把vector对象中每个单词转化为大写字母,输出vector对象中转化后的元素,每八个单词为一行输出。
答:
#include <iostream>
#include <vector>
#include <string>
using namespace std;
int main()
{
vector<string> ivstr;
string str;
int i=1;
while(cin>>str)
ivstr.push_back(str);
for(vector<string>::iterator iter1 = ivstr.begin(); iter1 != ivstr.end(); ++iter1)
{
++i;
for(string::size_type j=0;j!=iter1->size();++j)
{
if(islower((*iter1)[j]))
(*iter1)[j] = toupper((*iter1)[j]);
}
cout<<*iter1<<"\t";
if(i%8==0)
cout<<endl;
}
system("pause");
return 0;
}
3.15 下面程序合法吗?如果不合法,如何更正?
vector<int> ivec;
ivec[0] = 42;
答:不合法,ivec为空,没有分配内存空间,访问会出现内存泄漏。
3.16 列出三种定义vector对象的方法,给定10个元素,每个元素值为42.指出是否还有更好的实现方法,并说明为什么。
答:vector<int> ivec(10,42); vector<int> ivec(10); vector<int> ivec1; vector<int> ivec(ivec1); vector<int> ivec=ivec1;
每个元素值为42,10个元素,可以10次push_back,或者依次根据下表遍历,对每个值进行赋值,但前提必须是已经分配内存的vector<int>.
3.17 重做3.3.2节的习题,用迭代器而不是下标操作来访问vector中的元素。
3.18 编写程序来创建有10个元素的vector对象,用迭代器把每个元素值改为当前值的2倍。
答:
#include <iostream>
#include <vector>
using namespace std;
int main()
{
vector<int> ivec(10,25);
for(vector<int>::iterator iter = ivec.begin();iter!=ivec.end();++iter)
{
*iter=*iter+*iter;
cout<<*iter<<endl;
}
system("pause");
return 0;
}
3.19 验证习题3.18的程序,输出vector的所有元素。
3.20 解释一些在上几个习题的程序实现中你用了哪种迭代器-,并说明原因。
答:只用了普通的迭代器,在修改值的情况下不能用const_iterator这种的迭代器,其他情况下都好。
3.21 何时使用const迭代器的?又何时使用const_iterator? 解释两者的区别。
答:const迭代器是指迭代器只能指向固定的元素,该迭代器不能被修改,const_iterator是指指向的数值是const类型,不允许修改,但迭代器本身是可以自增和自减的。在只是读取并不修改元素的情况下,可以使用const_iterator.
3.22 如多采用下面的方法来计算mid会产生什么结果?
vector<int>::iterator mid = (vi.begin()+vi.end())/2;
答:会提示“+为定义,“+”操作符对于迭代器来说是不支持的,是未重载的操作符。
3.23 解释下面每个bieset对象包含的位模式:
(a)bieset<64> bitvec(32);
(b)bitset<32> bv(1010101);
(c)string bstr;cin>>str;bitset<8> bv(bstr);
答:(a)bitset包含64位,bitvec第五位,编号从0开始,为1,其他位为0;
(b)bitset 包含32为,根据bv中数值的二进制经行初始化。
(c)bv中从右至左的八个字符,保存为0~7位,但是这种初始化方法是错误的。
3.24 考虑这样的序列1,2,3,5,8,13,21,并初始化一个将该序列数字所对应的位置置为1的bitset<32>对象。然后换个方法,给定一个空的bitset对象,编写一段程序把相应位数置为1.
答:方法1:将1,2,3,5,8,13,21位置的数值设为一求16进制,用16进制数初始化bitset<32> bv(0x20212e),
方法2: 斐波纳菲数列,根据下表set(n)为1.
bitset<32> bv;
int x=0,y=1,z;
z= x+y;
while(z<=21)
{
bv.set(z);
x=y;
y=z;
z=x+y;
}
第四章 数组和指针
4.1 假设get_size 是一个没有参数并返回int值的函数,下列哪些定义是非法的?为什么?unsigned buf_size =1024;
(a) int ia[buf_size];
(b) int ia[get_size()];
(c) int ia[4*7-14];
(d) char st[11] = "fundamental";
答:(a)非法,buf_size是一个变量,不能用于定义数组的维数。
(b)非法,get_size()是函数调用,不是常量表达式,不能用于定义数组的维数。
(d)非法,存放字符串的数组必须有12个元素,st只有11个。
4.2 下列数组的值是什么?
string sa[10];
int ia[10];
int main()
{
string sa2[10];
int ia2[10];
}
答:sa和sa2为元素类型为string的数组,自动调用string类的默认构造函数将元素初始化为空字符串,ia为函数体外定义的内置数组,个元素初始化为0;ia2为在函数体内定义的内置数组,个元素未初始化,其值不确定。
4.3 下了哪些定义是错误的?
(a)int ia[7] = {0,1,1,2,3,5,8};
(b)vector<int> ivec = {0,1,1,2,3,5,8};
(c)int ia2[] = ia1;
(d)int ia3[] = ivec;
答:(b)有错,ivec的“=”操作符右边应该是相同类型的才可以。
(c)有错,数组的赋值需要一个一个给数组的元素赋值。
(d)有错,不能用vector<int>初始化数组。
4.4 如何初始化数组的一部分或全部元素?
答:定义数组时可使用初始化列表来初始化数组的部分或全部元素。如果是初始化全部元素,可以省略定义数组时方括号中给出的维数值,如果指定了数组的维数,则初始化列表提供的元素个数不能超过维数值,如果数组位数大于列出的元素初值个数,则只初始化前面的数组元素,剩下的其他元素,若是内置类型则初始化为0,若是类类型则调用该类的默认构造函数进行初始化,字符数组既可以用一组花括号括起来、逗号隔开的字符字面值进行初始化也可以用一个字符串字面值进行初始化。
4.5 列出使用数组而不是vector的缺点。
答:数组固定长,初始化时长度预先知道。
4.6 下面的程序段企图将下标值赋给数组的每个元素,其中在下标操作上有一些错误,请指出这些错误。
const size_t array_size = 10;
int ia[array_size];
for(size_t ix=1;ix<=array_size;++ix)
ia[ix]=ix;
答:ix=10ia[10]访问越界。
4.7 编写必要的代码将一个数组赋给另一个数组,然后把这段代码改用vector实现。考虑如何将一个vector赋给另一个vector.
4.8 编写程序判断两个数组是否相等,然后编写一段类似的程序比较两个vector。
4.9编写程序定义一个有10个int型元素的数组,并以其在数组中的位置作为各4.10元素的初值。
4.10 下面提供了两种指针声明的形式,解释宁愿使用第一种形式的原因:
int *ip;
int* ip;
答:第一种指明指针指向的是int型数据,指明ip是一个指针,尤其是当一个语句中同时定义了多个变量时。
4.11 解释下列声明语句,并指出哪些是非法的,为什么?
(a)int* ip;
(b)string s,*sp = 0;
(c)int i;double* dp=&i;
(d)int* ip,ip2;
(e)const int i =0 ,*p=i;
(f)string *p =NULL;
答:(a)合法
(b)合法
(c)非法类型不一样,不能用double型指针指向int型的值。
(d)合法
(e)合法
(f)合法
4.12 已知一指针p,你可以确定该指针是否指向一个有效的对象吗?如果可以,如何确定?如果不可以,请说明原因。
答:无法确定某指针是否指向一个有效对象。因为,在C++语言中,无法检测指针是否未被初始化,也无法区分一个地址是有效地址,还是由指针所分配的存储空间中存放的不确定值的二进制位形成的地址。
4.13 下列代码中,为什么第一个指针的初始化是合法的,第二个则不合法?
int i =32;
void *p =&i;
long *lp = &i;
答:第一个指针指针类型为空的指针可以指向任何一种类型,所以第一个合法,第二个两个指针指向了和自己所定义指向的类型不同的数值。
4.14 编写代码修改指针的值;然后再编写代码修改指针所指对象的值。
答:
#include <iostream>
#include <bitset>
#include <string>
#include <vector>
using namespace std;
int main()
{
int i=10;
int j=100;
int *p;
int *q;
p=&i;
q=&j;
p=q;
cout<<*p<<"\t"<<*q<<endl;
(*q)++;
*p=*q;
cout<<*p<<"\t"<<*q<<endl;
system("pause");
return 0;
}
4.15 解释指针和引用的主要区别。
答:使用引用和指针都可间接访问另一个值,但他们之间存在两个重要区别:(1)引用总是指向某个确定对象,定义引用时没有进行初始化会出现编译错误;(2)赋值行为上存在差异:给引用赋值修改的是该引用所关联的对象的值,而不是使该引用与另一个对象关联。引用一经初始化,就始终指向同一个特定对象。给指针赋值修改的是指针对象本身,也就是使该指针指向另一对象,指针在不同时刻可指向不同的对象(只要保证类型匹配)。
4.16 下列程序段实现什么功能?
int i=42,j=1024;
int *p1 = &i,*p2=&j;
*p2=*p1**p2;
*p1*=*p1;
答:i被赋值为42*42,j被赋值为42*1024.
4.17 已知p1和p2指向同一个数组中的元素,下面语句实现什么功能?
p1+=p2-p1;
答:当p1和p2具有什么值时这个语句是非法的?
4.18 编写程序,使用指针把一个int型数组的所有元素设置为0;
答:
int count[10]={1,2,3,4,5,6,7,8,9,10};
int *pp=count;
for(int i=0;i!=10;++i)
{
*(pp+i)=0;
cout<<*(pp+i)<<endl;
}
4.19 解释下列5个定义的含义,指出其中哪些定义是非法的:
(a)int i;
(b)const int ic;
(c)const int *pic
(d)int *const cpi;
(e)const int *const cpic;
答:
(b)const型量没有定义
(d)const*没初始化,
(e)consg*没初始化.
4.20 下列那些初始化是合法的?为什么?
(a)int i=-1;
(b)const int ic =i;
(c)const int *pic=⁣
(d)int *const cpi=⁣
(e)const int *const cpic=⁣
答:(d)不合法,指针类型与指针指向的类型不同
4.21 根据上述定义,下列哪些赋值运算是合法的?为什么?
(a)i=ic;
(b)pic=⁣
(c)cpi=pic;
(d)pic = cpic;
(e)cpic =⁣
(f)ic=*cpic;
答:常量不能被赋值,所以c、f是错的
4.22 下列两个while循环的差别:
const char *cp = "hello";
int cnt;
while(cp) { ++cnt;++cp}
while(*cp){++cnt;++cp}
答:第一个判断条件是cp为null,第二个是cp指向的数据为null,第二个才可以正确的计算cp的长度。
4.23 下列程序实现什么功能?
const char ca[]={'h','e','l','l','o'};
const char *cp=ca;
while(*cp)
{
cout<<*cp<<endl;
++cp;
}
答:一个一个字符的将ca输出
4.24 解释strcpy和strncpy的差别在哪里,各自的优缺点又是什么?
答:strcpy和strcnp的差别在于:前者复制整个指定的字符串,后者复制指定字符串中指定数目的字符。
strcpy比较简单,而使用strncpy可以适当地控制复制字符的数目,因此比strcpy更为安全。
4.25 编写程序比较两个string类型的字符串,然后编写另一个程序比较两个C风格字符串的值。
答:#include <iostream>
#include <bitset>
#include <string>
#include <vector>
using namespace std;
int main()
{
string str1("sdasfsf"),str2("sdfsfaswfs");
if(str1>str2)
cout<<"str1 is longer than str2"<<endl;
else if(str2>str1)
cout<<"str2 is longer than str1"<<endl;
else
cout<<"str1 is equal to str2"<<endl;
int result=0;
result=strcmp(str1.c_str(),str2.c_str());
if(result>0)
cout<<"str1 is longer than str2"<<endl;
else if(result<0)
cout<<"str2 is longer than str1"<<endl;
else
cout<<"str1 is equal to str2"<<endl;
system("pause");
return 0;
}
4.26 编写程序从标准输入设备读入一个string类型的字符串。考虑如何编程实现从标准输入设备读入一个C风格字符串。
答:string str;cin>>str;
const int str_size =80;
char str[str_size];
cin>>str;
4.27 假设有下面的new表达式,请问如何释放pa?
int *pa =new int[10];
答:用语句delete[] pa;释放pa所指向的数组空间。
4.28编写程序由从标准输入设备读入的元素数据建立一个int型vector对象,然后动态创建一个与该vector对象大小一致的数组,把vector对象的所有元素复制给新数组。
4.29 对本节第5条框中的两端程序:
(a)解释这两段程序实现的功能。
(b)平均来说,使用string类型的程序执行速度要比用C风格字符串的快很多,在我们用了5年的PC机上其平均执行速度分别是:
User 0.47 #string class
User 2.55 # c_style character string
你预计的也一样吗
4.30 编写程序连接两个C风格的字符串字面值,把结果存储在一个C风格字符串中。然后再编译写程序连接两个string类型字符串,这两个string类型字符串与前面的C风格字符串字面值具有相同的内容。
4.31 编写程序从标准输入设备读入字符串,并把该串存放在字符数组中。描述你的程序如何处理可变长的输入。提供比你分配的数组长度长的字符串数据测试你的程序.
答:
cin>>stemp;
char *p=new char [stemp.size()];
for(string::size_type i=0;i!=stemp.size();++i)
*(p+i)=stemp[i];
cout<<p<<endl;
delete [] p;
4.32 编写程序用int型数组初始化vector对象。
答:int a[8]={1,2,3,4,4,5,6,7};
vector<int> ivec(a,a+8);
for(vector<int>::iterator iter=ivec.begin();iter!=ivec.end();++iter)
cout<<*iter<<endl;
4.33 编写程序把int型vector复制给int型数组。
4.34 编写程序读入一组string类型的数据,并将他们存储在vector中,接着,把该vector对象复制给一个字符指针数组。为vector中的每个元素创建一个新的字符数组,并把该vector元素的数据复制到相应的字符数组中,最后把指向该数组的指针插入字符指针数组。
4.35 输出习题4.34中建立的vector对象和数组的内容。输出数组后,记得释放字符数组。
4.36 重写程序输出ia数组的内容,要求在外层循环中不能使用typedef定义的类型