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。

  • 相关阅读:
    洛谷p1017 进制转换(2000noip提高组)
    Personal Training of RDC
    XVIII Open Cup named after E.V. Pankratiev. Grand Prix of Eurasia
    XVIII Open Cup named after E.V. Pankratiev. Grand Prix of Peterhof.
    Asia Hong Kong Regional Contest 2019
    XVIII Open Cup named after E.V. Pankratiev. Grand Prix of Siberia
    XVIII Open Cup named after E.V. Pankratiev. Ukrainian Grand Prix.
    XVIII Open Cup named after E.V. Pankratiev. GP of SPb
    卜题仓库
    2014 ACM-ICPC Vietnam National First Round
  • 原文地址:https://www.cnblogs.com/songshuguiyu/p/9116463.html
Copyright © 2011-2022 走看看