4.1:表达式5+10*20/2的求值结果是多少?

根据运算符的优先级和结合律,此表达式可以看作 5+( (10 * 20) / 2),结果为105

4.2:根据运算符优先级表,在下述表达式的合理位置添加括号,使得添加括号后运算对象的组合顺序与添加括号前一致。

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

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

4.3:C++语言没有明确规定大多数二元运算符的求值顺序,给编译器优化留下了余地。这种策略实际上是在代码生成效率和程序潜在缺陷之间进行了权衡,你认为这可以接受吗?请说出你的理由。

可以接受,我们可以自己判断,如果改变了某个运算对象的值,在表达式的其他地方就不再使用这个运算对象,但改变运算对象的子表达式本身就是另外一个子表达式的运算对象时该规则无效。

4.4:在下面的表达式中添加括号,说明其求值的过程及最终结果。编写程序编译该(不加括号的)表达式并输出其结果验证之前的推断。

12/3*4+5*15+24%4/2

添加括号后:( (12 / 3) * 4)+(5 * 15)+( (24%4) / 2) = 91

#include<iostream>
using namespace std;
int main()
{int num = 12 / 3 * 4 + 5 * 15 + 24 % 4 / 2;cout << num;
}
//输出91

4.5:写出下列表达式的求值结果。

(a) -30*3+21/5                        //-86

(b) -30+3*21/5                        //-18

(c) 30/3*21%5                        //0

(d) -30/3*21%4                      //-2

4.6:写出一条表达式用于确定一个整数是奇数还是偶数。

#include<iostream>
using namespace std;
int main()
{int num;cin >> num;if (num % 2)cout << "奇数";elsecout << "偶数";
}

4.7:溢出是何含义?写出三条将导致溢出的表达式。

当计算的结果超出该类型所能表示的范围时就会产生溢出。

#include<iostream>
using namespace std;
int main()
{short a = 32768;cout << a << endl;        //输出-32768int b = 2147483648;cout << b << endl;        //输出-2147483648int c = -b - 1;cout << c;             //输出2147483647
}

4.8:说明在逻辑与、逻辑或及相等性运算符中运算对象求值的顺序。

对于逻辑与&&:当且仅当左侧运算对象为真时才对右侧运算对象求值

对于逻辑或 | |:当且仅当左侧运算对象为假时才对右侧运算对象求值

对于相等性运算符:如果两侧运算对象类型不同,进行类型转换

4.9:解释在下面的if语句中条件部分的判断过程。

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

先判断cp,是一个指针,指向了字符数组的第一个元素,不为空,结果为真

接着判断*cp,解引用操作,得到字符'H',为真。

4.10:为while循环写一个条件,使其从标准输入中读取整数,遇到42时停止。

#include<iostream>
using namespace std;
int main()
{int n;while (cin >> n && n != 42){ }
}

4.11:书写一条表达式用于测试4个值a、b、c、d的关系,确保a大于b、b大于c、c大于d。

#include<iostream>
using namespace std;
int main()
{int a = 4, b = 3, c = 2, d = 1;if (a > b && b > c && c > d)cout << "a>b、b>c、c>d" << endl;
}

4.12:假设i、j和k是三个整数,说明表达式 i != j<k 的含义。

根据优先级,先比较 j 和 k 的大小,关系运算符的运算结果是布尔值,如果 j < k,运算结果为true;如果 j >=k ,运算结果为false。接着进行相等性测试,首先布尔值将先转换整型,true转换为1;false转换为0,与i比较是否相等,如果相等,运算结果为true,如果不相等,运算结果为false。

4.13:在下述语句中,当赋值完成后 i 和 d 的值分别是多少?

#include<iostream>
using namespace std;
int main()
{int i;double d;d = i = 3.5;      //3 3i = d = 3.5;     //3 3.5cout << i << " " << d;
}

4.14:执行下述 if 语句后将发生什么情况?

if (42 = i)        //会报错,字面值42是右值

if (i = 42)         //i=42,赋值语句结果为左侧运算对象,赋值后为42,非0,因此为真

4.15:下面的赋值时非法的,为什么?应该如何修改?

int main()
{double dval;int ival;int* pi;dval = ival = pi = 0;//pi类型时int*型,ival是int型,不能把指针类型的值赋给int
}

改正:

int main()
{double dval;int ival;int* pi;pi = 0;dval = ival = 0;
}

4.16:尽管下面的语句合法,但它们实际执行的行为可能和预期并不一样,为什么?应该如何修改?

