c++ Primer 第五版習題答案 第三章


3.2 編寫程序,從標准輸入中一次讀入一整行,然后修改該程序使其一次讀入一個詞。

void readByLine ()
{
    string line;

    while (getline (cin, line)) {
        cout << line << endl;
    }   
}
void readByWord ()
{
    string word;

    while (cin >> word) {
        cout << word << endl;
    }   
}

3.3 說明string類的輸入運算符和getline函數分別是如何處理空白字符的。

輸入運算符會自動忽略字符串前的空白(空格、制表符、換行等),從第一個真正的字符到下一個空白。
getline函數會保存字符串中的空白,讀入數據直到遇見換行符。

3.4 編寫程序,讀入兩個字符串,比較其是否相等並輸出結果。如果不相等,輸出較大的那個字符串。改寫上述程序,比較輸入的兩個字符串是否等長,如果不等長,輸出長度較大的那個字符串。

void compareString ()
{
    string s1, s2;

    cin >> s1 >> s2;

    if (s1 == s2) {
        cout << "equal" << endl;
    } else if (s1 > s2){
        cout << s1 << endl;
    } else {
        cout << s2 << endl;
    }

}
void compareSize ()
{
    string s1, s2;

    cin >> s1 >> s2;
    if (s1.size() == s2.size()) {
        cout << "equal" << endl;
    } else if (s1.size() > s2.size()) {
        cout << s1 << endl;
    } else {
        cout << s2 << endl;
    }
}

3.5 編寫一段程序,從標准輸入中讀入多個字符串並將它們連接在一起,輸出連接成的大字符串。然后修改程序,用空格把輸入的多個字符串分割開來。

void linkString ()
{
    string word;
    string sum;

    while (getline (cin, word)) {

        sum += word;
        cout << sum << endl;
    }   
}
void spliteString ()
{
    string word;
    string sum;

    while (getline(cin, word)) {
        sum += (word + " ");
        cout << sum << endl;
    }
}

3.6 編寫程序,使用范圍for語句將字符串內的所有字符用X代替。

void test306 ()
{
    string str("hello world!");
    int len = str.size();

   //  for (int i = 0; i < len; i++) {
  //      str[i] = 'x';
  //  }
      for (auto &c : str) {
          c = 'X';
      }   

    cout << str << endl;
}

3.7 就上題的程序,將循環控制變量的類型設為char會發生什么?
> Answer: 設置成char也是可以的,因為每個元素都是char類型的。

3.8 分別用while循環和for循環重寫第一題,哪種形式更好呢?

  >  Answer: 用普通for循環實現如3.6題代碼中注釋部分,while實現也差不多,都要先知道字符串的長度。相比較而言,范圍for語句更加簡潔一點。

3.9 下面的程序有何作用?它合法嗎?如果不合法,為什么?

 string s;
 cout << s[0] << endl;
Answer:  不合法,使用超出范圍的下標將引發不可預知的結果,由此推斷,使用下標訪問空string也會引發不可預知的結果。

3.10 編寫程序,讀入一個包含標點符號的字符串,將標點符號去除后輸出字符串剩余的部分。

void test310 ()
{
      const string str = "0123&*sjaa,.?70!";
      string result;

      for (auto c : str) {
        // if ((c>='0' && c<='9') || (c>='a' && c<='z') || (c>='A' && c<='Z')) {
     if (!ispunct(c)) { //ispunct函數,如果c為標點符號時為真。
              result += c;
          }   
      }   

      cout << result << endl;
  }

3.11 下面的范圍for語句合法嗎?如果合法,c的類型是什么?

const string s = "Keep out!";
for (auto &c : s) { /*. . . */ }

不合法,設置一個auto類型的引用時,初始值中的頂層const依舊保留,c的類型為const string&。 因此,如果, 在for循環中要改變c的值,則語句不合法。

3.12 下列vector對象的定義是否正確?

    vector<vector<int>> ivec;    //合法,創建類型為vector<int>的對象。
    vector<string> svec = ivec;    //不合法,svec是string類型,而ivec是vector<int>類型。
    vector<string>svec(10, "null");  //合法,創建10個string類型的元素,每個都被初始化為null

