C++ Primer(第五版)|练习题答案与解析(第五章:语句)

C++ Primer(第五版)|练习题答案与解析(第五章:语句)

本博客主要记录C++ Primer(第五版)中的练习题答案与解析。
参考:C++ Primer
C++ Primer

练习题5.1

什么是空语句,什么时候会用到?

空语句只含有一个单独的分号。一种常见的情况是:当循环的全部工作在条件部分就可以完成时,通常就会用到空语句(P154)。

练习题5.2

什么是块,什么时候会用到块?

用花括号括起来的语句和声明的序列成为块,一个块就是一个作用域。如循环体内有多条执行语句,就需要用到块,函数也需要用到块(P155)。

练习题5.3

使用逗号运算符重写while循环,使其不需要块,观察改写之后代码可读性提高还是降低了。

重写后:while (val <= 10) sum += val, ++val;可读性并没有提高,使用块更易读。

练习题5.4

说明下列例子的含义,如果存在问题,试着修改。

(a) while (string::iterator iter != s.end()) { /* ... */ }iter没有指向,直接判断其不等于s.end()是非法的。

(b)while ( bool status = find(word) ) {/* ... */ } if ( !status ) { /* ... */ }while执行的条件就是status为真,status取反为假,因此if判断永远不成立。

练习题5.5

写一段自己的程序,使用if else语句实现把数字成绩转化为字母成绩的要求。

代码:

#include 
#include 
#include 
#include 

using namespace std;
int main()
{
    vector<string> scores = { "F", "D", "C", "B", "A", "A++" };
    for (int g; cin >> g;)
    {
        string letter;
        if (g < 60)
        {
            letter = scores[0];
        }
        else
        {
            letter = scores[(g - 50) / 10];
            if (g != 100)
                letter += g % 10 > 7 ? "+" : g % 10 < 3 ? "-" : "";
        }
        cout << letter << endl;
    }

    return 0;
}

测试:

60
D-
75
C
88
B+

练习题5.6

改写上题程序,使用条件运算符代替if-else语句。

代码

#include 
#include 
#include 
#include 

using namespace std;
int main()
{
    vector<string> scores = { "F", "D", "C", "B", "A", "A++" };

    int grade = 0;
    while (cin >> grade)
    {
        string lettergrade = grade < 60 ? scores[0] : scores[(grade - 50) / 10];
        lettergrade += (grade == 100 || grade < 60) ? "" : (grade % 10 > 7) ? "+" : (grade % 10 < 3) ? "-" : "";
        cout << lettergrade << endl;
    }

    return 0;
}

练习题5.7

改正下面代码段中的错误。

(a)

if (ival1 != ival2)
        ival1 = ival2//ival1 = ival2少了分号,修改为:ival1 = ival2;
else  ival1 = ival2 = 0;  

(b)

if (ival < minval)
            minval  = ival;
			occurs = 1;//这里没有加花括号,否则不在一个块内执行 

(c)

if (int ival = get_value())
     cout << "ival = " << ival << endl;
if (!ival)
     cout << "ival = 0\n";// 第二个if中的ival未定义,ival的作用域仅限于第一个if循环中

(d)

if (ival = 0)
      ival = get_value(); // if中的判断应写为if (ival == 0)或 if (0 == ival)

练习题5.8

什么是“悬垂else”?c++语言是如何处理else字句的?

当if语句嵌套时,可能会出现if语句的数量大于else语句的情况,这时,我们如何确定给定的else是和哪个if匹配的呢?这个问题就称作悬垂else。c++中规定,else与离它最近且尚未匹配的if语句匹配(P158)。

练习题5.9

编写一段程序,使用if语句统计从cin读入的文本中有多少元音字母。

代码:

#include 
#include 
#include 
#include 