(a) if(p = getPtr() != 0)

此表达式中 != 运算符优先级高于 = 运算符,因此会先比较 getPtr( )的返回值与0是否相等,比较的结果是一个布尔值,相等为true,不相等为false,再将结果赋给p,结果为1或0。

这样的过程和结果可能与设想的过程并不一致,因此可以用括号将上述语句修改为

if( (p = getPtr()) != 0)

(b) if(i = 1024)

此表达式为赋值表达式,值为1024,转换为布尔类型永远为true,而期待的可能是比较 i 与1024是否相等,因此我们可以把上述表达式改为

if(i ==1024)

4.17:说明前置递增运算符和后置递增运算符的区别。

前置递增运算符:j=++i,首先将 i 加1,然后将改变后的对象作为求值结果

后置递增运算符:j=i++,也会将韵算对象加1,但是求值结果是运算对象改变之前那个值的副本

两种运算符必须作用于左值运算对象。前置版本将对象本身作为左值返回,后置版本将对象原始值的副本作为右值返回

建议:如果不需要修改前的值,都采用前置版本。

4.18:如果以下输出vector对象元素的while循环使用前置递增运算符,将得到什么结果?

 auto pbeg = v.begin();while (pbeg != v.end() && *pbeg >= 0)cout << *pbeg++ << endl;

如果改为前置递增运算符,第一个元素的值将无法输出,而且如果序列中没有负值,后面可能试图解引用一个不存在的元素。

4.19:假设ptr的类型是指向int的指针、vec的类型是vector<int>、ival的类型是int,说明下面的表达式是何含义?如果有表达式不正确,为什么?应该如何修改?

(a) ptr != 0 && *ptr++

如果指针不是空指针,就将指针指向后一位,接着返回指针改变之前指向的对象,若未非0,表达式为真

(b) ival++ && ival

首先ival自增1,然后返回ival原始值的副本,如果不为0,就对右边ival求值,此时的ival应是加1之后的,如果不为0,表达式为真

(c) vec[ ival++] <= vec[ival]

表达式的求值顺序未知,若是先求左侧,右侧的ival就应该是加了1以后的,若是先求右侧,ival就应该是原始值,修改如下:

++ival;

vec[ival] <= vec[ival+1] ;

4.20:假设iter的类型是vector<string>::iterator,说明下面的表达式是否合法。如果合法,表达式的含义是什么?如果不合法,错在何处?

(a) *iter++;

合法,自增运算符优先级大于解引用,iter++使iter加1,接着返回iter原始值的副本作为iter++表达式的结果,接着*解引用的是未增加之前的iter副本

(b) (*iter)++;

不合法,先解引用iter,得到了一个sring元素,string不能自增,不能通过编译

(c) *iter.empty()

不合法,迭代器没有empty()成员函数

(d) iter->empty();

合法,iter->empty()等价于(*iter).empty(),如果iter指向的string为空就返回true,否则返回false

(e) ++*iter;

不合法,原因同b,不能通过编译

(f) iter++->empty();

合法,先判断迭代器指向的值是否为空,再对迭代器加1,指向下一个元素

4.21:编写一段程序,使用条件运算符从vector<int>中找到哪些元素的值是奇数,然后将这些奇数值翻倍。

#include<vector>
#include<iostream>
using namespace std;
int main()
{vector<int> sp{ 1,2,3,4,5,6 };cout << "Original data is:";for (auto it : sp)cout << it << " ";cout << endl;cout << "After changing is:";for (auto it : sp)cout << ((it % 2) ? 2 * it : it)<<" ";
}

4.22:本节的示例程序将成绩划分成high pass、pass和fail三种,扩展该程序使其进一步将60分到75分之间的成绩设定为low pass。要求程序包含两个版本:一个版本只使用条件运算符;另一个版本使用1个或多个if语句。哪个版本的程序更容易理解呢?为什么?

只用条件运算符:

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

使用if语句

#include<iostream>
#include<string>
using namespace std;
int main()
{int grade = 0;cin >> grade; string finalgrade;if (grade > 90)cout << "high pass";else if (grade > 75)cout << "pass";else if (grade > 60)cout << "low pass";elsecout << "fail";cout << finalgrade;
}

if语句更容易理解,可读性比条件运算符多次嵌套好。

4.23:因为运算符的优先级问题,下面这条表达式无法通过编译。根据运算符优先级表指出它的问题在哪里?应该如何修改?

