zoukankan      html  css  js  c++  java
  • 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初始化时,并未加‘’,因此其长度未知,while循环会一直继续知道遇见''。输出“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', '+', '+', ''};
          char s2[] = {'c', '+', '+', ''};
    
          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";
          char s2[40] = "I want to get off my work";
          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;
      }
    
  • 相关阅读:
    Java日期时间API系列1-----Jdk7及以前的日期时间类
    Redis设置密码,保护数据安全
    Java SE 8 并发增强
    Java8并发教程:Threads和Executors
    MySQL5.7增量备份恢复全实战
    HashSet HashMap 源码阅读笔记
    操作系统知识点
    Window批处理命令
    JS典型题
    SiteMesh装饰模式
  • 原文地址:https://www.cnblogs.com/songshuguiyu/p/9081507.html
Copyright © 2011-2022 走看看