C++ Primer (第五版) 课后习题 Unit4

4.1.2 节练习

练习4.1


5+10*20/2 = 105

练习4.2


需要在加完括号后运算顺序和加括号前一样一样

a)* vec.begin()     *(vec.begin())

b)*vec.begin()+1  (*(vec.begin()))+1

4.1.3节练习

练习4.3


可以接受。如果把运算符求值顺序明确规定,必然会影响程序的效率。但是也有一些潜在的影响,但是大多数的时候程序并不会被这种潜在问题影响,所以只需要在需要的时候,对其进行优化。C++是尽可能相信程序员

4.2节练习

练习4.4


12/3*4+5*15+24%4/2 = (12/3*4)+(5*15)+(24%4/2)=16+75+0=91

练习4.6


(a%2==0)? :

练习4.7


溢出:因为计算机里存取数值都是有位数限制的,有位数限制就会有大小上下限的限制。如果超过了一个数字的上限,那么就会发生溢出。如果比能表示的最小值还要小,就会发生溢出。

比如:

    unsigned char x=0xff;
    x++;

    int a=INT_MAX;
    a++;
    cout<<a<<endl;

    int b=INT_MIN;
    b--;
    cout<<b<<endl;

练习4.8


逻辑与,当且仅当左侧为真时,才对右侧进行判断

逻辑或,当且仅当左侧为假时,才对右侧进行判断

相等性运算,并未定义求值顺序。不过我试着用一个程序来检测是先运行左边还是右边:

    int i=0;
    int j=1;   
    if(i++==(j==i))
        cout<<"good";
    else
        cout<<"bad";
//bad
    if((j==i)==i++)
        cout<<"good";
    else
        cout<<"bad";
//good

这个程序说明了我的这个编译器会先执行等号右侧的,然后再执行等号左侧的算式。当然不论先执行哪边,通常情况下都不会影响最终的结果,而且这个式子,最好不要因为执行等号两边的顺序不同,而产生不同的结果。

练习4.9


const char *cp = "Hello World";
if(cp && *cp)

条件部分判断当cp不为空指针时,再去判断这个字符串是否为空串。如果不为空串,则会返回1

练习4.10


#include <iostream>
using std::cin;
using std::cout;

int main() {
    int i=0;
    while((cin>>i)&&(i!=42)){
        cout<<"ok\n";
    }
    return 0;
}

练习4.11


if(a>b&&b>c&&c>d)

if(a>b>c>d)//这个写法好像也可以通过编译

练习4.12


i!=j<k

该表达式先计算j<k,然后将判断结果用于和i比较,如果判断结果为真,则比较看i是否为1,否则看i是否为0。先计算等号后面的。

    i=1;
    j=0;
    k=0;//如果先计算i!=j,然后用这个结果计算小于k,则判断错误,输出22,否则要是先计算j<K,判断正确,返回11
    if(i!=j<k){
        cout<<11;
    }
    else
        cout<<22;

 

总结:

关于比较运算符的前后顺序:

    int i=2;
    int j=2;
    int k=2;
    int o=3;
    if(i<j<k<o){// 通过数字2223检查比较时是左结合还是右结合。如果为真,说明是左结合,如果条件为假,说明是右结合
        cout<<"11111111";
    }

关于比较运算符,应该是左结合

 

关于带不等号的比较符的前后顺序

    i=1;
    j=0;
    k=0;//如果先计算i!=j,然后用这个结果计算小于k,则判断错误,输出22,否则要是先计算j<K,判断正确,返回11
    if(i!=j<k){
        cout<<11;
    }
    else
        cout<<22;

还有等号的比较符的前后顺序:

    int i=0;
    int j=1;   
    if(i++==(j==i))
        cout<<"good";
    else
        cout<<"bad";
//bad
    if((j==i)==i++)
        cout<<"good";
    else
        cout<<"bad";
//good

可以看到不论是等于还是不等于,都是先计算等号右边的值,然后用等号左边的值去和这个计算后的右边的值去比较。

练习4.13


a)i=3;d=3;

b)i=3;d=3.5;

练习4.14


第一句无法执行,赋值的左值不允许为一个常量

第二句就是单纯的将42赋值给i,返回值为42,条件为真

练习4.15


因为pi是一个指向int的指针,赋值的类型不同。

修改:dval=ival=*pi=0;

练习4.16


a)会先执行 getPtr()!=0 会将这个判断结果,0 or 1 赋值给p,如果是想要先赋值,那需要括号((p=getPtr())!=0)

b)会直接将1024赋值给i ,如果想要单纯判断i是否为1024,可以(i==1024)

练习4.17


前置递增运算符是先对对象进行递增,然后将递增的结果返回

后置递增运算符也会对对象进行递增,只不过返回的对象是递增前的一个副本

练习4.18


递增运算符的优先级要高于解引用运算符

如果使用前置,那么将会对该元素指向的下一个元素进行运算。因为没法判断下一个元素是否存在,即下一个元素是否<v.end(),所以这样做可能会引起错误。(该循环会从第二个值开始计算,最后会取到v.end().值未定义)

练习4.19


a)判断ptr不为空指针,如果不为空,同时判断ptr指向的值是否为0,同时将ptr指针指向下一个元素

b)ival和ival+1的值是否都不为0

c)判断vec的第ival个元素和ival+1个元素是否相等,但是由于<=运算符,会先计算右侧,所以会导致值永远相等。

修改后:vec[ival]<=vec[ival++];

练习4.20


a)*iter++ 返回一个副本,为iter指向的元素,而当前iter指向下一个元素

