本书为Primer C++ 中文第五版
练习题笔记
void t41() {
cout<<"*****4.1*****"<<"\n";
cout<<"5+10*20/2 = "<<5+10*20/2<<"\n";
cout<<"*****4.2*****"<<"\n";
std::string s = "Hello World!";
cout<<"*s.begin() = "<<*s.begin()<<"\n";
cout<<"*(s.begin()) = "<<*(s.begin())<<"\n";
cout<<"*s.begin()+1 = "<<*s.begin()+1<<"\n";
cout<<"(*s.begin())+1 = "<<(*s.begin())+1<<"\n";
}
*****4.1*****
5+10*20/2 = 105
*****4.2*****
*s.begin() = H
*(s.begin()) = H
*s.begin()+1 = 73
(*s.begin())+1 = 73
如果m%n不等于0,则它的符号与m相同;
void t42() {
cout<<"*****4.4*****"<<"\n";
//(((12/3)*4)+(5*15)+((24%4)/2))
cout<<"12/3*4+5*15+24%4/2 = "<<12/3*4+5*15+24%4/2<<"\n";
cout<<"*****4.5*****"<<"\n";
cout<<"-30*3+21/5 = "<<-30*3+21/5<<"\n";
cout<<"-30+3*21/5 = "<< -30+3*21/5<<"\n";
cout<<"30/3*21%5 = "<<30/3*21%5<<"\n";
cout<<"-30/3*21%4 = "<<-30/3*21%4<<"\n";
cout<<"*****4.6*****"<<"\n";
int i;
while(1) {
std::cin>>i;
if(i%2 == 0) {
cout<<i<<" is a even number"<<"\n";
if(i==0)break;
}
else{
cout<<i<< " is a odd number"<<"\n";
}
}
cout<<"*****4.7*****"<<"\n";
int value = std::numeric_limits<int>::max();
cout<<"int value "<< std::numeric_limits<int>::max()<<" + 1 = "<<value+1<<"\n";
}
*****4.4*****
12/3*4+5*15+24%4/2 = 91
*****4.5*****
-30*3+21/5 = -86
-30+3*21/5 = -18
30/3*21%5 = 0
-30/3*21%4 = -2
*****4.6*****
3
3 is a odd number
4
4 is a even number
0
0 is a even number
*****4.7*****
int value 2147483647 + 1 = -2147483648
void t43() {
cout<<"*****4.9*****"<<"\n";
const char *cp = "Hello World";
if(cp && *cp) {
cout<<cp<<" "<<*cp<<"\n";
}
cout<<"*****4.10*****"<<"\n";
int value;
while(1) {
std::cin>>value;
if(value == 42) {
break;
}
}
cout<<"*****4.11*****"<<"\n";
int a,b,c,d;
while(1){
std::cin>>a>>b>>c>>d;
if(a>b&&b>c&&c>d) {
cout<<"sucessful!"<<"\n";
break;
}
}
cout<<"*****4.12*****"<<"\n";
int i,j,k;
while(1) {
std::cin>>i>>j>>k;
//因为<优先级比!=高
//首先判断j<k,如果true返回1,否则返回0
//再判断i 是否等于 1或者0
//即 i!=j<k <=> i != (j<k)
cout<<(i!=j<k)<<"\n";
if(i == 0 && j ==0) {
break;
}
}
}
*****4.9*****
Hello World H
*****4.10*****
1
2
3
4
42
*****4.11*****
1 2 3 4
1 3 2 4
3 2 4 1
3 2 1 4
4 3 2 1
sucessful!
*****4.12*****
1 2 3
0
0 2 3
1
0 0 1
1
void t44() {
int i,i1;
double d,d1;
d = i = 3.5;
i1 = d1 = 3.5;
//赋值运算符为右结合律
// d = (i = 3.5);
// i1 = (d1 = 3.5);
cout << d <<" "<<i<<"\n";
cout << d1 <<" "<<i1<<"\n";
/*
if(42 = i) {
cout<<"42 = i"<<"\n";
}
if(42 = i) error: lvalue required as left operand of assignment
赋值运算符的左值错误
*/
if(i = 42) {
//赋值语句,为真
cout<<"i = 42"<<"\n";
}
double dval;
int ival, *pi;
/*
dval = ival = pi = 0;
error: invalid conversion from ‘int*’ to ‘int’ [-fpermissive]
dval = ival = pi = 0;
*/
dval = ival = 0;
pi = 0;
cout<<dval<<" "<<ival<<" "<<pi<<"\n";
}
3 3
3.5 3
i = 42
0 0 0
*****4.16*****
p = getptr() != 0;
因为!=优先级高于=
所以上面等价于p = (getptr() != 0);即p等于1或者0
417
后置递增和递减与前置递增和递减操作区别在于 包含它们的语句被求值之后还是之前 执行
418
不输出第一个值,并且最后会出现错误
419
(a)首先判断ptr是否为空,是的话判断指针对象是否为0,且指针向后移到一位
(b)首先判断ival是否为空,不是的自增继续判断自增后的是否为空
(c)求值顺序不正确
(a) 解引用当前迭代器所指对象的内容,然后将迭代器向后移动一位。
(b) 非法。string类没有自增操作。
(c) 非法。 点运算符的优先级大于解引用运算符。所以,先进行iter.empty()操作,但迭代器iter并没有定义empty()成员函数。
(d)引用iter所指对象的内容,并调用其成员函数empty()检查string是否为空串。
(e)非法。不能对string用递增运算符。
(f)->运算符的优先级大于后置递增运算符。含义:解引用iter所指对象的内容,并调用其成员函数empty()检查元素是否为空串。最后,迭代器向后移动一位。
void t421() {
int v[10]={0,1,2,3,4,5,6,7,8,9};
std::vector<int> vi(v,v+10);
for(auto &i : vi) {
cout<<((i%2 == 0)? i : i*2)<<" ";
}
cout<<"\n";
}
//if语句
void t4220() {
int grade;
while(cin>>grade) {
if(grade >= 90) {
cout << "high pass"<<"\n";
}
else if(grade >= 75) {
cout << "pass"<<"\n";
}
else if(grade >= 60) {
cout << "low pass"<<"\n";
}
else{
cout << "fail"<<"\n";
}
}
}
//条件语句
void t4221() {
int grade;
while(cin>>grade) {
cout<<(grade>=90?"high pass"
: grade>=75?"pass"
: grade>=60?"low pass" :"fail")<<"\n";
}
}
//优先级 [] > + > == > ?: > =
//题意大概是要将单词末尾加上s
//所以修改如下
void t423() {
std::string s = "word";
std::string s1 = s + (s[s.size()-1] == 's'? "" : "s");
cout<<s1<<"\n";
}
void t425() {
cout<<sizeof(int)<<" "<<sizeof(char)<<"\n";
cout<< (~'q'>>6) <<"\n";
}
4 1
-7296
位运算的对象为int型,首先将char类型转换成int类型
00000000 00000000 00000000 01110001
~优先级比<<高,
所以先位求反:11111111 11111111 11111111 10001110
然后移位:11111111 11111111 11100011 10000000
计算机中以补码形式存储整数,正数不变,负数等于反码+1,负数的反码为除符号位取反;
所以结果为:10000000 00000000 00011100 10000000 (-7296)
426
因为unsigned int只占16位,小于27(书中的int只有16位,见表2.1)