using namespace std;
int main()
{
    unsigned aCnt = 0, eCnt = 0, iCnt = 0, oCnt = 0, uCnt = 0;
    char ch;
    while (cin >> ch)
    {
        if (ch == 'a') ++aCnt;
        else if (ch == 'e') ++eCnt;
        else if (ch == 'i') ++iCnt;
        else if (ch == 'o') ++oCnt;
        else if (ch == 'u') ++uCnt;
    }
    cout << "Number of vowel a: \t" << aCnt << '\n'
        << "Number of vowel e: \t" << eCnt << '\n'
        << "Number of vowel i: \t" << iCnt << '\n'
        << "Number of vowel o: \t" << oCnt << '\n'
        << "Number of vowel u: \t" << uCnt << endl;

    return 0;
}

测试:

a
e
d
^Z
Number of vowel a:      1
Number of vowel e:      1
Number of vowel i:      0
Number of vowel o:      0
Number of vowel u:      0

练习题5.10

上述代码有一个问题,如果是大写字母则不会被统计在内。编写程序,使大写字母和小写字母都能够统计在内。

代码:

#include 
#include 
#include 
#include 

using namespace std;
int main()
{
    unsigned aCnt = 0, eCnt = 0, iCnt = 0, oCnt = 0, uCnt = 0;
    char ch;
    while (cin >> ch)
        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 << "Number of vowel a(A): \t" << aCnt << '\n'
         << "Number of vowel e(E): \t" << eCnt << '\n'
         << "Number of vowel i(I): \t" << iCnt << '\n'
         << "Number of vowel o(O): \t" << oCnt << '\n'
         << "Number of vowel u(U): \t" << uCnt << endl;

    return 0;
}

测试:

A
a
c
D
e
^Z
Number of vowel a(A):   2
Number of vowel e(E):   1
Number of vowel i(I):   0
Number of vowel o(O):   0
Number of vowel u(U):   0

练习题5.11

修改统计元音字母的程序,使其也能统计空格、制表符和换行符的数量。

代码:

#include 
#include 
#include 
#include 

using namespace std;
int main()
{
    unsigned aCnt = 0, eCnt = 0, iCnt = 0, oCnt = 0, uCnt = 0, spaceCnt = 0, tabCnt = 0, newLineCnt = 0;
    char ch;
    while (cin >> std::noskipws >> ch)
        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 '\t':
                ++tabCnt;
                break;
            case '\n':
                ++newLineCnt;
                break;
        }

    cout << "Number of vowel a(A): \t" << aCnt << '\n'
        << "Number of vowel e(E): \t" << eCnt << '\n'
        << "Number of vowel i(I): \t" << iCnt << '\n'
        << "Number of vowel o(O): \t" << oCnt << '\n'
        << "Number of vowel u(U): \t" << uCnt << '\n'
        << "Number of space: \t" << spaceCnt << '\n'
        << "Number of tab char: \t" << tabCnt << '\n'
        << "Number of new line: \t" << newLineCnt << endl;

    return 0;
}

测试:

a
d
A
E


^Z
Number of vowel a(A):   2
Number of vowel e(E):   1
Number of vowel i(I):   0
Number of vowel o(O):   0
Number of vowel u(U):   0
Number of space:        0
Number of tab char:     1
Number of new line:     6

注意cin要使用noskipws,noskipws会告诉istream读取字符时不要跳过空白符。

练习题5.12

修改统计元音字母的程序,使其能统计以下含有两个字符的字符序列的数量:ff,fl, fi

代码:

#include 
#include 
#include 
#include 