b)(*iter)++  相当于给string+1,这是不合法的

c)*iter.empty() 因为*的优先级低于.的,所以相当于对iter.empty()解引用,iter.empty()是不合法的,通过指针访问对象的成员函数,必须用->

d)iter相当于一个指针,所以可以通过箭头访问成员函数,是看当前元素是否为空

e)不能给一个string 类型++

f)将iter指向下一个元素,但是返回当前的元素的副本的成员函数。

4.7节练习

练习4.21


#include <iostream>
#include <vector>
using std::cout;
using std::vector;

int main() {
    vector<int> v{1,2,3,4,5,6,7,8,9};
    for(auto iter=v.begin();iter<v.end();iter++){
        (*iter)%2==0? :*iter=*iter*2;
    }
    for(auto iter=v.begin();iter<v.end();iter++)
        cout<<(*iter)<<" ";
    return 0;
}

练习4.22


只是用条件运算符

#include <iostream>
using std::cin;
using std::cout;
int main() {
    int grade;
    cin>>grade;
    cout<<((grade<60)?"fail":((grade<75)?"low pass":((grade<90)?"pass":"high pass")));
    return 0;
}

可以看到程序的可读性很差,逻辑不是一目了然的那种

 

使用一个或多个if

    cin>>grade;
    if(grade<60)
        cout<<"fail";
    else if(grade<75)
        cout<<"low pass";
    else if(grade<90)
        cout<<"pass";
    else
        cout<<"high pass";

比较两个程序,下面这个相对更加好理解。

练习4.23


string s = "word";

string p1 = s + s[s.size() -1] == 's'?"":"s";

这里是将s和另一个字符的加和作为p1的值,但是加完以后,又去和‘s'进行了比较

可以改为这样:string p1 = s+(s[s.size() -1]=='s'?"":"s");

练习4.24


finalgrade = (grade > 90) ? "high pass" : (grade < 60) ? "fail" : "pass";

假如其满足左结合律,等同于 finalgrade = ((grade > 90) ? "high pass" : (grade < 60)) ? "fail" : "pass"; 

假如此时 grade > 90 ,第一个条件表达式的结果是 "high pass" ,而字符串字面值的类型是 const char *,非空所以为真。因此第二个条件表达式的结果是 "fail"。这样就出现了自相矛盾的逻辑

练习4.25


‘q' << 6

得到的结果:7232

练习4.26


有的机器上,unsigned int 是16位的,其结果可能是未定义的。

练习4.27


ul1=3=0b0101

ul2=7=0b0111

a)ul1&ul2 = 0b0101=3

b)ul1|ul2 = 0b0111=7

c)ul1&&ul2 = 1

d)ul1||ul2 = 1

练习4.28


#include <iostream>
using std::cout;
int main() {
    cout<<sizeof(int);
    cout<<sizeof(double);
    cout<<sizeof(long);
    cout<<sizeof(char);
    cout<<sizeof(unsigned int);

    return 0;
}

练习4.29


int x[10];

int*p =x;

cout<<sizeof(x)/sizeof(*x)<<endl; // 10

cout<<sizeof(p)/sizeof(*p)<<endl;//这取决于指针在计算机上的大小,在我的计算机上指针为8字节,所以这个为2

练习4.30


a) sizeof x+y = (sizeof x)+y

b)sizeof p->mem[i] = sizeof(p->mem[i])

c)sizeof a<b = (sizeof a)<b

d)sizeof f() = sizeof(f())

练习4.31


在这里要使用后者版本的递增递减运算符不需要任何改动。

练习4.32


对数组的每个元素进行访问。只是同时使用了两套计数方法。一套是通过index下标,另一套是通过指针来完成。

练习4.33


如果someValue为真,则x 和y 同时加一

如果someValue为假,则x 和y 同时减一 ❌

以上理解错误,没有考虑进去优先级问题,因为逗号优先级最低,所以:

这条表达式等价于:(someValue ? ++x,++y:--x),--y;

所以当条件为真时,x和y同时加一,然后这个式子的返回值是y值,之后会丢弃y值,因为作为第二个逗号,它的左边已经全部计算完成了。此时将这个y丢弃,然后对y进行减一,返回y

当条件为假时,x减一,返回这个x,然后丢弃x,然后对y减一,返回y

    int x2=1,y=2;
    (1>0)?++x2,++y:--x2,--y;
    cout<<x2<<y<<endl;
    (1<0)?++x2,++y:--x2,--y;
    cout<<x2<<y<<endl;

计算结果:

 

4.11.1节练习

练习4.34


a)if(fval) float->bool

b)dval = fval+ival   ival->float  最终的结果 ->double

c)dval + ival * cval  cval->int  (ival*cval)->double //右结合律

练习4.35


a)没有❌  首先‘a' ->int ,然后和3加和的结果转换成char

b) 首先发生了ival -> double   然后 ui ->double  它们的结果double->float

c)ui -> float ;然后它们运算的结果 ->double

d)cval = ival + fval + dval ival->float 它们加和的结果 ->double ;再然后 最终结果  double->char

4.11.3节练习

练习4.36


i*=static_cast<int>(d)

练习4.37


a)pv=(void*)ps;

pv = static_cast<void*>(const_cast<string*>(ps));

b)i=int(*pc)

i = static_cast<int>(*pc)

c)pv = &d

pv = static_cast<void*>(&d)

d)pc=(char*)pv

pc = static_cast<char*>pv;

练习4.38


double slope = static_cast<double>(j/i)

将两个整型相除的结果,还是一个整型强制转换成一个浮点数类型。赋值给slope

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值