zoukankan      html  css  js  c++  java
  • c++ Primer 第五版习题答案第四章

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

    105

    4.2 在下述表达式的合理位置添加括号,使得添加括号后运算对象的组合顺序与添加前一致。
    (a) *vec.begin() --> *(vec.begin())
    (b) vec.begin() + 1 --> (vec.begin() + 1)

    4.4 求下列表达式的值。

        int result = 12 / 3 * 4 + 5 * 15 +24 % 4 / 2;
        cout << result << endl;                                  // 91
    

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

        int result1 = -30 * 3 + 21 / 5; // -86
        int result2 = -30 + 3 * 21 / 5; // -18
        int result3 = 30 / 3 * 21 % 5; // 0
        int result4 = -30 / 3 * 21 % 4; // -2
    

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

        int num = 4;
        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的值,为一个字符串,不为0.最后两者相与,值> 为真。
    

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

    void test410()
      {
          int number = 0;
          while (cin >> number) 
          {   
              if (42 == number)
              {   
                  break;
              }   
          }   
      }
    

    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的值分别是多少?

         d = i = 3.5;          // i = 3, d = 3; i = 3.5, 将3.5隐式转化为整型。
          i = d = 3.5;         // d = 3.5, i = 3.4.14
    

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

    if (42 = i)            //报错,不能对常量42赋值。
    if (i = 42)            // 将42赋值给i,if条件为真。
    

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

        double dval;
          int ival;
          int *pi;
    
         dval = ival = pi = 0;            // pi存的是地址,给pi赋值为0,即要访问地址为0的内存?
    // 应改为:
        dval = ival = *pi = 0;
    

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

     if (p = getPtr != 0){}       // 可能会先判断!=, 再把结果赋值给p,改为if ((p = getPtr) != 0)
     if (i = 1024)                    // 会把1024赋值给i,再进行判断,改为if (1024 == i)
    

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

    会先向后移动一个元素,再输出移动后的值。输出范围为第二个元素到最后一个元素的下一个元素。由于最后一个元素的下一个元素未知,所以会访问到未知内存。

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

    ptr != 0 && *ptr++;        //判断ptr是否为空,并且ptr指向的值是否为0;
    ival ++ && ival;                // 判断ival及ival++是否为空。运算的顺序为,先计算++,在进行&&
    vec[ival++] <= vec[ival];    // 运算顺序未知,比如ival = 1,编译器有可能先算vec[ival++],得到ival=2,再计算vec[ival],这样就得不到预期结果。因此改成vec[ival+1] <= vec[ival];
    

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

    *iter++;                    // 合法,先对iter+1,再返回iter初始值的副本,再对该副本进行解引用
    (*iter)++;                  //  不合法,不能对string类型进行++操作。
    *iter.empty();           // 不合法,不能对指针指向的值判空。可改为(*iter).empty();
    iter->empty();          // 合法
    ++*iter;                    // 不合法,先求*iter,在进行++操作,不能对string类型做++操作,可改为 *(++iter);
    iter++->empty();      //合法,++和->的优先级一样,所以遵循自左向右结合,先算iter++的值,返回iter初始值的副本,再进行empty()判断。iter->empty等价于(*iter).empty
    

    4.21 编写程序,使用条件运算符从vector中找到哪些元素是奇数,然后将奇数翻倍。

    void test421()
      {
          vector<int> ivec = {1, 2, 3, 4, 5, 6}; 
    
          for (auto &iter : ivec) {
              iter = (iter % 2 == 1) ? iter * 2 : iter;
              cout << iter << " ";
          }   
          cout << endl;
    }
    

    4.22

    void test422()
      {   
          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";
     //  条件语句优先级较低,要给其加括号。
       string p1 = s + (s[s.size()-1] == 's' ? "" : "s");
    

    4.24 假如条件运算符满足的是左结合律,求值过程会是怎样的?

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

    'q' << 6运算会把结果隐式转化为int类型,因为6是int类型。因此结果的二进制码为:
    0000 0000 0000 0000 0001 1100 0100 0000,转化为10进制为7232.

    4.26 测验成绩的例子中,如果使用unsigned int作为quiz1的类型会发生什么情况。
    > 在某些系统上,int占16为,因此如果用unsigned int来存储的话,在这些机器上就会发生位数不够用的情况。而unsigned long则可以保证在任何机器上都至少有32位。

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

    unsigned long ul1 = 3, ul2 = 7;
    cout << (ul1 & ul2) << endl;            // 0011 & 0111 = 0011 = 3
    cout << (ul1 | ul2) << endl;              // 0011 | 0111 = 0111 = 7
    cout << (ul1 && ul2) << endl;          // 3 && 7 = 1
     cout << (ul1 || ul2) << endl;4.28     // 3 || 7 = 1
    

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

    void test428()
      {   
          cout << sizeof (int) << endl;                // 4
          cout << sizeof (char) << endl;             // 1
          cout << sizeof (short) << endl;            // 2
          cout << sizeof (long) << endl;             // 8
          cout << sizeof (float) << endl;              // 4
          cout << sizeof (double) << endl;          // 8
          cout << sizeof (long double) << endl;  // 16
          cout << sizeof (long long) << endl;      // 8
      }
    

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

    void test429()
      {
          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;     // 2, sizeof(p)的含义:p是一个int *类型,因此得出的大小应该是指针的大小。
                                                                          // sizeof(*p)的含义:*p已经对p解引用了,*p实际就是int类型,因此sizeof(*p)得到的是一个int型的大小。
      }
    

    4.30 在下面的表达式的适当位置加上括号,使得加上括号之后表达式的含义与原来的含义相同。

    sizeof x +  y;                // sizeof(x) +  y; 
    sizeof p->mem[i];        // sizeof (p->mem[i]); 
    sizeof a < b;                // sizeof (a) < b;   
    sizeof f();                     // sizeof (f()); 
    

    4.31 使用递增和递减运算符时,为什么要用前置版本而不用后置版本,要想使用后置版本需要做哪些改动?

    在for循环中使用前置版本和后置版本都能得到相同的结果。这里使用前置版本的原因,就是4.5节中的建议所述:“前置版本的递增运算符避免了不必要的工作,它把值加1后直接返回改变了运算对象。与之相比,后置版本需要将原始值存储下来以便于返回这个未修改的内容,如果我们不需要修改前的值,那么后置版本的操作就是一种浪费。”

    for ( init; condition; increment )
    {
       statement(s);
    }
    

    for循环的执行流程:
    1、先执行init,且只执行一次。
    2、判断condition,如果为真,则执行循环主体。
    3、循环主体执行完之后再执行increment,更新循环控制变量。
    改为后置版本如下:

    void test431()
      {
          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属于一个单独的语句。也就是( someValue ? ++x, ++y : --x), --y; 因此,如果someValue为真,则执行++x,++y,--y,最后得到的结果是y本身。如果someValue为假,则执行--x,--y,最终的结果是--y的值。

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

    if (fval)                        // float类型转化为bool类型
    dval = fval + ival;        // int先转化为float,然后赋值给dval时再转化为double类型
    dval + ival * cval;        // char先转化为int,然后int转化为double
    

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

    char cval;
    int ival;
    unsigned int ui;
    float fval;
    double dval;
    
    cval = 'a' + 3;                             // ‘a’先转化为int进行计算,得到的结果再转化为char
    fval = ui - ival * 1.0;                //  ival先转化为double,ui也转化为double,double再截为float
    dval = ui * fval;                           // unsigned int先提升为float,float再转为double
    cval = ival + fval + dval;             // ival先转为float,float再转为double,最后double转为char
    

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

    i *= static_cast<int> (d);
    

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

    int i;
    double d;
    const string *ps;
    char *pc;
    void *pv;
    
    pv = (void *)ps;            // pv = const_cast<string *>(ps); 去除底层const属性。
    i = int(*pc);                  // i = static_cast<int>(*pc);
    pv = &d;                      // pv = static_cast<void *>(&d);
    pc = (char *)pv;           // pc = reinterpret_cast<char *> (pv);
    

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

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

    将j/i的结果转化为double类型,再赋值给slope。

  • 相关阅读:
    移动端UI
    jQuery 下拉框三级联动
    jQuery基础与学习资源
    jQuery
    TCP、UDP、HTTP、SOCKET之间的区别
    Socket 通信原理(Android客户端和服务器以TCP&&UDP方式互通)
    android 中 任务、进程和线程的区别
    android中不同手机分辨率适配问题
    经验分享:CSS浮动(float,clear)通俗讲解(真的很通俗)
    关于各种排列组合java算法
  • 原文地址:https://www.cnblogs.com/songshuguiyu/p/9116463.html
Copyright © 2011-2022 走看看