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。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM