《C++ Primer》第5章 5.3节习题答案

《C++ Primer》第5章 语句

5.3节 条件语句

练习5.5:写一段自己的程序,使用if-else语句实现把数字成绩转换成字母成绩的要求。
【出题思路】
练习if-else语句的基本语法结构。
【解答】
满足题意的程序如下所示:

#include <iostream>

using namespace std;

int main()
{
    int grade;
    cout << "请输入您的成绩:";
    cin >> grade;
    if(grade < 0 || grade > 100)
    {
        cout << "该成绩不合法" << endl;
        return -1;
    }
    
    if(100 == grade)
    {
        cout << "等级成绩是:" << "A++" << endl;  //处理满分的情况
        return -1;
    }
    
    if(grade < 60)
    {
        cout << "等级成绩是:" << "F" << endl;  //处理不级格的情况
        return -1;
    }
    
    int iU = grade / 10;  //成绩的十位数
    int iT = grade % 10;  //成绩的个位数
    string score, level, lettergrade;
    //根据成绩的十位数字确定score
    if(9 == iU)
        score = "A";
    else if(8 == iU)
        score = "B";
    else if(7 == iU)
        score = "C";
    else
        score = "D";
    //根据成绩的个位数字确定level
    if(iT < 3)
        level = "-";
    else if(iT > 7)
        level = "+";
    else
        level = "";
    //累加求得等级成绩
    lettergrade = score + level;
    cout << "等级成绩是:" << lettergrade << endl;
    
    return 0;
}

运行结果:

 练习5.6:改写上一题的程序,使用条件运算符(参见4.7节,第134页)代替if-else语句。
【出题思路】
条件运算符可以实现与if-else语句类似的功能,当有嵌套的条件表达式时,注意其满足右结合律。
【解答】
改写了score和level的求值形式,得到满足题意的程序如下所示:

#include <iostream>

using namespace std;

int main()
{
    int grade;
    cout << "请输入您的成绩:";
    cin >> grade;
    if(grade < 0 || grade > 100)
    {
        cout << "该成绩不合法" << endl;
        return -1;
    }
    
    if(grade == 100)  //处理满分的情况
    {
        cout << "等级成绩是:" << "A++" << endl;
        return -1;
    }
    
    if(grade < 60)   //处理不级格的情况
    {
        cout << "等级成绩是:" << "F" << endl;
        return -1;
    }
    
    int iU = grade / 10;  //成绩的十位数
    int iT = grade % 10;  //成绩的个位数
    string score, level, lettergrade;
    //根据成绩的十位数字确定score
    score = (9 == iU) ? "A" : (8 == iU) ? "B" : (7 == iU) ? "C" : "D";
    //根据成绩的个位数确定level
    level = (iT < 3) ? "-" : (iT > 7) ? "+" : "";
    //累加求得等级成绩
    lettergrade = score + level;
    cout << "等级成绩是:" << lettergrade << endl;
    
    return 0;
}

运行结果:

 练习5.7:改正下列代码段中的错误。