using namespace std;
int main()
{
    unsigned aCnt = 0, eCnt = 0, iCnt = 0, oCnt = 0, uCnt = 0, spaceCnt = 0, tabCnt = 0, newLineCnt = 0, ffCnt = 0, flCnt = 0, fiCnt = 0;
    char ch, prech = '\0';
    while (cin >> std::noskipws >> ch)
    {
        switch (ch)
        {
            case 'a':
            case 'A':
                ++aCnt;
                break;
            case 'e':
            case 'E':
                ++eCnt;
                break;
            case 'i':
                if (prech == 'f') ++fiCnt;
            case 'I':
                ++iCnt;
                break;
            case 'o':
            case 'O':
                ++oCnt;
                break;
            case 'u':
            case 'U':
                ++uCnt;
                break;
            case ' ':
                ++spaceCnt;
                break;
            case '\t':
                ++tabCnt;
                break;
            case '\n':
                ++newLineCnt;
                break;
            case 'f':
                if (prech == 'f') ++ffCnt;
                break;
            case 'l':
                if (prech == 'f') ++flCnt;
                break;
        }
        prech = ch;
    }
    
    cout << "Number of vowel a(A): \t" << aCnt << '\n'
        << "Number of vowel e(E): \t" << eCnt << '\n'
        << "Number of vowel i(I): \t" << iCnt << '\n'
        << "Number of vowel o(O): \t" << oCnt << '\n'
        << "Number of vowel u(U): \t" << uCnt << '\n'
        << "Number of space: \t" << spaceCnt << '\n'
        << "Number of tab char: \t" << tabCnt << '\n'
        << "Number of new line: \t" << newLineCnt << '\n'
        << "Number of ff: \t" << ffCnt << '\n'
        << "Number of fl: \t" << flCnt << '\n'
        << "Number of fi: \t" << fiCnt << endl;
    
    return 0;
}

练习题5.13

下面显示的每个程序都有一个常见的编程错误,指出错误在哪里,然后修改它们。

(a)添加break;
(b)ix应在外部声明定义
(c)不能用逗号加以表示包括case 1 : case 2: case : 3
(d)case 后面需要加的是常量表达式,可以加const修饰符,将ival、jval、kval变成”常量“

练习题5.14

从标准库中读取若干string对象并查询连续重复出现的单词。

代码:

#include 
#include 
#include 
#include 

using namespace std;
int main()
{
    pair<string, int> max_duplicated;
    int count = 0;
    for (string str, prestr; cin >> str; prestr = str)
    {
        if (str == prestr) ++count;
        else count = 0;
        if (count > max_duplicated.second) max_duplicated = { prestr, count };
    }

    if (max_duplicated.first.empty()) cout << "There's no duplicated string." << endl;
    else cout << "the word " << max_duplicated.first << " occurred " << max_duplicated.second + 1 << " times. " << endl;

    return 0;
}

测试:

how now now now brown cow cow
^Z
the word now occurred 3 times.

练习题5.15

说明下面循环的含义并改正其错误。

(a)

for(int ix = 0; ix != sz; ++ ix) {...}    
if (ix != sz)         // for循环结束的条件是ix == sz,因此if语句永远不成立。
 // ...

(b)

int ix;
for (ix != sz; ++ix) {/* ... */}        // 省略了初始化语句必须要有“;”,表示一个空语句。

(c)

for (int ix = 0; ix != sz; ++ix; ++ sz) {/* ... */}        // ++ix和++sz同时执行,则for会一直循环下去。

练习题5.17

假设有两个包含整数的vector对象,编写一段程序,检验其中一个vector的对象是否为另一个的前缀。为了实现这一目标,对于两个不等长的vector,只需挑出长度较短的那个,把它的所有元素和另一个vector对象比较即可。例如,两个vector的元素分别是0、1、1、2和0、1、1、2、3、5、8,则程序的返回结果应该为真。

代码:

#include 
#include 
#include 
#include 

using namespace std;
bool is_prefix(vector<int> const& lhs, vector<int> const& rhs)
{
    if(lhs.size() > rhs.size())
        return is_prefix(rhs, lhs);
    for(unsigned i = 0; i != lhs.size(); ++i)
        if(lhs[i] != rhs[i]) return false;
    return true;
}

