C++primer习题第五章


练习5.1:什么是空语句?什么时候会用到空语句?

答:(标准)

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

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


练习5.2:什么是块?什么时候会用到块?

答:(标准)

块是指用花括号括起来的语句和声明的序列,也称为复合语句。一个块就是一个作用域,在块中引入的名字只能在块内部以及嵌套在块中的字块里访问。

如果在程序的某个地方,语法上需要一条语句,但是逻辑上需要多条语句,此时应该使用块。


练习5.3:使用逗号运算符重写1.4.1节的while循环,使它不再需要块,观察改写之后的代码的可读性提高了还是降低了。

#include

int main()
{
    int sum =0, val = 1;
    while( val <=  10 )
        sum += val, ++val;

    std::cout << "Sum of 1 to 10 inclusive is "
              << sum << std::endl;
    return 0;
}
很明显,改写部分的可读性下降了。


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

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

iter并没有赋初值。不能用来比较。

修改为:

string::iterator iter = s.begin();

while( iter != s.end() ) { /*. . . */ }


(b)while( bool status = find( word ) ) { /* . . . */}

    if( !status ) { /* . . . */}

非法。status定义在while循环内部,所以作用域仅限于while循环。不能在if语句中使用status 。

修改为:

bool status;

while( status = find( word ) {/* . . . */}

if( !status ) { /* . . . */}


练习5.5:写一段自己的程序,使用if else语句实现把数字成绩转换成字母成绩的要求。

#include
#include

using namespace std;

int main()
{
    int grade = 0;
    string letterGrade;
    vector alp = { "F", "D", "C", "B", "A", "A++"};
    cout << "请输入一个成绩:" << endl;

    while( cin >> grade && grade >=0 && grade <= 100 )
    {
        if( grade < 60 )
            letterGrade = alp[0];

        else
        {
            letterGrade = alp[ grade / 10 - 5 ];

            if( grade != 100 )
                if( grade % 10 <= 3 )
                    letterGrade += '-';
                else if( grade % 10 >=88 7 )
                    letterGrade += '+';
        }
        cout << "你的成绩等级为:" << letterGrade << endl;

        char reply;
        cout << "你仍想继续输入吗?回答: Y or N" << endl;
        if( cin >> reply && ( reply == 'y' || reply == 'Y' ) )
            cout << "请再输入一个成绩:" << endl;

        else
        {
            cout << "程序结束,拜" << endl;
            break;
        }
        cin.sync();
    }


练习5.6:改写上一题的程序,使用条件运算符代替if else语句。

#include

using namespace std;

int main()
{
    int grade = 0;
    cout << "请输入一个成绩:" << endl;

    while( cin >> grade )
    {
        if( grade < 0 || grade > 100 )
        {
            cout << "无效成绩!" << endl;
            return -1;
        }

        string letterGrade, postfix;
        int sd, td; // single digit & tens digit
        sd = grade % 10;
        td = grade / 10;

        letterGrade = ( td == 9 ) ? "A"
                                    : ( td == 8 ) ? "B"
                                                    : ( td == 7 ) ? "C"
                                                                    : ( td == 6 ) ? "D" : "";
        postfix = ( sd <= 3 ) ? "-"
                                : ( sd >= 7 ) ? "+" : "";

        letterGrade += postfix;
        if( grade == 100 )
            letterGrade = "A++";
        if( grade < 60 )
            letterGrade = "F";

        cout << "你的成绩等级是:" << letterGrade << endl;

        char reply;
        cout << "你是否想继续输入成绩?回答:Y or N 。" << endl;
        if( cin >> reply  &&  reply != 'y' && reply != 'Y'  )
        {
            cout << "程序结束,拜!" << endl;
            break;
        }
        cout << "请再输入一个成绩:" << endl;
        cin.sync();
    }
    return 0;
}

练习5.7:改正下列代码中的错误。

略了。


练习5.8:什么是“悬垂else”?C++语言是怎么处理else子句的?

(标准)

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

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


练习5.9:编写一段程序,使用一系列if语句统计从cin读入的文本中有多少元音字母?

#include

using namespace std;

int main()
{
    char ch;
    unsigned vowel_cnt = 0;
    cout << "请输入一段文本:" << endl;
    while( cin >> ch )
    {
        if( ch == 'a' || ch == 'A' )
            ++vowel_cnt;
        else if( ch == 'e' || ch == 'E' )
            ++vowel_cnt;
        else if( ch == 'i' || ch == 'I' )
            ++vowel_cnt;
        else if( ch == 'o' || ch == 'O' )
            ++vowel_cnt;
        else if( ch == 'u' || ch == 'U' )
            ++vowel_cnt;

        else
            ;
    }
    cout << "您的输入中含有元音字母的个数为:" << vowel_cnt << endl;

    return 0;
}

练习5.10:我们之前的统计元音字母的程序存在一个问题:如果原因字母以大写形式出现,不会被统计在内。编写一段程序,既统计元音字母的小写形式,也统计大写形式,也就是说,新程序遇到'a'和'A'都应该递增aCnt的值,以此类推。

#include

using namespace std;

int main()
{
    char ch;
    unsigned aCnt =0, eCnt = 0, iCnt = 0, oCnt = 0, uCnt= 0;
    cout << "请输入一段文本:" << endl;
    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;

            default:;
        }

    cout << "元音字母a/A出现了" << aCnt << "次" << endl;
    cout << "元音字母e/E出现了" << eCnt << "次" << endl;
    cout << "元音字母i/I出现了" << iCnt << "次" << endl;
    cout << "元音字母o/O出现了" << oCnt << "次" << endl;
    cout << "元音字母u/U出现了" << uCnt << "次" << endl;



    return 0;
}


练习5.11:修改统计原因字母的程序,使其也能统计空格、制表符和换行符的数量。

#include
#include
using namespace std;

int main()
{
    char ch;
    unsigned aCnt =0, eCnt = 0, iCnt = 0, oCnt = 0, uCnt= 0;
    unsigned space_Cnt = 0, t_Cnt = 0, n_Cnt = 0; //t means \t, n means \n;
    cout << "请输入一段文本:" << endl;
    /* cin会自动过滤掉不可见字符
     * 所以采用 cin.get(ch) 而不是用cin >> ch
     * 或者使用 cin >> noskipws >> ch;
    */
    while( cin.get( 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 ' ':++space_Cnt;
                     break;
            case '\t':++t_Cnt;
                     break;
            case '\n':++n_Cnt;


            default:;
        }

    cout << "元音字母a/A出现了" << aCnt << "次" << endl;
    cout << "元音字母e/E出现了" << eCnt << "次" << endl;
    cout << "元音字母i/I出现了" << iCnt << "次" << endl;
    cout << "元音字母o/O出现了" << oCnt << "次" << endl;
    cout << "元音字母u/U出现了" << uCnt << "次" << endl;

    cout << "空格出现了" << space_Cnt << "次" << endl;
    cout << "制表符出现了" << t_Cnt << "次" << endl;
    cout << "换行符出现了" << n_Cnt << "次" << endl;

    return 0;
}

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

#include

using namespace std;

int main()
{
    bool first_f = 0;
    char ch, last_ch;
    unsigned aCnt =0, eCnt = 0, iCnt = 0, oCnt = 0, uCnt= 0;
    unsigned ff_Cnt = 0, fl_Cnt = 0, fi_Cnt = 0;
    unsigned space_Cnt = 0, t_Cnt = 0, n_Cnt = 0; //t means \t, n means \n;
    cout << "请输入一段文本:" << endl;
    /* cin会自动过滤掉不可见字符
     * 所以采用 cin.get(ch) 而不是用cin >> ch
     * 或者使用 cin >> noskipws >> ch;
    */
    while( cin.get( ch ) )
    {

       switch( ch )
        {
            case 'a':
            case 'A':++aCnt;
                     break;
            case 'e':
            case 'E':++eCnt;
                     break;
            case 'i':
                if( last_ch == 'f' && first_f )
                {
                    ++fi_Cnt;
                    first_f = 0;
                }
            case 'I':++iCnt;
                     break;
            case 'o':
            case 'O':++oCnt;
                     break;
            case 'u':
            case 'U':++uCnt;
                     break;

            case 'f':
                if( first_f )
                {
                    if( last_ch == 'f' )
                    {
                        ++ff_Cnt;
                        first_f = 0;
                    }
                }
                else
                    first_f = 1;
                break;

            case 'l':
                if( last_ch == 'f' && first_f )
                 {
                    ++fl_Cnt;
                    first_f = 0;
                 }

            case ' ':++space_Cnt;
                     break;
            case '\t':++t_Cnt;
                     break;
            case '\n':++n_Cnt;


            default:;
        }
        last_ch = ch;
    }
    cout << "元音字母a/A出现了" << aCnt << "次" << endl;
    cout << "元音字母e/E出现了" << eCnt << "次" << endl;
    cout << "元音字母i/I出现了" << iCnt << "次" << endl;
    cout << "元音字母o/O出现了" << oCnt << "次" << endl;
    cout << "元音字母u/U出现了" << uCnt << "次" << endl;

    cout << "空格出现了" << space_Cnt << "次" << endl;
    cout << "制表符出现了" << t_Cnt << "次" << endl;
    cout << "换行符出现了" << n_Cnt << "次" << endl;

    cout << "ff出现了" << ff_Cnt << "次" << endl;
    cout << "fl出现了" << fl_Cnt << "次" << endl;
    cout << "fi出现了" << fi_Cnt << "次" << endl;

    return 0;
}




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

略了。


练习5.14:编写一段程序,从标准输入中读取若干string对象并查找连续重复出现的单词。所谓连续重复出现的意思是:一个单词后面紧跟着这个单词本身。要求记录连续重复出现的最大次数以及对应的单词。如果这样的单词存在,输出重复出现的最大次数;如果不存在,输出一条信息说明任何单词都没有连续出现过。

#include

using namespace std;

int main()
{
    string currStr, preStr = "", maxStr;
    unsigned cnt = 1, maxcnt = 0;
    cout << "请输入多个字符串:" << endl;
    while( cin >> currStr )
    {
        if( currStr == preStr )
        {
            ++cnt;
            if( cnt > maxcnt )
            {
                maxcnt = cnt;
                maxStr = currStr;
            }
        }
        else
        {
            preStr = currStr;
            cnt = 1;
        }
    }
    if( cnt != 1)
        cout << "连续重复出现最大次数的单词是:" << maxStr << ",它出现了"
             << maxcnt << "次" << endl;

    else
    {
        cout << "没有任何单词重复出现过!" << endl;
        return -1;
    }


    return 0;
}

练习5.15:说明下列循环的含义并改正其中的错误。

略了。


练习5.16:while循环特别适用于那种条件保持不变、反复执行操作的情况,例如,当未达到文件末尾时不断读取下一个值。for循环则更像是在按步骤迭代,它的索引值在某个范围内依次变化。根据每种循环的习惯各自编写一段程序,然后分别用另一种循环改写。如果只能使用一种循环, 你倾向于使用哪种呢?为什么?

答:大多情况下,两种循环能够相互转换。如果只用一种,倾向于使用for循环,for循环结构严谨,便于控制程序的逻辑。


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

#include
#include

using namespace std;

void IsPrefix( vector &v1, vector &v2 );

int main()
{
    vector ivec1, ivec2;
    int iData = 0;
    cout << "请分别为两个容器输入数据:" << endl;
    cout << "容器1: " ;
    while( cin >> iData )
        ivec1.push_back( iData );

    cout << endl;

    cin.clear();
    cin.sync();

    cout << "容器2:" << endl;
    while( cin >> iData )
        ivec2.push_back( iData );

    cout << endl;

    IsPrefix( ivec1, ivec2 );


    return 0;
}


void IsPrefix( vector &v1, vector &v2 )
{
    vector::size_type len;
    len = ( ( v1.size() < v2.size() )? v1.size() : v2.size() );

    decltype( len ) i;
    for( i = 0; i != len; ++i )
        if( v1[i] != v2[i] )
            break;

    if( len == v1.size() && i == len )
        cout << "容器1是容器2的前缀。" << endl;
    else if( len == v2.size() && i == len )
        cout << "容器2是容器1的前缀。" << endl;
    else
        cout << "容器1和容器2互不为对方前缀。" << endl;
}

练习5.18:说明下列循环的含义并改正其错误。

略了。


练习5.19:编写一段程序,使用do-while循环重复地执行下述任务:首先提示用户输入两个string对象,然后挑出较短的那个并输出它。

#include

using namespace std;

int main()
{
    string str1, str2;
    do
    {
        cout << "请输入两个字符串:" << endl;
        cin >> str1 >> str2;
        if( str1.size() < str2.size() )
            cout << "较短的字符串为:" << str1 < str2.size() )
            cout << "较短的字符串为:" << str2 << endl;
        else
            cout << str1 << "和" << str2 << "等长" << endl;
    }
    while( cin );

    return 0;
}

练习5.20:编写一段程序,从标准输入中读取string对象的序列直到连续出现两个相同的单词或者所有单词读完为止。
#include

using namespace std;

int main()
{
    string word, lastWord;
    bool Exist = 0;
    cout << "请输入多个单词:" << endl;
    while( cin >> word )
    {
        if( word == lastWord )
        {
            Exist = true;
            break;
        }
        lastWord = word;
    }
    if( !Exist )
    {
       cout << "不存在连续重复重现的单词。" << endl;
       return -1;
    }

    cout << "连续重复出现的单词是:" << word << endl;

    return 0;
}


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

#include
#include

using namespace std;

int main()
{
    string word, lastWord;
    bool Exist = 0;
    cout << "请输入多个单词:" << endl;
    while( cin >> word )
    {
        if( word == lastWord && isupper( word[0] ) )
        {
            Exist = true;
            break;
        }
        lastWord = word;
    }
    if( !Exist )
    {
       cout << "不存在连续重复重现的首字母大写的单词。" << endl;
       return -1;
    }

    cout << "连续重复出现的首字母大写的单词是:" << word << endl;

    return 0;
}



练习5.22:本节的最后一个例子跳回到begin,其实使用循环能更好地完成该任务。重写这段代码,注意不再使用goto语句。
int sz;

do

sz = get_size();

while( sz <= 0 );



练习5.23:编写一段程序,从标准输入读取两个整数,输出第一个数除以第二个数的结果。

略了。


练习5.24:修改你的程序,使得当第二个数是0时抛出异常。先不要设定catch子句,运行程序并真的为除数输入0,看看会发生什么?

#include
#include


using namespace std;

int main()
{
    int iva1,iva2;
    cout << "请依次输入一个被除数和除数:" << endl;
    cin >> iva1 >> iva2;
    if( iva2 == 0 )
        throw runtime_error( "除数不能为0" );
    cout << iva1 << "除以" << iva2 << "的结果为:"
         << iva1 / iva2 << endl;


    return 0;
}


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

#include

using namespace std;

int main()
{
    int iva1,iva2;
    cout << "请依次输入一个被除数和除数:" << endl;
    while( cin >> iva1 >> iva2 )
    {
        try{
            if( iva2 == 0 )
                throw runtime_error( "除数不能为0" );

            cout << iva1 << "除以" << iva2 << "的值为:"
                 << iva1 / iva2 << endl;
        }catch( runtime_error err ){
            cout << err.what() << endl;
            cout << "Try again? Enter y or n" << endl;
            char c;
            cin >> c;
        if( !cin || c == 'n' )
            break;
        }
        cout << "请依次输入一个被除数和除数:" << endl;
    }

    return 0;
}



你可能感兴趣的:(C++primer习题)