string s = "word";

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

根据运算符优先级,将首先通过s.size()求出s中字符的个数为4,接着s[4-1]访问s中下标为3的字符'd',将字符字面值与string对象s相加,相加后的string对象s为"wordd",接着与字符's'比较是否相等,但是string对象无法与字符字面值s进行==比较,因此错误。

修改如下:

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

上述过程到访问s中下标为3的字符时,若字符为's',则不向string对象s加入任何值,若字符不为's',则向string对象s结尾加上's‘。

4.24:本节的示例程序将成绩分成high pass、pass和fail三种,它的依据是条件运算符满足右结合律。假如条件运算符满足的是左结合律,求值的过程将是怎样的?

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

左边的条件运算构成了右边的条件运算的判断条件的表达式,如果输入的值大于90,表达式的结果就应该是”high pass",字符串转换成布尔类型是有限制的,显然此字符串不可以转换,会出错。

4.25:如果一台机器上int占32位、char占8位、用的是Latin-1字符集,其中字符’q‘的二进制形式是01110001,那么表达式~'q'<<6的值是什么?

根据运算符优先级,先对'q'按位取反,

在内存中字符q为:00000000 00000000 00000000 01110001

按位取反后为      :   11111111 11111111 11111111 10001110

按位左移6位后为: 11111111 11111111 11100011 10000000

是一个负数,在内存中以补码存取,如果输出,输出的是化为原码的十进制数

原码 :10000000 00000000 00011100 10000000

化为十进制后的数为 -7296

4.26:在本节关于测验成绩的例子中,如果使用unsigned int作为quiz1的类型会发生什么情况?

不确定30个学生的成绩都能准确表示,因为unsigned int只能确保占用16位,而此例至少需要30位,因此选择unsigned long。

4.27:下列表达式的结果是什么?

#include<iostream>
using namespace std;
int main()
{//3: 00000000 00000000 00000000 00000011//7: 00000000 00000000 00000000 00000111unsigned long ul1 = 3, ul2 = 7;cout << (ul1 & ul2);        //3cout << (ul1 | ul2);       //7cout << (ul1 && ul2);      //1cout << (ul1 || ul2);      //1
}

后两个表达式的运算符是逻辑运算符。

4.28:编写一段程序,输出每一种内置类型所占空间的大小。

#include<iostream>
using namespace std;
int main()
{cout << "bool的大小为:" << sizeof(bool) << endl;            //1cout << "char的大小为:" << sizeof(char) << endl;          //1cout << "short的大小为:" << sizeof(short) << endl;            //2cout << "int的大小为:" << sizeof(int) << endl;                //4cout << "long的大小为:" << sizeof(long) << endl;          //4cout << "long long的大小为:" << sizeof(long long) << endl;    //8cout << "float的大小为:" << sizeof(float) << endl;            //4cout << "double的大小为:" << sizeof(double) << endl;      //8
}

4.29:推断下面代码的输出结果并说明理由。实际运行这段程序,结果和你想象的一样吗?如果不一样,为什么?

#include<iostream>
using namespace std;
int main()
{int x[10];int* p = x;cout << sizeof(x) / sizeof(*x) << endl;          //10cout << sizeof(p) / sizeof(*p) << endl;         //2
}

第一个表达式计算的是数组x中的元素数量

第二个表达式的sizeof(p)计算的是一个指针的大小,由于我的电脑是64位的,因此大小为8,sizeof(*p)计算的是指针所指向的对象所占空间大小,为4。

4.30:根据运算符优先级表,在下述表达式的适当位置加上括号,使得加上括号之后表达式的含义与原来的含义相同。

(a) sizeof x+y                //(sizeof x)+y

(b) sizeof p-> men[i]     //sizeof (p->men[i])

(c)sizeof a<b                //(sizeof a)<b

(d)sizeof f()                   //sizeof (f())

4.31:本节的程序使用了前置版本的递增运算符和递减运算符,解释为什么要用前置版本而不用后置版本。要想使用后置版本的递增递减运算符需要做哪些改动?使用后置版本重写本节的程序。

#include<vector>
#include<iostream>
using namespace std;
int main()
{vector<int> ivec{1,2,3,4,5};vector<int>::size_type cnt = ivec.size();for (vector<int>::size_type ix = 0; ix != ivec.size(); ++ix, --cnt)ivec[ix] = cnt;for (auto it : ivec)cout << it << " ";
}
//输出5 4 3 2 1