427
ul1:00000000 00000000 00000000 00000011
ul2:00000000 00000000 00000000 00000111
(a)3
(b)7
(c)1
(d)1
void t428() {
cout<<"bool"<<sizeof(bool)<<"\n";
cout<<"char"<<sizeof(char)<<"\n";
cout<<"long"<<sizeof(long)<<"\n";
cout<<"unsigned long"<<sizeof(unsigned long)<<"\n";
cout<<"int"<<sizeof(int)<<"\n";
cout<<"unsigned int"<<sizeof(unsigned int)<<"\n";
cout<<"short"<<sizeof(short)<<"\n";
cout<<"long long"<<sizeof(long long)<<"\n";
cout<<"float"<<sizeof(float)<<"\n";
cout<<"double"<<sizeof(double)<<"\n";
cout<<"long double"<<sizeof(long double)<<"\n";
}
bool1
char1
long8
unsigned long8
int4
unsigned int4
short2
long long8
float4
double8
long double16
void t429() {
int x[10];
int *p = x;
cout<< sizeof(x)/sizeof(*x) <<"\n";
cout<< sizeof(p)/sizeof(*p) <<"\n";
}
10
2
/*
sizeof(x)表示整个数组所占的大小
sizeof(*x)表示int类型所占的大小
sizeof(p)表示指针类型所占的大小
sizeof(*p)表示指针指向类型int所占的大小
*/
430
(a)sizeof( x ) + y //sizeof 高于 +
(b)sizeof( p->men[i]) //-> 高于 sizeof
(c)sizeof(a) < b //sizeof 高于 <
(d)sizeof( f() ) //()高于sizeof
431
在for语句中,前置和后置没有区别,可以直接替换。
432
循环内ptr指向每个数组内对象的地址;
void t433() {
int x = 1, y =5;
cout << (x>y? ++x,++y : --x,--y)<<"\n";
cout << x <<" "<<y<<"\n";
int x1 = 1, y1 =5;
cout << (x1<y1? ++x1,++y1 : --x1,--y1)<<"\n";
cout << x1 <<" "<< y1 <<"\n";
}
4
0 4
5
2 5
/*
通过输出,我们可以看得出这个表达式得到的值为y的值。因为逗号运算符的结果为最后一个表达式的值。
分析可得出表达式计算顺序为:(((someValue) ? (++x, ++y) : (--x) ),--y)
*/
434
(a)fval 将转换成 bool
(b)ival 将转换成 float类型 与 fval 相加 最后转换成 double类型
(c)cval 将转换成int类型 与ival 相乘 最后转换成double类型 与dval相加
435
(a) 'a'先转换成int与3相加 最后转换成char
(b) ival先转换成double与1.0相乘 然后ui转换为double型相减 最后转换成float
(c) ui先转换成float 与 fval 相乘 然后转换为double
(d) ival先转换成float与fval相加 然后转换成double和dval相加 最后转换成char
其他隐式类型转换
数组转换成指针
int ia[10];
int *p = ia;
p转换成指向数组首元素的指针
当被当成decltype的参数,或者取地址符、sizeof及typeid等运算符的对象,或者用一个引用初始化数组都不会转换
指针的转换
0和nullptr能转换成任意指针类型
指向任意非常量的指针能转换成void*
指向任意对象的指针能转换成const void*
转换成布尔类型
如果指针或者算术类型的值为0,转换结果为false,否则为true
转换成常量
允许将指向非常量类型的指针转换成指向相应的常量类型的指针或者引用。反之不可
类类型定义的转换
由编译器自动执行的转换
显示转换
命名的强制类型转换
cast-name<type>(expression)
type是转换的目标类型,如果type是引用类型,结果是左值
expression是要转换的值
cast-name包括:
static_cast 只要不包含底层const,都可以使用static_cast,尤其是将江大的算术类型赋值给较小的类型
dynamic_cast
const_cast 只能改变运算对象的底层const,改变对象的常量属性
reinterpret_cast 为运算对象的位模式提供较低层次上的重新解释
void t436() {
int i = 2;
double d = 3.14;
cout << (i*=static_cast<int>(d))<<"\n";
}
void t437() {
int i;double d;
const std::string *ps;
char *pc;
void *pv;
pv = static_cast<void*>(const_cast<std::string*>(ps));
i = static_cast<int>(*pc);
pv = static_cast<void*>(&d);
pc = static_cast<char*>(pv);
}
438
将(j/i)的值强制转换成double类型