int main()
{
    vector<int> l{ 0, 1, 1, 2 };
    vector<int> r{ 0, 1, 1, 2, 3, 5, 8 };
    cout << (is_prefix(r, l) ? "yes\n" : "no\n");

    return 0;
}

练习题5.18

说明循环含义并指出错误

(a)do需要使用花括号包含后面的语句,使其成为一个块。
(b)因为在do循环体中还需要使用到ival这个变量(作为判断条件),所以应该将其定义在循环体外部。
(c)同上

练习题5.19

使用do while执行:提示用户输入两个string对象,然后跳出较短的那个并输出它。

代码:

#include 
#include 
#include 
#include 

using namespace std;
int main()
{
    string rsp;
    do {
        cout << "Input two strings: ";
        string str1, str2;
        cin >> str1 >> str2;
        cout << (str1 <= str2 ? str1 : str2)
             << " is less than the other. " << "\n\n"
             << "More? Enter yes or no: ";
        cin >> rsp;
    } while (!rsp.empty() && tolower(rsp[0]) == 'y');
    return 0;
}

测试

Input two strings: asd asde
asd is less than the other.

More? Enter yes or no: n

练习题5.20

从标准输入中读取string对象的序列直到连续出现两个相同的单词或者所有单词都读完为止。使用while循环一次读取一个单词,当一个单词连续出现两次时使用break语句终止循环。输出连续重复的单词,或者输出一个消息说明没有任何单词重复。

代码:

#include 
#include 
#include 
#include 

using namespace std;
int main()
{
    string read, tmp;
    while (cin >> read)
        if (read == tmp) break; else tmp = read;

    if (cin.eof())  cout << "no word was repeated." << endl;
    else            cout << read << " occurs twice in succession." << endl;

    return 0;
}

测试

abc abc
abc occurs twice in succession.

练习题5.21

修改P171练习题的程序,使其找到的重复单词必须以大写字母开头

代码:

#include 
#include 
#include 
#include 

using namespace std;
int main()
{
    string curr, prev;
    bool no_twice = true;
    while (cin >> curr)
    {
        if (isupper(curr[0]) && prev == curr)
        {
            cout << curr << ": occurs twice in succession." << endl;
            no_twice = false;
            break;
        }
        prev = curr;
    }

    if (no_twice)
        cout << "no word was repeated." << endl;

    return 0;
}

测试:

Abc
Abc
Abc: occurs twice in succession.

练习题5.23

从标准输入读入两个整数,输出第一个数除以第二个数的结果

代码:

#include 
using std::cin;
using std::cout;
using std::endl;

int main() 
{
    int i, j; 
    cin >> i >> j;
    cout << i / j << endl;
 
    return 0;
}

练习题5.24

修改程序,当第二个数是0时抛出异常。

代码:

#include 
#include 


int main(void)
{
    int i, j;
    std::cin >> i >> j;
    if (j == 0)
        throw std::runtime_error("divisor is 0");
    std::cout << i / j << std::endl;

    return 0;
}

测试

1
0
terminate called after throwing an instance of 'std::runtime_error'
  what():  divisor is 0

练习题5.25

修改程序,使用try语句块捕获异常。catch子句应该为用户输出一条提示信息,询问是否输入新数并重新执行try语句块的内容。

代码:

#include 
#include 
using std::cin; using std::cout; using std::endl; using std::runtime_error;

int main(void)
{
    for (int i, j; cout << "Input two integers:\n", cin >> i >> j; )
    {
        try
        {
            if (j == 0)
                throw runtime_error("divisor is 0");
            cout << i / j << endl;
        }
        catch (runtime_error err)
        {
            cout << err.what() << "\nTry again? Enter y or n" << endl;
            char c;
            cin >> c;
            if (!cin || c == 'n')
                break;
        }
    }

    return 0;
}

测试:

Input two integers:
1
0
divisor is 0
Try again? Enter y or n
n

你可能感兴趣的:(C++,Primer,自学)