个人认为如果使用了后置版本就会把原始的值存储下来,而前置版本则是直接返回改变了以后的运算对象,但是我们并不需要原始值了,因此使用后置版本是一种浪费,其他原因暂时想不到,而用后置改写也改动不大。

#include<vector>
#include<iostream>
using namespace std;
int main()
{vector<int> ivec{ 1,2,3,4,5 };vector<int>::size_type cnt = ivec.size();for (vector<int>::size_type ix = 0; ix != ivec.size(); ix++, cnt--)ivec[ix] = cnt;for (auto it : ivec)cout << it << " ";
}

如上,改变之后的版本输出依然正确。

4.32:解释下面这个循环的含义。

int main()
{constexpr int size = 5;int ia[size] = { 1,2,3,4,5 };for (int* ptr = ia, ix = 0;ix != size && ptr != ia + size;++ix, ++ptr) {/* ... */ }
}

ptr是一个指针,被初始化为指向数组ia的第一个元素,当ix的值不等于数组的维度并且指针没有指向数组之外时,循环才继续,每次循环结束,ix和指针都自增1。

4.33:根据运算符优先级表说明下面这条表达式的含义。

someValue ?++x, ++y : --x, --y

由于逗号表达式优先级最低,此表达式可以看成

(someValue ?++x, ++y : --x), --y

如果someValue为真,x自增1,y自增1,后又自减1,y的值不变

如果someValue为假,x自减1,y自减1

4.34:根据本节给出的变量定义,说明在下面的表达式中将发生什么样的类型转换:

float fval;        int ival;        double dval;        char cval;

(a) if (fval)                        //fval如果是0,则转换为false,否则转换为true

(b) dval = fval + ival;        //ival首先被转换为float,将fval+ival的结果转换为double

(c) dval + ival * cval;        //cval先整型提升成int,与ival相乘后的结果被转换成double

4.35:假设有如下的定义,请回答在下面的表达式中发生了隐式类型转换吗?如果有,指出来。

char cval;        int ival;        unsigned int ui;        float fval;        double dval;

(a) cval = 'a' + 3;

//'a'整型提升为int,与3相加后的结果转换为char赋给cval

(b) fval = ui - ival * 1.0;

//ival转换为double,与1.0相乘,ui转换为double,与ival*1.0相减,相减后结果转换为float赋给fval

(c) dval = ui * fval;

//ui转换为float,与fval相乘,乘积转换为double赋给dval

(d) cval = ival +fval + dval;

//ival转换为float,与fval相加后的结果转换为double,与dval相加后的结果转换为char,赋给cval

4.36:假设i是int类型,d是double类型,书写表达式i*=d使其执行整数类型的乘法而非浮点类型的乘法。

i *= static_cast<int>(d);

#include<iostream>
using namespace std;
int main()
{int i = 2;double d = 2.5;i *= d;                        //5i *= static_cast<int>(d); //4cout << i ;
}

原表达式输出结果为5,更改后为4,因为原表达式i类型转换为了double型,执行浮点型的乘法,而更改后用强制类型转换将d转换为int型,执行整型的乘法。

4.37:用命名的强制类型转换改写下列旧式的转换语句。

int i;        double d;        const string *ps;        char *pc;        void *pv;

(a) pv = (void*)ps;                        // pv = const_cast<void*>(ps);

(b) i = int(*pc);                              // i = static_cast<int>(*pc)

(c) pv = &d;                                  // pv = static_cast<void*>(&d)

(d) pc = (char*) pv;                       // pc = static<char*>(pv)

4.38:说明下面这条表达式的含义。

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

将 ( j / i )的值强制转换为double类型,赋给slope