3.13 下列vector對象各包含多少個元素?值分別是多少?

    (a)vector<int> v1;                         //不包含元素
    (b)vector<int> v2(10);                   //包含10個元素,每個都初始化為0
    (c)vector<int> v3(10, 42);             // 包含10個元素,每個都初始化為42
    (d)vector<int> v4{10};                  // 包含1個元素,值為10 
    (e)vector<int> v5{10, 42};            // 包含2個元素,值分別是10和42
    (f)vector<string> v6{10};              // 10個默認初始化的元素,初始化為空
    (g)vector<string> v7{10, "hi"};     // 10個值為hi的元素

3.14 編寫一段程序,用cin讀入一組整數並把它們存入vector對象。

void test314 ()
  {
      vector<int> ivec;
      int num;
      while (cin >> num) {
          ivec.push_back(num);
      }
      vector<int>::iterator iter;
      for (iter = ivec.begin(); iter != ivec.end(); iter ++) {
          cout << *iter << " ";
      }
      cout << endl;
  }

ctrl + D 結束輸入

3.15 改寫上題程序,讀入字符串。

void test315 ()
  {
      vector<string> svec;
      string str;
      while (cin >> str) {
          svec.push_back(str);
      }

      vector<string>::iterator iter;

      for (iter = svec.begin(); iter != svec.end(); iter ++) {
          cout << *iter << " ";
      }
      cout << endl;
  }

3.16 編寫程序,將13題中的vector對象容量和值輸出。檢驗之前的回答是否正確。

void test316 ()
  {
      vector<int> v1; //不包含元素
      vector<int> v2(10); //包含10個元素,每個都初始化為0
      vector<int> v3(10, 42); // 包含10個元素,每個都初始化為42
      vector<int> v4{10}; // 包含1個元素,值為10
      vector<int> v5{10, 42}; // 包含2個元素,值分別是10和42
      vector<string> v6{10}; // 10個默認初始化的元素,初始化為空
      vector<string> v7{10, "hi"}; // 10個值為hi的元素

      vector<int>::iterator iter;
      for (iter = v3.begin(); iter != v3.end(); iter++) {
          cout << *iter << " ";
      }   
  }

3.17 從cin讀入一組詞並把它們存入一個vector對象,然后設法把所有詞都改為大寫。輸出改變后的結果,每個詞占一行。

void test317 ()
  {
      string word;
      vector<string> svec;

      while (cin >> word) {
           svec.push_back(word);
      }   

      for (auto &str : svec) {
          for (auto &c : str) {
              c = toupper(c);
          }   
      }   

      for (auto i : svec) {
          cout << i << endl;
      }   
  }

3.18 下面的程序合法嗎?該如何修改?

vector<int> ivec;
ivec[0] = 42;

不合法,ivec為空,不包含任何元素,不能通過下標去訪問元素。應改為 ivec.push_back(42);

3.19 如果想定義一個含有10個元素的vector元素,所有元素值都為42,請列舉三種不同的方式,哪種更好?

vector<int> ivec1(10, 42);
vector<int> ivec2 (ivec1);
vector<int> ivec3 {42, 42, 42, 42, 42, 42, 42, 42, 42, 42};

第一種更好,簡潔。還可以使用for循環挨個賦值,但都繁瑣。

3.20 讀入一組整數並把它們存入一個vector對象,將每對相鄰整數的和輸出出來,改寫程序,這次要求先輸出第一個和最后一個之和,接着輸出第二個和倒數第二個之和,依次類推。