(a)if(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";
(d)if(ival = 0)
    ival = get_value();
【出题思路】
理解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 ival;
if(ival = get_value())
    cout << "ival = " << ival << endl;
if(!ival)
    cout << "ival = 0\n";
(d)程序的原意是判断ival的值是否是0,原题使用赋值运算符的结果是把0赋给了ival,然后检验ival的值,这样使得条件永远不会满足。程序修改为:
if(ival == 0)
    ival = get_value();

练习5.8:什么是“悬垂else”?C++语言是如何处理else子句的?
【出题思路】
理解悬垂else的定义,以及C++是如何处理悬垂else的。
【解答】
悬垂else是指当程序中的if分支多于else分支时,如何为else寻找与之匹配的if分支的问题。C++规定,else与离它最近的尚未匹配的if匹配,从而消除了二义性。

练习5.9:编写一段程序,使用一系列if语句统计从cin读入的文本中有多少元音字母。
【出题思路】
if语句和switch语句是分支语句的两种形式,一般来说可以互相转化。
【解答】
满足题意的程序如下所示:

#include <iostream>

using namespace std;

int main()
{
    unsigned int vowelCnt = 0;
    char ch;
    cout << "请输入一段文本:" << endl;
    while(cin >> ch)
    {
        if('a' == ch)
            ++vowelCnt;
        if('e' == ch)
            ++vowelCnt;
        if('i' == ch)
            ++vowelCnt;
        if('o' == ch)
            ++vowelCnt;
        if('u' == ch)
            ++vowelCnt;
    }
    
    cout << "您输入的文本中共有 " << vowelCnt << " 个元音字母" << endl;
    
    return 0;
}

运行结果:

练习5.10:我们之前实现的统计元音字母的程序存在一个问题:如果元音字母以大写形式出现,不会被统计在内。编写一段程序,既统计元音字母的小写形式,也统计大写形式,也就是说,新程序遇到'a'和'A'都应该递增aCnt的值,以此类推。
【出题思路】
要实现本题的要求,只需更新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)
    {
        switch(ch)
        {
            case 'a':
            case 'A':
                ++aCnt;
                break;
            case 'e':
            case 'E':
                ++eCnt;
                break;
            case 'i':
            case 'I':
                ++eCnt;
                break;
            case 'o':
            case 'O':
                ++oCnt;
                break;
            case 'u':
            case 'U':
                ++uCnt;
                break;
            default:
                break;
        }
    }
    
    cout << "元音字母 a 的数量是:" << aCnt << endl;
    cout << "元音字母 e 的数量是:" << eCnt << endl;
    cout << "元音字母 i 的数量是:" << iCnt << endl;
    cout << "元音字母 o 的数量是:" << oCnt << endl;
    cout << "元音字母 u 的数量是:" << uCnt << endl;
    
    return 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 >> ch)
    {cout << "ch==========" << ch << endl;
        switch(ch)
        {
            case 'a':
            case 'A':
                ++aCnt;
                break;
            case 'e':
            case 'E':
                ++eCnt;
                break;
            case 'i':
            case 'I':
                ++eCnt;
                break;
            case 'o':
            case 'O':
                ++oCnt;
                break;
            case 'u':
            case 'U':
                ++uCnt;
                break;
            case ' ':
                ++spaceCnt;
                break;
            case '\t':
                ++tabCnt;
                break;
            case '\n':
                ++newlineCnt;
                break;
            default:
                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;
}

练习5.12:修改统计元音字母的程序,使其能统计以下含有两个字符的字符序列的数量:ff、fl和fi。
【出题思路】
为了统计字符序列的情况,必须记录前一个字符的内容。
【解答】
我们的设定是一个字符只会被统计一次。如果用户输入的序列是xxxxxfflxxx,则统计结果是ff:1次、fl:0次、fi:0次。如果用户输入的序列是xxxxxfiffffflxxx,则统计结果是ff:2次、fl:1次、fi:1次。满足题意的程序如下所示:

#include <iostream>

using namespace std;

int main()
{
    unsigned int ffCnt = 0, flCnt = 0, fiCnt = 0;
    char ch, prech = '\0';
    cout << "请输入一段文本:" << endl;
    while(cin >> ch)
    {
        bool b1 = true;
        if('f' == prech)
        {
            switch(ch)
            {
                case 'f':
                    ++ffCnt;
                    break;
                case 'l':
                    ++flCnt;
                    break;
                case 'i':
                    ++fiCnt;
                    break;
            }
        }
        
        if(!b1)
            prech = '\t';
        else
            prech = ch;
    }
    
    cout << "ff的数量是:" << ffCnt << endl;
    cout << "fl的数量是:" << flCnt << endl;
    cout << "fi的数量是:" << fiCnt << endl;
    
    return 0;
}

运行结果:

练习5.13:下面显示的每个程序都含有一个常见的编程错误,指出错误在哪里,然后修改它们。
(a)    unsigned aCnt = 0, eCnt = 0, iouCnt = 0;
    char ch = next_text();
    switch(ch){
        case 'a':aCnt++;
        case 'e':eCnt++;
        default:iouCnt++;
    }
(b)    unsigned index = some_value();
    switch(index){
        case 1:
            int ix = get_value();
            ivec[ix] = index;
            break;
        default:
            ix = ivec.size() - 1;
            ivec[ix] = index;
(c)    unsigned evenCnt = 0, oddCnt = 0;
    int digit = get_num() % 10;
    switch(digit) {
        case 1,3,5,7,9:
            oddcnt++;
            break;
        case 2,4,6,8,10:
            evencnt++;
            break;
    }
(d)    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;
    }
【出题思路】
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:
    case 10:
        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;

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值