Advertisement

C++ Primer(第五版)|练习题答案与解析(第四章:表达式)

阅读量:

C++ Primer(第五版)|练习题答案与解析(第四章:表达式)

本博客专门收录《C++ Primer》(第五版)一书中各章练习题的详细解析与解答过程。
参考:《C++ Primer》
C++ Primer
[C++ Primer](http://cba Operand.com/store/c-plus-plus-primer-9780321714114)

练习题4.1

表达式5+10*20/2的值是多少?

105,P122

练习题4.2

按照第4.12节,在以下所述的表达式中适当的位置添加括号,以使所添加括号后的运算对象组合顺序与原有顺序保持一致。

(a) *vec.begin()–> (*vec.begin())
(b) *vec.begin() + 1 --> (*vec.begin() + 1)

练习题4.4

在下列表达式添加括号,说明求值过程,编写代码验证

表达式:12 / 3 * 4 + 5 * 15 +24 % 4 / 2–>(12 / 3 * 4) + (5 * 15) +(24 % 4 / 2)=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

写出一个表达式,确定一个整数是奇数还是偶数

复制代码
       int num = 10;
       num % 2 == 1 ? cout << "odd" << endl : cout << "even" << endl;

练习题4.7

溢出是何含义,写出三条会溢出的表达式。

溢出现象通常发生在计算结果超出数据类型所能表示的范围时。表达式:short c = (short)65538; // print c = 2, overflow

练习题4.8

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

逻辑与运算符的优先级高于逻辑或运算符,并遵循短路求值规则。相等性运算符则会完整地计算两个操作数的值。

练习题4.9

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

复制代码
    const char *cp = "Hello World";
    if (cp && *cp); 
     // cp是一个地址,不为0。再取*cp的值,为一个字符串,是"Hello World",不为0.最后两者相与,值为True。

练习题4.10

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

代码:

复制代码
    #include <iostream>
    using namespace std;
    int main()
    {
      int number = 0;
      while (cin >> number)
      {
          if (42 == number)
          {
              break;
          }
      }
    }

测试:

复制代码
    1
    2
    42

练习题4.11

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

表达式:if ((a>b) && (b>c) && (c>d))

练习题4.12

假设i,j和k是三个整数,说明表达式i != j < k。

含义:“先取i值,再计算j < k是否成立,成立为大于0的数,否则为0。再计算i != (j < k) 。”

练习题4.13

下述语句中,赋值完i和d的值分别是多少?

语句:int i; double d;
(a)d = i = 3.5; i = 3, d = 3; i = 3.5, 将3.5隐式转化为整型。
(b)i = d = 3.5; d = 3.5, i = 3,因为i是整型。

练习题4.14

执行下述if语句会发生什么情况

(a)if (42 = i) 会报错,42是常量,不能赋值。
(b)if (i = 42)将42赋值给i,if条件为真。

练习题4.15

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

复制代码
    double dval; int ival; int *pi;
    dval = ival = pi = 0

pi是地址,不能把指针的值赋值给int(P129)
修改为:dval = ival = *pi = 0;

练习题4.16

尽管这些语句在语法上是正确的*,但它们可能会出现与预期不符的行为*。为什么*?如何进行改进*?

(a)if (p = getPtr() != 0){} 是由于赋值运算的优先级较低(见P130),可能导致先执行条件判断后再进行赋值操作;修改为:if ((p = getPtr) != 0)
(b)if (i = 1024) 可以直接比较数值是否等于1024;即改为:if (i == 1024)

练习题4.17

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

前置版本采用对象自身作为左值进行返回(P132),而后置版本则采用对象原始值的副本进行右值返回。

练习题4.18

如果第132页的那个输出向量对象元素的while循环在每次迭代前应用递增运算符会发生什么?

将该列表向右移动一位,并在每次循环中将当前索引对应的值赋给下一位的位置;其中列表中的每个索引i(i从1开始)对应的值会被赋给i+1的位置。当处理最后一位数据时,在计算下一位位置时可能会超出数组边界。

练习题4.19

设变量ptr为指向整型的指针。其中向量vec和标量ival分别定义为向量类型和整型类型,请解释以下表达式的含义:该表达式是否存在语法错误?若存在,请说明原因及修改建议。

(a)首先检查ptr变量是否不等于零;随后判断ptr所指内存单元中的值是否为零。
(b)该表达式的作用等同于对两个独立表达式进行评估:一方面评估"++val"操作的效果;另一方面评估"val"状态的变化情况。
需要注意的是,在这种情况下运算顺序会对最终结果产生重要影响:
运算遵循短路规则:即先对前一个操作数执行验证操作;如果前一个操作数的结果已经判定为假,则无需对后一个操作数进行验证即可确定整个表达式的逻辑结果。
因此,在这种情况下建议采用以下修改方案:
将原代码中的"++val && val;"替换为"val++; ++val;"这样就能避免因运算顺序导致的结果偏差。

练习题4.20

设iter类型的变量为vector \::iterator

请判断以下表达式的合法性。

若合法,请指出该表达式的含义。

若不合法,请指出其错误所在。

(a)先将迭代器加1后返回初始迭代器并解引用
(b)无法执行字符串后缀自增操作
(c)无法判断指向对象是否为空可改为(*\text{iter}).\text{empty}()
(d)\text{iter}->\text{empty}() 合法
(e)无法执行字符串前缀自增操作可改为 *(\text{++}\text{ iter})
(f)\text{ iter} ++ -> \text{ empty}() 合法

练习题4.21

编写一个程序来处理数据。运用条件判断运算符来筛选数据,在给定的数据集中找出所有奇数值,并将这些奇数值放大两倍。

代码:

复制代码
    #include <iostream>
    #include <vector>
    #include <iterator>
    #include <string>
    
    using namespace std;
    int main()
    {
      vector<int> ivec = {1, 2, 3, 4, 5, 6};
    
      for (auto &iter : ivec) {
          iter = (iter % 2 == 1) ? iter * 2 : iter;
          cout << iter << " ";
      }
      cout << endl;
    }

输出:

复制代码
    2 2 6 4 10 6

练习题4.22

编写一个程序以实现对学生成绩的分类功能。
该程序需新增一种成绩等级:将成绩分为high pass、pass、fail及新增的low pass(60-75分)。
该功能可采用两种不同的实现方式:
第一种方式利用条件运算符;
第二种方式则基于if-else语句。

代码:

复制代码
    #include <iostream>
    #include <vector>
    #include <iterator>
    #include <string>
    
    using namespace std;
    int main()
    {
      int grade;
      string finalgrade;
      while (cin >> grade)
      {
      // approach 1
          finalgrade = (grade > 90) ? "high pass" : ((grade < 60) ? "fail" : ((grade < 75) ? "low pass" : "pass"));
      // approch 2
          if (grade > 90)
          {
              finalgrade = "hign pass";
          }
          else if (grade < 60)
          {
              finalgrade = "fail";
          }
          else if (grade < 75)
          {
              finalgrade = "low pass";
          }
          else
          {
              finalgrade = "pass";
          }
          cout << finalgrade << endl;
      }
    }

练习题4.23

指出下面表达式的问题,并说明如何修改。

复制代码
    string s = "word";
    string p1 = s + s[s.size()-1] == 's' ? "" : "s";

条件语句优先级较低(P135),要给其加括号。string p1 = s + (s[s.size()-1] == 's' ? "" : "s");

练习题4.25

假设一台机器中的int变量占用32位空间,并且每个char变量占用8位内存空间,在这种情况下基于拉丁码表编码方案下,“q”这个字符的ASCII编码对应的二进制表示为0111\,0001。那么计算结果如何?

该操作(即'q' << 6)会将结果显式地转换为int类型的原因是6属于int类型。具体来说,在二进制表示中为:……而将其转换为十进制则得到数值7232。

练习题4.26

在本节关于测验成绩的实例中,假设将quiz1的数据类型设置为unsigned int将会出现什么问题或现象。

在一些处理器架构中,int占用16位空间。这意味着使用无符号整数(unsigned int)时,在这些设备上可能会出现空间不足的问题。相比之下,在所有设备中使用无符号长整数(unsigned long)能够提供至少32位的空间。

练习题4.27

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

复制代码
    unsigned long ul1 = 3, ul2 = 7;

(a)cout << (ul1 & ul2) << endl; 0011 & 0111 = 0011 = 3
(b)cout << (ul1 | ul2) << endl; 0011 | 0111 = 0111 = 7
(c)cout << (ul1 && ul2) << endl; 3 && 7 = 1
(d)cout << (ul1 || ul2) << endl; 3 || 7 = 1

练习题4.28

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

代码:

复制代码
    #include <iostream>
    #include <vector>
    #include <iterator>
    #include <string>
    
    using namespace std;
    int main()
    {
    // by using method below only include what is needed.
    using std::cout;
    using std::endl;
    
    // void type
    cout << "void: nullptr_t\t" << sizeof(std::nullptr_t) << " bytes" << endl << endl;
    
    // boolean type
    cout << "bool:\t\t" << sizeof(bool) << " bytes" << endl << endl;
    
    // charactor type
    cout << "char:\t\t" << sizeof(char) << " bytes" << endl;
    cout << "wchar_t:\t" << sizeof(wchar_t) << " bytes" << endl;
    cout << "char16_t:\t" << sizeof(char16_t) << " bytes" << endl;
    cout << "char32_t:\t" << sizeof(char32_t) << " bytes" << endl << endl;
    
    // integers type
    cout << "short:\t\t" << sizeof(short) << " bytes" << endl;
    cout << "int:\t\t" << sizeof(int) << " bytes" << endl;
    cout << "long:\t\t" << sizeof(long) << " bytes" << endl;
    cout << "long long:\t" << sizeof(long long) << " bytes" << endl << endl;
    
    // floating point type
    cout << "float:\t\t" << sizeof(float) << " bytes" << endl;
    cout << "double:\t\t" << sizeof(double) << " bytes" << endl;
    cout << "long double:\t" << sizeof(long double) << " bytes" << endl << endl;
    
    // Fixed width integers
    cout << "int8_t:\t\t" << sizeof(int8_t) << " bytes" << endl;
    cout << "uint8_t:\t" << sizeof(uint8_t) << " bytes" << endl;
    cout << "int16_t:\t" << sizeof(int16_t) << " bytes" << endl;
    cout << "uint16_t:\t" << sizeof(uint16_t) << " bytes" << endl;
    cout << "int32_t:\t" << sizeof(int32_t) << " bytes" << endl;
    cout << "uint32_t:\t" << sizeof(uint32_t) << " bytes" << endl;
    cout << "int64_t:\t" << sizeof(int64_t) << " bytes" << endl;
    cout << "uint64_t:\t" << sizeof(uint64_t) << " bytes" << endl;
    
    return 0;
    }

输出:

复制代码
    oid: nullptr_t 4 bytes
    
    bool:           1 bytes
    
    char:           1 bytes
    wchar_t:        2 bytes
    char16_t:       2 bytes
    char32_t:       4 bytes
    
    short:          2 bytes
    int:            4 bytes
    long:           4 bytes
    long long:      8 bytes
    
    float:          4 bytes
    double:         8 bytes
    long double:    12 bytes
    
    int8_t:         1 bytes
    uint8_t:        1 bytes
    int16_t:        2 bytes
    uint16_t:       2 bytes
    int32_t:        4 bytes
    uint32_t:       4 bytes
    int64_t:        8 bytes
    uint64_t:       8 bytes

练习题4.29

推断下面代码的输出,说明原因。

代码:

复制代码
    #include <iostream>
    #include <vector>
    #include <iterator>
    #include <string>
    
    using namespace std;
    int main()
    {
      int x[10];
      int *p = x;
    
      cout << sizeof(x)/sizeof(*x) << endl;
      // 10, sizeof(x) = 10*4, sizeof(*x) = 4;
      cout << sizeof(p) / sizeof (*p) << endl;
      cout << sizeof(p)  << endl;
      cout << sizeof (*p) << endl;
      // sizeof(p)的含义:p是一个int *类型,因此得出的大小应该是指针的大小。
      // sizeof(*p)的含义:*p已经对p解引用了,*p实际就是int类型,因此sizeof(*p)得到的是一个int型的大小。
    }

输出:

复制代码
    10
    1
    4
    4

练习题4.30

在下面的表达式的合适地方插入括号后, 使得其含义与原来完全一致。

(a)`x的大小通过s\text{izeof}计算得到,并将其与y相加。
(b)对于指针p指向的内存区域中的第i个元素的大小也是使用s\text{izeof}进行计算。
(c)当比较ab时,在比较运算符之前先确定a的具体大小。
(d)函数f()返回的数据类型的大小可以通过s\text{izeof}函数获取。

练习题4.31

在处理递增和递减运算符时,为何优先选择前置版本而非后置版本?若需采用后置版本,则需进行哪些调整?

无论是采用前置版还是后置版,在for循环中执行都会产生相同的效果。因此选择前置版本的原因是因为4.5节中的建议指出:递增运算符的作用是仅增加数值而不影响后续操作;相比之下,则需要先存储原始数据以便返回未修改的内容;若无需修改原有的数据,则必须先存储副本以便后续操作。

复制代码
    #include <iostream>
    #include <vector>
    #include <iterator>
    #include <string>
    
    using namespace std;
    int main()
    {
      vector<int> ivec(10, 0); 
    
      vector<int>::size_type cnt = ivec.size();
    
      for (vector<int>::size_type ix = 0; ix != ivec.size(); ix++, cnt++)
      {   
          cout << "ix = " << ix << " cnt = " << cnt << endl; 
          ivec[ix] = cnt;
      }
    }

练习题4.32

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

复制代码
    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)
    {   
    /* ... */
    }

循环遍历ia数组。ix与ptr的作用一致,在其中一个是通过索引法进行遍历,在另一个则利用指针机制。

练习题4.33

说明下面表达式的含义。

由于逗号运算符的优先级最低,在三目运算表达式someValue ? ++x, ++y : --x, --y;中,默认情况下只有前半部分会被编译器识别并执行。具体而言,在这种情况下(即someValue为真),程序将依次执行++x++y这两个操作;而不管是否满足条件后续都会继续执行后面的语句--x, --y;。因此,在这种逻辑下(即someValue为真),最终的结果将是先增加x和y各一次(即++x和++y),然后在随后的操作中再分别减少x和y一次(即--x和--y)。这样一来,在经过整个表达式后,y 的值不会发生变化;而如果 someValue 为假,则会先减少 x 和 y 的值一次(即--x 和 --y),最终导致 y 的值变为负数。

练习题4.34

说明下面的表达式中将会发生什么样的类型转化。

(a)判断条件变为浮点数
(b)计算结果先被转换为浮点数值,并在此基础上将其转为双精度型
(c)首先将字符数据转换为整数值,并接着将其转为双精度数值

练习题4.35

假设有如下定义,则下面表达式中是否发生了隐式转化?

复制代码
    char cval;
    int ival;
    unsigned int ui;
    float fval;
    double dval;

(a)cval = 'a' + 3; 将字符'a'转换为整数后进行计算,并将结果转回字符型变量。
(b)fval = ui - ival * 1.0; 将整数值变量ival和用户界面读取的数值ui分别转换为双精度浮点数后相减。
(c)dval = ui * fval; 将无符号整型数据提升为单精度浮点数后再与单精度浮点数据相乘。
(d)cval = ival + fval + dval; 将整数值、单精度浮点值和双精度浮点值依次转换后相加得到最终结果。

练习题4.36

根据给定变量i和d的数据类型设定,在编程环境中构建表达式i *= d时,请确保该操作以整型运算方式进行处理。

表达式:i *= static_cast<int> (d);

练习题4.37

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

复制代码
    int i;
    double d;
    const string *ps;
    char *pc;
    void *pv;

(a)通过动态常量和string指针进行强制转换。
(b)明确地从字符中获取整数值。
(c)去除底层const属性。
(d)直接提取字符数据。

练习题4.38

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

将j除以i的结果静态转换为双精度类型并赋值给slope

全部评论 (0)

还没有任何评论哟~