• 第 5 章


    5.1

    【出题思路】

    理解空语句的形式和用法。

    【解答】

    空语句是最简单的语句,空语句由一个单独的分号构成。如果在程序的某个地方,语法上需要一条语句但是逻辑上不需要,此时应该使用空语句,空语句什么也不做。

    一种常见的情况是,当循环的全部工作在条件部分就可以完成时,我们通常会用到空语句。使用空语句时最好加上注释,从而令代码的阅读者知道这条语句是有意省略内容的。

    5.2

    【出题思路】

    理解块的形式和用法。

    【解答】

    块是指用花括号括起来的语句和声明的序列,也称为复合语句。一个块就是一个作用域,在块中引入的名字只能在块内部以及嵌套在块中的子块里访问。如果在程序的某个地方,语法上需要一条语句,但是逻辑上需要多条语句,此时应该使用块。块不需要以分号结束。

    例如,循环体必须是一条语句,但是我们通常需要在循环体内做很多事情,此时就应该把多条语句用花括号括起来,从而把语句序列转换成块。

    5.3

    【出题思路】

    使用连续的逗号运算符可以把多条语句合并为一条,这一点与块的作用类似。但是一般来说,直接使用块在程序的可读性上更有优势。

    【解答】

    原文的 while 循环使用了块,其形式是:

    while (val <= 10) {
        sum += val;
        ++val;
    }
    

    利用逗号运算符改写之后的形式如下所示:

    while (val <= 10)
        sum += val, ++val;
    

    很明显,改写之后的代码不够清晰,可读性降低了。

    5.4

    【出题思路】

    我们可以在 if、switch、while 和 for 语句的控制结构内定义变量。定义在控制结构当中的变量只在相应语句的内部可见,一旦语句结束,变量也就超出其作用范围了。如果其他代码需要访问控制变量,则变量必须定义在语句的外部。

    【解答】

    (a)是非法的,它的原意是希望在 while 语句的控制结构当中定义一个 string::iterator 类型的变量 iter,然后判断 iter 是否到达了 s 的末尾,只要还没有到达末尾就执行循环体的内容。但是该式把变量的定义和关系判断混合在了一起,如果要使用 iter 与其他值比较,必须首先为 iter 赋初值。修改后的程序应该是:

    string::iterator iter = s.begin();
    while (iter != s.end()) {
      ++iter;
      /* ... */
    }
    

    (b)是非法的,变量 status 定义在 while 循环控制结构的内部,其作用域仅限于 while 循环。if 语句已经位于 while 循环的作用域之外,status 在 if 语句内是一个未命名的无效变量。要想在 if 语句中继续使用 status,需要把它定义在 while 循环之前。修改后的程序应该是:

    bool status;
    while (status = find(word)) { /* ... */}
    if (!status) { /* ... */ }
    

    5.5

    【出题思路】

    练习 if-else 语句的基本语法结构。

    【解答】

    满足题意的程序如下所示:

    #include <iostream>
    #include <vector>
    #include <string>
    
    using namespace std;
    
    int main() {
        int grade;
        cout << "请输入您的成绩:" << endl;
        cin >> grade;
        if (grade < 0 || grade > 100) {
            cout << "该成绩不合法" << endl;
            return -1;
        }
        if (grade == 100) {                             // 处理满分的情况
            cout << "等级成绩是:" << "A++" << endl;
            return 0;
        }
        const vector<string> scores = {"F", "D", "C", "B", "A"};
        string lettergrade;
        // 如果成绩不合格,不需要考虑添加加号减号的问题
        if (grade < 60)
            lettergrade = scores[0];
        else {
            lettergrade = scores[(grade - 50) / 10];    // 获得字母形式的成绩
            if (grade != 100)       // 只要不是 A++,就考虑添加加号减号
                if (grade % 10 > 7)
                    lettergrade += '+';     // 末尾是 8 或者 9 的成绩添加一个加号
                else if (grade % 10 < 3)
                    lettergrade += '-';     // 末尾是 0、1 或者 2 的成绩添加一个减号
        }
        cout << "等级成绩是:" << lettergrade << endl;
    
        return 0;
    }
    
    // 测试样例一,运行结果
    请输入您的成绩:
    100
    等级成绩是:A++
    
    Process finished with exit code 0
    
    // 测试样例二,运行结果
    请输入您的成绩:
    80
    等级成绩是:B-
    
    Process finished with exit code 0
      
    // 测试样例三,运行结果
    请输入您的成绩:
    101
    该成绩不合法
    
    Process finished with exit code 255
      
    // 测试样例四,运行结果
    请输入您的成绩:
    87
    等级成绩是:B
    
    Process finished with exit code 0
    

    5.6

    【出题思路】

    条件运算符可以实现与 if-else 语句类似的功能,当有嵌套的条件表达式时,注意其满足右结合律。

    C++ 运算符优先级

    【解答】

    改写后的程序如下所示:

    #include <iostream>
    #include <vector>
    #include <string>
    
    using namespace std;
    
    int main() {
        int grade;
        cout << "请输入您的成绩:" << endl;
        cin >> grade;
        if (grade < 0 || grade > 100) {
            cout << "该成绩不合法" << endl;
            return -1;
        }
        if (grade == 100) {                             // 处理满分的情况
            cout << "等级成绩是:" << "A++" << endl;
            return 0;
        }
        const vector<string> scores = {"F", "D", "C", "B", "A"};
        string lettergrade;
        // 如果成绩不合格,不需要考虑添加加号减号的问题
        if (grade < 60)
            lettergrade = scores[0];
        else {
            lettergrade = scores[(grade - 50) / 10];    // 获得字母形式的成绩
            if (grade != 100)       // 只要不是 A++,就考虑添加加号减号
                // 末尾是 8 或者 9 的成绩添加一个加号
                // 末尾是 0、1 或者 2 的成绩添加一个减号
                // 注意运算符的优先级和结合性,不确定的可以加括号
                lettergrade += grade % 10 > 7 ? "+" : grade % 10 < 3 ? "-" : "";
        }
        cout << "等级成绩是:" << lettergrade << endl;
    
        return 0;
    }
    
    // 测试样例一,运行结果
    请输入您的成绩:
    100
    等级成绩是:A++
    
    Process finished with exit code 0
    
    // 测试样例二,运行结果
    请输入您的成绩:
    80
    等级成绩是:B-
    
    Process finished with exit code 0
      
    // 测试样例三,运行结果
    请输入您的成绩:
    101
    该成绩不合法
    
    Process finished with exit code 255
      
    // 测试样例四,运行结果
    请输入您的成绩:
    87
    等级成绩是:B
    
    Process finished with exit code 0
    

    5.7

    【出题思路】

    理解 if 语句的语法规则。

    【解答】

    (a)if 语句的循环体应该是一条语句,需要以分号结束,程序修改为:

    if (ival1 != ival2)
        ival1 = ival2;
    else ival1 = ival2 = 0;
    

    (b)if 语句的循环体只能是一条语句,本题从代码的缩进格式上来说需要做两件事,一是修改 minval 的值,二是重置 occurs 的值,所以必须把这两条语句放在一个块里。

    程序修改为:

    if (ival < minval) {
      minval = ival;
      occurs = 1;
    }
    

    (c)ival 是定义在 if 语句中的变量,其作用域仅限于第一个 if 语句,要想在第二个 if 语句中也使用它,就必须把它定义在两个 if 语句的外部。程序修改为:

    int val;
    if (ival = get_value())
        cout << "ival = " << ival << endl;
    if (!val)
        cout << "ival = 0
    ";
    

    (d)程序的原意是判断 ival 的值是否是 0,原题使用赋值运算符的结果是把 0 赋给了 ival,然后检验 ival 的值,这样使得条件永远不会满足。程序修改为:

    if (ival == 0)
        ival = get_value();
    

    5.8

    【出题思路】

    理解悬垂 else 的定义,以及 C++ 是如何处理悬垂 else 的。

    【解答】

    悬垂 else 是指程序中的 if 分支多于 else 分支时,如何为 else 寻找与之匹配的 if 分支的问题。

    C++ 规定,else 与离它最近的尚未匹配的 if 匹配,从而消除了二义性。

    5.9

    【出题思路】

    if 语句和 switch 语句是分支语句的两种形式,一般来说可以相互转化。

    【解答】

    满足题意的程序如下所示:

    #include <iostream>
    
    using namespace std;
    
    int main() {
        unsigned int vowelCnt = 0;
        char ch;
        cout << "请输入一段文本:" << endl;
        while (cin >> ch && ch != 'Q') {
            if (ch == 'a' || ch == 'e' || ch == 'i' || ch == 'o' || ch == 'u')
                ++vowelCnt;
        }
        cout << "您输入的文本中共有 " << vowelCnt << " 个元音字母" << endl;
    
        return 0;
    }
    
    // 运行结果
    请输入一段文本:
    AaOoEeIiUu Q
    您输入的文本中共有 5 个元音字母
    
    Process finished with exit code 0
    

    5.10

    【出题思路】

    要实现本题的要求,只需更新 switch 语句的 case 分支即可。

    【解答】

    本题的关键是在适当位置添加 break; 语句。其中,表示同一字母大小写的 case 标签之间不写 break; ,因为它们要做的操作是一样的;而不同字母的 case 分支最后要写上 break; 。满足题意的程序如下所示:

    #include <iostream>
    
    using namespace std;
    
    int main() {
        unsigned int aCnt = 0, eCnt = 0, iCnt = 0, oCnt = 0, uCnt = 0;
        char ch;
        cout << "请输入一段文本:" << endl;
        while (cin >> ch && ch != 'Q') {
            switch (ch) {
                case 'a':
                case 'A':
                    ++aCnt;
                    break;
                case 'e':
                case 'E':
                    ++eCnt;
                    break;
                case 'i':
                case 'I':
                    ++iCnt;
                    break;
                case 'o':
                case 'O':
                    ++oCnt;
                    break;
                case 'u':
                case 'U':
                    ++uCnt;
                    break;
            }
        }
        cout << "元音字母 a 的数量是:" << aCnt << endl;
        cout << "元音字母 e 的数量是:" << eCnt << endl;
        cout << "元音字母 i 的数量是:" << iCnt << endl;
        cout << "元音字母 o 的数量是:" << oCnt << endl;
        cout << "元音字母 u 的数量是:" << uCnt << endl;
    
        return 0;
    }
    
    // 运行结果
    请输入一段文本:
    AaOoEeIiUu Q
    元音字母 a 的数量是:2
    元音字母 e 的数量是:2
    元音字母 i 的数量是:2
    元音字母 o 的数量是:2
    元音字母 u 的数量是:2
    
    Process finished with exit code 0
    

    5.11

    【出题思路】

    继续扩充 case 标签即可。其中,读入字符的语句应该使用 cin.get(ch) ,而不能使用 >> ,因为后者会忽略本题所要统计的特殊符号。

    #include <iostream>
    
    using namespace std;
    
    int main() {
        unsigned int aCnt = 0, eCnt = 0, iCnt = 0, oCnt = 0, uCnt = 0;
        unsigned int spaceCnt = 0, tabCnt = 0, newlineCnt = 0;
        char ch;
        cout << "请输入一段文本:" << endl;
        while (cin.get(ch) && ch != 'Q') {
            switch (ch) {
                case 'a':
                case 'A':
                    ++aCnt;
                    break;
                case 'e':
                case 'E':
                    ++eCnt;
                    break;
                case 'i':
                case 'I':
                    ++iCnt;
                    break;
                case 'o':
                case 'O':
                    ++oCnt;
                    break;
                case 'u':
                case 'U':
                    ++uCnt;
                    break;
                case ' ':
                    ++spaceCnt;
                    break;
                case '	':
                    ++tabCnt;
                    break;
                case '
    ':
                    ++newlineCnt;
                    break;
            }
        }
        cout << "元音字母 a 的数量是:" << aCnt << endl;
        cout << "元音字母 e 的数量是:" << eCnt << endl;
        cout << "元音字母 i 的数量是:" << iCnt << endl;
        cout << "元音字母 o 的数量是:" << oCnt << endl;
        cout << "元音字母 u 的数量是:" << uCnt << endl;
        cout << "空格的数量是:" << spaceCnt << endl;
        cout << "制表符的数量是:" << tabCnt << endl;
        cout << "换行符的数量是:" << newlineCnt << endl;
    
        return 0;
    }
    
    // 运行结果
    请输入一段文本:
    AaOoEeIiUu 			
    
    fksjkfl
    Q
    元音字母 a 的数量是:2
    元音字母 e 的数量是:2
    元音字母 i 的数量是:2
    元音字母 o 的数量是:2
    元音字母 u 的数量是:2
    空格的数量是:1
    制表符的数量是:3
    换行符的数量是:3
    
    Process finished with exit code 0
    

    5.12

    【出题思路】

    为了统计字符序列的情况,必须记录前一个字符的内容。

    【解答】

    我们的设定是一个字符只会被统计一次。如果用户输入的序列是 xxxxxfflxxx,则统计结果是 ff:1 次、fl:0 次、fi:0 次。如果用户输入的序列是 xxxxxfiffffflxxx,则统计结果是 ff:2 次、fl:1 次、fi:1 次。

    cin.ignore():C++跳过(忽略)指定字符

    满足题意的程序如下:

    #include <iostream>
    
    using namespace std;
    
    int main() {
        unsigned int ffCnt = 0, flCnt = 0, fiCnt = 0;
        char ch, prech = '';
        cout << "请输入一段文本:" << endl;
        while (cin >> ch && ch != 'Q') {
            if (prech == 'f') {
                switch (ch) {
                    case 'f':
                        ++ffCnt;
                        cin.ignore();     // 跳过一个字符,即跳过当前字符 'f'
                        break;
                    case 'l':
                        ++flCnt;
                        cin.ignore();     // 跳过当前字符 'l'
                        break;
                    case 'i':
                        ++fiCnt;
                        cin.ignore();     // 跳过当前字符 'i'
                        break;
                }
            }
            prech = ch;
        }
        cout << "ff 的数量是:" << ffCnt << endl;
        cout << "fl 的数量是:" << flCnt << endl;
        cout << "fi 的数量是:" << fiCnt << endl;
    
        return 0;
    }
    
    // 测试样例一,运行结果
    请输入一段文本:
    xxxxxfflxxx Q
    ff 的数量是:1
    fl 的数量是:0
    fi 的数量是:0
    
    Process finished with exit code 0
    
    // 测试样例二,运行结果
    请输入一段文本:
    xxxxxfiffffflxxx Q
    ff 的数量是:2
    fl 的数量是:0
    fi 的数量是:1
    
    Process finished with exit code 0
    

    注:该程序测试样例二输出不符合预期。调试发现 ignore() 函数没理解明白,所以这里该函数的运用还是存在问题。随后理解的加深,再看此情况。

    一个字符不只会被统计一次。程序如下:

    #include <iostream>
    
    using namespace std;
    
    int main() {
        unsigned int ffCnt = 0, flCnt = 0, fiCnt = 0;
        char ch, prech = '';
        cout << "请输入一段文本:" << endl;
        while (cin >> ch && ch != 'Q') {
            if (prech == 'f') {
                switch (ch) {
                    case 'f':
                        ++ffCnt;
                        break;
                    case 'l':
                        ++flCnt;
                        break;
                    case 'i':
                        ++fiCnt;
                        break;
                }
            }
            prech = ch;
        }
        cout << "ff 的数量是:" << ffCnt << endl;
        cout << "fl 的数量是:" << flCnt << endl;
        cout << "fi 的数量是:" << fiCnt << endl;
    
        return 0;
    }
    
    // 测试样例一,运行结果
    请输入一段文本:
    xxxxxfflxxx Q
    ff 的数量是:1
    fl 的数量是:1
    fi 的数量是:0
    
    Process finished with exit code 0
    
    // 测试样例二,运行结果
    请输入一段文本:
    xxxxxfiffffflxxx Q
    ff 的数量是:4
    fl 的数量是:1
    fi 的数量是:1
    
    Process finished with exit code 0
    

    5.13

    【出题思路】

    switch 语句有几个语法要点:必须在必要的地方使用 break; 语句,应该把变量定义在块作用域内,case 标签只能有一个值且不能是变量(整型常量)。

    【解答】

    (a)的错误是在每个 case 分支中都缺少了 break; 语句,造成的后果是一旦执行了前面的 case 分支,必定还会继续执行接下来的其他 case 分支。举例说明,如果 ch 的内容是字符 a ,则 aCnt、eCnt 和 iouCnt 的值都会增加;如果 ch 的内容是字符 e ,则 eCnt 和 iouCnt 的值都会增加,这显然与程序的预期是不相符的。

    修改后的程序如下所示:

    unsigned aCnt = 0, eCnt = 0, iouCnt = 0;
    char ch = next_text();
    switch (ch) {
      case 'a':
        aCnt++;
        break;
      case 'e':
        eCnt++;
        break;
      default:
        iouCnt++;
        break;
    }
    

    (b)的错误是在 case 分支中定义并初始化了变量 ix,同时在 default 分支中使用了该变量,此时如果控制流跳过 case 分支而直接到达 default 分支,则会试图使用未经初始化的变量,因而该程序无法通过编译。解决办法是,把 ix 的定义放在 switch 语句之前。

    修改后的程序如下所示:

    unsigned index = some_value();
    int ix;
    switch (index) {
      case 1:
        ix = get_value();
        ivec[ix] = index;
        break;
      default:
        ix = ivec.size() - 1;
        ivec[ix] = index;
    }
    

    (c)的错误是在同一个 case 标签中放置了多个值,而 C++ 规定一个 case 标签只能对应一个值。修改后的程序如下所示:

    unsigned evenCnt = 0, oddCnt = 0;
    int digit = get_num() % 10;
    switch (digit) {
      case 1:
      case 3:
      case 5:
      case 7:
      case 9:
        oddCnt++;
        break;
      case 2:
      case 4:
      case 6:
      case 8:
        evenCnt++;
        break;
    }
    

    (d)的错误是使用变量作为 case 标签的内容,C++ 规定,case 标签的内容只能是整型常量表达式。修改后的程序如下所示:

    const unsigned ival = 512, jval = 1024, kval = 4096;
    unsigned bufsize;
    unsigned swt = get_bufCnt();
    switch (swt) {
      case ival:
        bufsize = ival * sizeof(int);
        break;
      case jval:
        bufsize = jval * sizeof(int);
        break;
      case kval:
        bufsize = kval * sizeof(int);
        break;
    }
    

    5.14

    【出题思路】

    使用 while 循环遍历用户输入的每一个字符串,根据当前字符串与上一个字符串是否相等决定如何更新各个变量的状态。如果相等,判断当前字符串连续出现的次数是否已经超过了系统记录的值,如果超过则及时更新。

    【解答】

    满足题意的程序如下所示:

    #include <iostream>
    #include <string>
    
    using namespace std;
    
    int main() {
        // 定义 3 个字符串变量,分别表示:
        // 当前操作的字符串、前一个字符串、当前出现次数最多的字符串
        string currString, preString = "", maxString;
        // 定义 2 个整型变量,分别表示:
        // 当前连续出现的字符串数量、当前出现次数最多的字符串数量
        int currCnt = 1, maxCnt = 0;
        while (cin >> currString && currString != "Q") { // 检查每个字符串
            // 如果当前字符串与前一个字符串一致,更新状态
            if (currString == preString) {
                ++currCnt;
                if (currCnt > maxCnt) {
                    maxCnt = currCnt;
                    maxString = currString;
                }
            } else {
                // 如果当前字符串与前一个字符串不一致,重置 currCnt
                currCnt = 1;
            }
            // 更新 preString 以便于下一次循环使用
            preString = currString;
        }
        if (maxCnt > 1)
            cout << "出现最多的字符串是:" << maxString
                 << ",次数是:" << maxCnt << endl;
        else
            cout << "每个字符串都只出现了一次" << endl;
        return 0;
    }
    
    // 运行结果
    how now now now brown cow cow Q
    出现最多的字符串是:now,次数是:3
    
    Process finished with exit code 0
    

    5.15

    【出题思路】

    理解 for 循环的语法规则,特别是 for 循环控制结构中三条语句的作用。理解循环控制变量与循环终止条件的关系,从而能够判断循环是否会无限执行下去。

    【解答】

    (a)的错误是在 for 语句中定义了变量 ix,然后试图在 for 语句之外继续使用 ix。因为 ix 定义在 for 语句的内部,所以其作用域仅限于 for 循环体。在 if 语句中 ix 已经失效,因此程序无法编译通过。

    修改后的程序如下:

    int ix;
    for (ix = 0; ix != sz; ++ix) { /* ... */ }
    if (ix != sz)
    // ...
    

    (b)的错误有两个,一是变量 ix 未经初始化就直接使用,二是 for 语句的控制结构缺少一句话,在语法上是错误的。

    修改后的程序如下:

    int ix;
    for (ix = 0; ix != sz; ++ix) { /* ... */ }
    

    (c)的错误是一旦进入循环,程序就会无休止地执行下去。也就是说,当初始情况下 ix != sz 时,由题意可知 ix 和 sz 一直同步增长,循环的终止条件永远不会满足,所以该循环是一个死循环。

    修改后的程序如下:

    for (int ix = 0; ix != sz; ++ix) { /* ... */ }
    

    5.16

    【出题思路】

    一般情况下,while 循环和 for 循环可以相互转换,不论哪种循环形式关键点都有三个:循环控制变量的初始值、循环控制变量的变化规则、循环终止条件。编写循环语句时除了要满足应用的需求,还必须时刻关注循环控制变量和循环终止条件,谨防写出死循环。

    【解答】

    从标准输入流读取数据的程序一般使用 while 循环,其形式是:

    char ch;
    while (cin >> ch) {
        /* ... */
    }
    

    因为这项功能事实上不太要求我们严格跟踪循环变量的变化过程,所以改写成 for 循环后稍显冗余:

    for ( ; cin >> ch; ){
        /* ... */
    }
    

    请注意:在上面的 for 循环控制结构中,第一条语句和第三条语句都是空语句,额外添加一个循环控制变量(比如 int i)是没有意义的。

    整数累加求和的程序一般使用 for 循环,其形式是:

    int iCount = 0;
    for (int i = 0; i < 10; ++i) {
        iCount += i;
    }
    

    使用 while 循环改写后的形式是:

    int iCount = 0, i = 0;
    while (i < 10) {
        iCount += i;
        ++i;
    }
    

    在大多数情况下,两种循环形式可以相互转换。如果只能使用一种循环,作者倾向于使用 for 循环。for 循环的优点是结构严谨,便于控制程序的逻辑。

    5.17

    【出题思路】

    使用 while 循环实现两个 vector 对象的逐元素比较。

    【解答】

    满足题意的程序如下所示:

    #include <iostream>
    #include <vector>
    
    using namespace std;
    
    int main() {
        vector<int> v1, v2;
        // 这里表示输入的变量之所以没有用 int 类型
        // 是因为想用字符 'Q' 结束每个 vector 的输入
        char c;
        cout << "请输入 v1 的一组整数值:";
        while (cin >> c && c != 'Q')
            v1.push_back(c);
        cout << "请输入 v2 的一组整数值:";
        while (cin >> c && c != 'Q')
            v2.push_back(c);
    
        auto it1 = v1.cbegin();     // 定义 v1 的迭代器
        auto it2 = v2.cbegin();     // 定义 v2 的迭代器
    
        // 设定循环条件:v1 和 v2 都尚未检查完
        while (it1 != v1.cend() && it2 != v2.cend()) {
            // 如果当前位置的两个元素不相等,则肯定没有前缀关系,退出循环
            if (*it1 != *it2) {
                cout << "v1 和 v2 之间不存在前缀关系" << endl;
                break;
            }
            ++it1;                  // 迭代器移动到下一个元素
            ++it2;                  // 迭代器移动到下一个元素
        }
    
        if (it1 == v1.cend())       // 如果 v1 较短
            cout << "v1 是 v2 的前缀" << endl;
    
        if (it2 == v2.cend())       // 如果 v2 较短
            cout << "v2 是 v1 的前缀" << endl;
    
        return 0;
    }
    
    // 测试数据一,运行结果
    请输入 v1 的一组整数值:0 1 1 2 Q
    请输入 v2 的一组整数值:0 1 1 2 3 5 8 Q
    v1 是 v2 的前缀
    
    Process finished with exit code 0
      
    // 测试数据二,运行结果
    请输入 v1 的一组整数值:3 5 8 Q
    请输入 v2 的一组整数值:3 5 0 9 2 7 Q
    v1 和 v2 之间不存在前缀关系
    
    Process finished with exit code 0
    

    5.18

    【出题思路】

    理解 do-while 循环的语法规则。do-while 与 while 的最主要区别是:do-while 语句至少会执行一次循环体;而 while 有可能一次都不执行循环体。

    【解答】

    (a)的含义是每次循环读入两个整数并输出它们的和。因为 do-while 语句的循环体必须是一条语句或者一个语句块,所以在本题中应该把循环体的内容用花括号括起来。修改后的程序是:

    do {
      int v1, v2;
      cout << "Please enter two numbers to sum:";
      if (cin >> v1 >> v2)
        cout << "Sum is: " << v1 + v2 << endl;
    } while (cin);
    

    (b)的含义是当 get_response 的返回值不为 0 时执行循环体。因为出现在 do-while 语句条件部分的变量必须定义在循环体之外,所以该程序是错误的。修改后的程序是:

    int ival;
    do {
      ival = get_response();
    } while (ival);
    

    (c)的含义是当 get_response 的返回值不为 0 时执行循环体。因为出现在 do-while 语句条件部分的变量必须定义在循环体之外,所以该程序是错误的。修改后的程序是:

    int ival;
    do {
      ival = get_response();
    } while (ival);
    

    5.19

    【出题思路】

    把题目要求的任务写在 do-while 循环体中即可,该程序至少会执行一次比较操作。把字符串定义成 string 对象,调用 size 函数即可得到 string 对象的长度。

    【解答】

    满足题意的程序如下所示:

    #include <iostream>
    #include <string>
    
    using namespace std;
    
    int main() {
        do {
            cout << "请输入两个字符串:" << endl;
            string str1, str2;
            cin >> str1 >> str2;
            if (str1.size() < str2.size())
                cout << "长度较小的字符串是:" << str1 << endl;
            else if (str1.size() > str2.size())
                cout << "长度较小的字符串是:" << str2 << endl;
            else
                cout << "两个字符串等长" << endl;
        } while (cin);
    
        return 0;
    }
    
    // 运行结果
    请输入两个字符串:
    fjsk sflj
    两个字符串等长
    请输入两个字符串:
    fjskfkjg fslfkwoie
    长度较小的字符串是:fjskfkjg
    请输入两个字符串:
    
    

    5.20

    【出题思路】

    break 语句是一种跳转语句,负责终止离它最近的 while、do-while、for 和 switch 语句,并把程序的控制权交给这些语句之后的第一条语句。

    【解答】

    满足题意的程序如下所示:

    #include <iostream>
    #include <string>
    
    using namespace std;
    
    int main() {
        string currString, preString;
        bool bl = true;
        cout << "请输入一组字符串:" << endl;
        while (cin >> currString && currString != "Q") {
            if (currString == preString) {
                bl = false;
                cout << "连续出现的字符串是:" << currString << endl;
                break;
            }
            preString = currString;
        }
        if (bl)
            cout << "没有连续出现的字符串" << endl;
    
        return 0;
    }
    
    // 测试样例一,运行结果
    请输入一组字符串:
    now today tomorrow Q
    没有连续出现的字符串
    
    Process finished with exit code 0
    
    // 测试样例二,运行结果
    请输入一组字符串:
    now day day yeal Q
    连续出现的字符串是:day
    
    Process finished with exit code 0
    

    5.21

    【出题思路】

    continue 语句是一种跳转语句,负责终止最近的循环中的当前迭代并立即开始下一次迭代。与 break 语句的区别是,continue 虽然终止了当前迭代,但是并不终止循环;而 break 语句则直接跳出循环。

    【解答】

    根据题目的要求,我们首先检查读入的单词是否以大写字母开头,如果不是则终止当前迭代并开始下一次循环。满足题意的程序是:

    #include <iostream>
    #include <string>
    
    using namespace std;
    
    int main() {
        string currString, preString;
        bool bl = true;
        cout << "请输入一组字符串:" << endl;
        while (cin >> currString && currString != "Q") {
            if (!isupper(currString[0]))
                continue;
            if (currString == preString) {
                bl = false;
                cout << "连续出现的字符串是:" << currString << endl;
                break;
            }
            preString = currString;
        }
        if (bl)
            cout << "没有连续出现的字符串" << endl;
    
        return 0;
    }
    
    // 运行结果
    请输入一组字符串:
    etc Day day Now Now Q
    连续出现的字符串是:Now
    
    Process finished with exit code 0
    

    5.22

    【出题思路】

    goto 语句的作用是从 goto 语句无条件跳转到同一函数的另一条语句。但是一般情况下,不建议读者使用 goto 语句,因为它使得程序既难理解又难修改。

    【解答】

    用 do-while 语句改写后的程序如下所示:

    int sz;
    do {
      sz = get_size();
    } while (sz <= 0);
    

    5.23

    【出题思路】

    对于整数除法来说,我们必须检查除数是否为 0。在这个版本的程序中,暂时不使用 try-catch 机制,而是直接输出错误信息。

    【解答】

    满足题意的程序如下所示:

    #include <iostream>
    
    using namespace std;
    
    int main() {
        cout << "请依次输入被除数和除数:" << endl;
        int ival1, ival2;
        cin >> ival1 >> ival2;
        if (ival2 == 0) {
            cout << "除数不能为 0" << endl;
            return -1;
        }
        cout << "两数相除的结果是:" << ival1 / ival2 << endl;
    
        return 0;
    }
    

    5.24

    【出题思路】

    与上一版相比,通过抛出异常来提示用户的输入错误。

    【解答】

    满足题意的程序如下所示:

    #include <iostream>
    #include <stdexcept>
    
    using namespace std;
    
    int main() {
        cout << "请依次输入被除数和除数:" << endl;
        int ival1, ival2;
        cin >> ival1 >> ival2;
        if (ival2 == 0) {
            throw runtime_error("除数不能为 0");
        }
        cout << "两数相除的结果是:" << ival1 / ival2 << endl;
    
        return 0;
    }
    
    // 运行结果
    请依次输入被除数和除数:
    23 0
    libc++abi.dylib: terminating with uncaught exception of type std::runtime_error: 除数不能为 0
    
    Process finished with exit code 6
    

    在本题中,我们设定当检测到除数为 0 时抛出一个 runtime_error 异常,因为没有 catch 语句,所以系统只报告异常而并不处理它。在我们的编译环境中,系统给出的报错信息为 "libc++abi.dylib: terminating with uncaught exception of type std::runtime_error: 除数不能为 0"。

    5.25

    【出题思路】

    使用 try-catch 结构实现完整的异常处理机制。

    【解答】

    满足题意的程序如下所示:

    #include <iostream>
    #include <stdexcept>
    
    using namespace std;
    
    int main() {
        cout << "请依次输入被除数和除数:" << endl;
        int ival1, ival2;
        while (cin >> ival1 >> ival2) {
            try {
                if (ival1 == 0) {
                    throw runtime_error("除数不能为 0");
                }
                cout << "两数相除的结果是:" << ival1 / ival2 << endl;
            } catch (runtime_error err) {
                cout << err.what() << endl;
                cout << "需要继续吗(y or n)?";
                char ch;
                cin >> ch;
                if (!cin && ch == 'n')
                    break;      // 跳出 while 循环
            }
        }
    
        return 0;
    }
    
    // 测试样例一,运行结果
    请依次输入被除数和除数:
    2 3
    两数相除的结果是:0
    
    
    // 测试样例二,运行结果
    请依次输入被除数和除数:
    2 0
    
    Process finished with exit code 8
    
    
  • 相关阅读:
    RHEL7: How to configure a rc-local service
    安装 jemalloc for mysql
    aws rhel 7 安装GUI ,配置VNC
    官方推荐的MySQL参数设置值
    Linux HugePages及MySQL 大页配置
    Linux Transparent Huge Pages 对 Oracle 的影响
    Linux的Transparent Hugepage与关闭方法
    Linux HugePages 配置与 Oracle 性能关系说明
    How To Change Log Rate Limiting In Linux
    MySQL 8.0窗口函数
  • 原文地址:https://www.cnblogs.com/hacker-x/p/11057035.html
Copyright © 2020-2023  润新知