void test318 ()
  {   
      int num;
      vector<int> ivec;
      vector<int> sum;

      while (cin >> num) {
          ivec.push_back(num);
      }


      for (vector<int>::size_type i = 0; i < ivec.size(); i+=2) {
          sum.push_back(ivec[i]+ivec[i+1]);
      }

      for (auto &s : sum) {
          cout << s << " ";
      }
      cout << endl;
void test319 ()
  {
      int num;
      vector<int> ivec;
      vector<int> sum;

      while (cin >> num) {
          ivec.push_back(num);
      }   

      vector<int>::size_type len = ivec.size();
      int temp;
// 如果有奇數個數字,則最中間的數會與自己相加一遍,未排除這種情況
      for (vector<int>::size_type i = 0; i < (len+1)/2; i++) {
          temp = ivec[i]+ivec[len-i-1];
          cout << "i = " << i << " temp = " << temp << endl;
          sum.push_back(temp);
      }   

      for (auto &s : sum) {
          cout << s << " ";
      }   
      cout << endl;

3.21 請使用迭代器重做3.16題。
> 已經使用過迭代器了,不再贅述。

3.22

3.23 創建一個含有10個整數的vector對象,使用迭代器將所有元素的值都變為之前的兩倍。

void test323()
  {
      vector<int> integer(10, 2); 

      for (auto& iter : integer) {
          iter *= 2;
      }   

      for (auto it : integer) {
          cout << it << " ";
      }   
      cout << endl;
 }

3.24 使用迭代器重做3.20題。

上面的答案就是用迭代器做的。

3.25 對成績進行分數段的划分,使用迭代器。

void test325()
  {
      vector<unsigned> scores(10, 0); 
      unsigned grade;
      int i = 0;
      int n = 0;
      auto iter = scores.begin();
      while (i < 5) {
          cin >> grade;
          if (grade > 100) {
              cout << "Wrong grade!" << endl;
              continue;
          }   
          n = grade/10;
      // scores[n] ++;
          iter = iter + n;
          (*iter) ++; 
          i++;
          iter = scores.begin();
      }   

      cout << "scores are : " ;
      for (auto iter : scores) {
          cout << iter << " ";
      }   
      cout << endl;
}

3.26 二分搜索中,為什么用的是mid=beg+(end-beg)/2,而非mid=(beg+end)/2;?

因為end指向最后一個元素的下一個位置。

3.27 假設txt_size是一個無參數的函數,返回值為int,下面定義是否合法?

unsigned buf_size = 1024;
int ia[buf_size];                                //非法,buf_size不是常量
int ia[4*7-14];                                  // 合法
int ia[txt_size()];                               // 非法,函數返回值不是常量
char str[11] = "fundamental";         // 非法,沒有空間可放空字符

3.28 下列數組中元素的值是什么?

string sa[10]; //空string對象
int ia[10]; // 10個整數,都為0
void test328 ()
{
    string sa2[10]; //空string
    int ia2[10]; //10個整數,內容未知
    for (auto i : ia2) {
        cout << i << " "; 
    }   

3.29 相比vector來說,數組有哪些缺點?

長度不可擴展,一旦定義,不能再更改長度。

3.30 指出下面代碼中的錯誤

constexpr size_t array_size = 10;
int ia[array_size]; // 下標越界,最大為9.
for (size_t ix = 1; ix <= array_size; ix ++) { // 下標范圍為0--9,而不是1--10
    ia[ix] = ix;
}

3.31 編寫程序,定義一個長度為10的int數組,令每個元素的值就是其下標值。

void test331 ()
  {
      int a[10];

      for (int i = 0; i < 10; i++) {
          a[i] = i;
      }   

      for (auto j : a) {
          cout << j << "--";
      }   
      cout << endl;

3.32 將上題創建的數組拷貝給另一個數組

{
      int a[10];

      for (int i = 0; i < 10; i++) {
          a[i] = i;
      }   

      for (auto j : a) {
          cout << j << "--";
      }   
      cout << endl;

      int b[10];
      memcpy (&b, &a, sizeof(b));
      for (auto k : b) {
          cout << k << "..";
      }   
      cout << endl;
  }

使用vector實現如下:

void test332()
  {
      vector<int> vec(10);

      for (int i = 0; i < 10; i++) {
          vec[i] = i;
      }   

      for (auto iter : vec) {
          cout << iter << "---";
      }   
      cout << endl;

      vector<int> vec1(vec);
      for (auto iter1 : vec1) {
          cout << iter1 << "...";
      }   
      cout << endl;
  }

3.33 對於分數分段的程序來說,不初始化scores會發生什么?

不初始化scores,則其中內容未知,可能為空,也可能有別的數據。

3.34 假定p1和p2指向同一數組中的元素,則下面程序的功能是什么?什么情況下該程序是非法的?

> p1 += p2 - p1;
  p2-p1為p1與p2之間的距離,p1+(p1和p2之間的距離),即最后得到p2的值。當p1或p2不在同一數組內,則程序非法。
void test333()
  {
      int a[10] = {1, 3, 0, 9, 7, 5, 4, 11, 12, 15};

      int *p1 = a; //*p1 = 1;
      int *p2 = &a[5]; // *p2 = 5

      p1 += p2 - p1; 

      cout << "p1 = " << *p1 << endl; // *p1 = 5
  }

3.35 編寫一段程序,利用指針將數組中的元素置為0.

 
void test335()
  {
      int a[10] = {1, 3, 0, 9, 7, 5, 4, 11, 12, 15};

      int *p1 = a; //*p1 = 1;

      for (int i = 0; i < 10; i++) {
          p1[i] = 0;
      }   

      for (auto j : a) {
          cout << j << "---";
      }   

3.36 編寫一段程序,比較兩個數組是否相等。再寫一段程序,比較兩個vector對象是否相等。

// 數組中可存儲任何類型,因此要用void* 來表示。有現成的memcmp函數可用。
int compareArray(void *a, void *b, size_t len)
  {
      int flag = 0;

      char *p1 = static_cast<char *> (a);
      char *p2 = static_cast<char *> (b);

      while (len --) {
          if (*p1 == *p2) {
              flag ++;
              p1++;
              p2 ++;
          }
          else {
              return -1;
          }
      }

      return 1;
  }
  void test336()
  {

      int a[10] = {1, 3, 0, 9, 7, 5, 4, 11, 12, 15};
      int b[10] = {1, 3, 0, 9, 7, 5, 4, 11, 12, 15};
      int c[10] = {1, 3, 0, 9, 7, 5, 4, 13, 12, 15};

      if (1 == compareArray(a, b, sizeof(a))) {
          cout << "equal!" << endl;
      }
      if (1 == compareArray(a, c, sizeof(a))) {
          cout << "equal" << endl;
      } else {
          cout << "not equal" << endl;
      }
   }

vector的比較直接用等號就可以。

void test336()
  {

      int a[10] = {1, 3, 0, 9, 7, 5, 4, 11, 12, 15};
      int c[10] = {1, 3, 0, 9, 7, 5, 4, 13, 12, 15};

      vector<int> vec1 (begin(a), end(a));
      vector<int> vec2 (begin(c), end(c));

      if (vec1 == vec2) {
          cout << "equal" << endl;
      } else {
          cout << "not equal" << endl;
      } 
}

3.37 下面的程序是何含義,輸出結果是什么?

void test335()
  {
      const char s[] = {'h', 'e', 'l', 'l', 'o'};
      const char* p = s;

      while (*p) {
          cout << *p << " ";
          ++ p;
      }   
      cout << strlen(s) << endl;
  }
//s初始化時,並未加‘\0’,因此其長度未知,while循環會一直繼續知道遇見'\0'。輸出“hello+未知字符”。

3.38 兩個指針相加不僅是非法的,並且沒什么意義,請問為什么沒有意義?

兩個指針相加,相當於兩個地址值相加,比如0x849248 + 0x328134.有何意義?

3.39 寫一段程序,比較兩個string對象,再編寫一段程序,比較兩個c風格字符串的內容。

void test339()
  {
      string str1 = "hello world";
      string str2 = "hello world";

      if (str1 == str2) {
          cout << str1 << " is equal with " << str2 << endl;
      }   
      else {
          cout << str1 << " is not equal with " << str2 << endl;
      }   

      char s1[] = {'c', '+', '+', '\0'};
      char s2[] = {'c', '+', '+', '\0'};

      int result = memcmp (s1, s2, sizeof(s1));

      if (0 == result) {
          cout << "s1 is equal with s2!" << endl;
      }   
      else {
          cout << "s1 is not equal with s2!" << endl;
      }   
  }

3.40 編寫一段程序,定義兩個字符數組並用字符串字面值初始化它們,接着再定義一個字符數組,存放前兩個數組連接后的結果。使用strcpy和strcat把前兩個數組的內容拷貝到第三個數組中。

void test340()
  {
      char s1[20] = "hello world\0";
      char s2[40] = "I want to get off my work\0";
      char s3[100];

      strcpy (s3, s1);
      strcat (s3, " ");
      strcat (s3, s2);

      cout << s3 << endl;
  }

3.41 編寫一段程序,用整型數組初始化一個vector對象。

      int a[10] = {1, 3, 0, 9, 7, 5, 4, 11, 12, 15};
      int c[10] = {1, 3, 0, 9, 7, 5, 4, 13, 12, 15};

      vector<int> vec1 (begin(a), end(a));
      vector<int> vec2 (c, c+10);
//兩種寫法均可。

3.42 編寫一段程序,將含有整數元素的vector對象拷貝給一個整型數組。

void test342()
  {
      vector<int> ivec = {1, 3, 0, 9, 7, 5, 4, 11, 12, 15};
      int a[10];

      for (int i = 0; i < 10; i++) {
          a[i] = ivec[i];
      }   

      for (auto j : a) {
          cout << j << " ";
      }   
      cout << endl;
  }

3.43 編寫三個不同版本的程序,令其均能輸出ia元素,版本1使用范圍for語句管理迭代過程,版本2和3都使用普通for語句,其中版本2要求使用下標運算符,版本3要求使用指針。此外,三個版本都要直接寫出數據類型,而不能使用類型別名,auto關鍵字和decltype。

void test343()
  {
      int ia[3][4] = { 
                      {0, 1, 2, 3}, 
                      {4, 5, 6, 7}, 
                      {8, 9, 10, 11} 
                      };  

  // version1
  // 要用int引用,是因為防止數組被自動轉化成指針。int row[4],就會變成int指針。
      for (const int (&row)[4] : ia) {
          for (int col : row)
          cout << col << " ";
      }   
      cout << endl;

  // version 2
      for (int i = 0; i < 3; i++) {
          for (int j = 0; j < 4; j++)
          cout << ia[i][j] << " ";
      }   
      cout << endl;

  // version 3
  // p指向含有4個整數的數組,q指向p的首元素
      for (int (*p)[4] = ia; p != ia+3; p++) {
          for (int *q = *p; q != *p+4; q++)
          cout << *q << " ";
      }   
      cout << endl;

  }
  

3.44 改寫上一個練習中的程序,使用類型別名來代替循環控制變量的類型。

void test344()
  {
      int ia[3][4] = { 
                      {0, 1, 2, 3}, 
                      {4, 5, 6, 7}, 
                      {8, 9, 10, 11} 
                      };  
//使用別名
      using ci = const int[4];
  // version 1
      for (ci &row : ia) {
          for (int col : row) {
              cout << col << " ";
          }   
      }   
      cout << endl;

  // version 2
      for (int i = 0; i < 3; i++) {
          for (int j = 0; j < 4; j++)
          cout << ia[i][j] << " ";
      }   
      cout << endl;

  // version 3
  // 使用別名
      using ip = int[4];
      for (ip *p = begin(ia); p != end(ia); p++) {
          for (auto q = begin(*p); q != end(*p); q++) {
              cout << *q << " ";
          }   
      }   
      cout << endl;
  }

3.45 再次改寫程序,這次使用auto關鍵字。

void test345()
  {
      int ia[3][4] = { 
                      {0, 1, 2, 3}, 
                      {4, 5, 6, 7}, 
                      {8, 9, 10, 11} 
                      };  
  // version 1
      for (auto &row : ia) {
          for (auto col : row) {
              cout << col << " ";
          }   
      }   
      cout << endl;

  // version 2
      for (int i = 0; i < 3; i++) {
          for (int j = 0; j < 4; j++)
          cout << ia[i][j] << " ";
      }   
      cout << endl;

  // version 3
  // p指向含有4個整數的數組,q指向p的首元素
      for (auto p = begin(ia); p != end(ia); p++) {
          for (auto q = begin(*p); q != end(*p); q++) {
              cout << *q << " ";
          }   
      }   
      cout << endl;
  }


免責聲明!

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



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