C++ Primer(第5版) 课后答案 第四章相关推荐

  1. C程序设计谭浩强第五版课后答案 第三章习题答案

    C语言程序设计谭浩强第五版课后答案第三章 1.假如我国国民生产总值的年增长率为7%, 计算10年后我国国民生产总值与现在相比增长多少百分比.计算公式为p=(1+r)np = (1+r)^np=(1+r ...

  2. 操作系统课后答案第四章

    **操作系统课后答案** 第四章 存储器管理 1.为什么要配置层次式存储器? 答:设置多个存储器可以使存储器两端的硬件能并行工作:采用多级存储系统,特别是Cache 技术,是减轻存储器带宽对系统性能影 ...

  3. 计算机网络谢希仁第七版课后答案第五章 传输层

    5-01 试说明运输层在协议栈中的地位和作用,运输层的通信和网络层的通信有什么重要区别?为什么运输层是必不可少的? 答:运输层处于面向通信部分的最高层,同时也是用户功能中的最低层,向它上面的应用层提供 ...

  4. python程序设计第三版课后答案第六章_python程序设计 第六章答案

    参考答案如下 程序[名词解释] 囊式封堵 设计[单选] 变电所的主要功能是(). [判断题] 单独一根仪表管的支架间距应不大于700mm,章答同一管道支架间距应相等. [单选] 在电路计算时如果不作说 ...

  5. 计算机网络谢希仁第七版课后答案第六章 应用层

    6-01 因特网的域名结构是怎么样的?它与目前的电话网的号码结构有何异同之处?答:(1)域名的结构由标号序列组成,各标号之间用点隔开: - . 三级域名 . 二级域名 . 顶级域名 各标号分别代表不同 ...

  6. 计算机网络谢希仁第七版课后答案第三章 数据链路层

    3-01 数据链路(即逻辑链路)与链路(即物理链路)有何区别? "电路接通了"与"数据链路接通了"的区别何在? 答:数据链路与链路的区别在于数据链路出链路外,还 ...

  7. c语言第四版课后答案第三章3.4,算法与数据结构C语言版课后习题答案(机械工业出版社)第3,4章 习题参考答案...

    第3章 栈和队列 一.基础知识题 3.1 有五个数依次进栈:1,2,3,4,5.在各种出栈的序列中,以3,4先出的序列有哪几个.(3在4之前出栈). [解答]34215 ,34251, 34521 3 ...

  8. linux教程第五版课后答案第六章,linux基础及应用第六章练习题

    linux基础及应用第六章练习题 1. 下列哪个文件的内容为当前已挂载文件系统的列表? A. /etc/inittab B. /etc/profile C. /etc/mtab D. /etc/fst ...

  9. Python语言程序设计基础 第二版(嵩天著)课后答案第四章

    思考与练习: P99 4.1 正确 4.2 错误.分支结构(if/else)不能向已经执行过的语句部分跳转,循环结构(while/for)可以向已经执行过的语句部分跳转. 4.3 A 流程图的基本元素 ...

最新文章

  1. 霍尔开关YS1382检测速度 以及对 智能车竞赛节能组的影响
  2. NYOJ 20 吝啬的国度(深搜)
  3. nyoj1228矩形判断
  4. 作为一名Java开发者应该掌握的基础知识汇总!
  5. 基于单链表的生产者消费者问题
  6. oracle 10.2.0.1 升级 10.2.0.5,Oracle10.2.0.1RAC 升级 Oracle10.2.0.5案例分享 -DATABASE篇
  7. C++之new再探究
  8. 马化腾最新演讲谈机遇:让所有企业在云端利用AI处理大数据
  9. pb中的tounicode 函数_历年高考数学的必考热点三角函数,2020高考生,你会了吗?...
  10. Mysql语句字符串拼接
  11. python实用脚本(三)—— 通过有道智云API实现翻译
  12. Facebook投资者Peter Thiel—一个不折不扣的“魔戒”迷
  13. 翻译考试用计算机作答,2021翻译资格水平考试:CATTI考试时间是多久?考试是上机操作吗?...
  14. 跨平台转码软件HandBrake, 一款万能的视频压缩/格式转换工具!
  15. 单元格下拉全选快捷键_【excel下拉全选快捷键】Excel中全选是Ctrl A,那么反选呢?...
  16. 编程题008--求二叉树的层序遍历--niuke
  17. Windows批处理文件定时删除文件
  18. 总裁福布斯约稿:人工智能与差异化的探讨
  19. 简单又好用的财务分析工具有哪些?
  20. 今天大佬告诉你B站崩溃的背后,b站高可用架构到底是怎么样的

热门文章

  1. 经典供货保密协议模板
  2. 苹果微信点开才会收到信息_2020年2月份最新版苹果手游退款教程
  3. 服务器显示已登陆的用户太多,服务器远程连接用户太多了
  4. 蜂鸟E203 SOC系统
  5. 电子工程师名片——FAT16文件系统
  6. 灵声科技获数千万元 A 轮融资,由北极光创投投资...
  7. 《Apollo 智能驾驶进阶课程》四、感知
  8. 01-2021年6月
  9. 新员工转正申请书如何写呢?工作转正申请书范文分享
  10. 《C++ Primer Plus》第17章:输入、输出和文件(6)