C++primer习题集(第五章)

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

空语句就是只有一个分号";"的语句
最常见的,是在循环里面省略一些内容,例如for(;i<10;i++)

 


 

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

一个“块”通常指的是一段被花括号({})包围的代码,也称为代码块。
代码块可以包含一组相关的语句,通常用于定义函数、循环、条件语句等。
有时候语法上只需要一条句子,逻辑上需要多个句子,例如循环中,可能包含了多句话,就需要用块把它包起来

 


 

5.3 使用逗号运算符(140页)重写1.4.1节(10页)的while循环,使他不需要块,观察修改之后的代码可读性提高了还是降低了。

#include<iostream>
using namespace std;

int main()
{
    int sum = 0, val = 1;
    while (val <= 10)
        sum += val, ++val;
    cout << "Sum of 1 to 10 inclusive is " << sum << 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) { /* . . . */ }
    /*
    if()语句中的status,超出了作用域
    bool status;
    while (status = find(word)) {  . . .  }
    if (!status) {  . . .  }
    */

 


 

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

#include<iostream>
#include<vector>
using namespace std;

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

    string lettergrade;
    if(grade<60)
        lettergrade=scores[0];
    else if(grade<70)
        lettergrade=scores[1];
    else if(grade<80)
        lettergrade=scores[2];
    else if(grade<90)
        lettergrade=scores[3];
    else if(grade<100)
        lettergrade=scores[4];
    else if(grade==100)
        lettergrade=scores[5];
    else
        cout<<"error!"<<endl;
    return 0;
}

 


 

5.6 改写上一题的程序,使用条件运算符(134页)代替if else语句。

#include<iostream>
#include<vector>
using namespace std;

int main()
{
    int grade=99;
    const vector<string> scores={"F","D","C","B","A","A++"};

    string lettergrade;
    lettergrade=grade<60?scores[0]:
                grade<70?scores[1]:
                grade<80?scores[2]:
                grade<90?scores[3]:
                grade<100?scores[4]:
                grade==100?scores[5]:"ERROR";
    cout<<lettergrade<<endl;
    return 0;
}

 


 

5.7 改写下列代码段中的错误。

    //a     ival1=ival2;        这里要加分号
    if(ival1 != ival2)
        ival1 = ival2
    else ival1=ival2=0;
    
    //b     {minval=ival; occurs=1;} if后面多条语句要用块
    if(ival<minval)
        minval=ival;
        occurs=1;
    //c     ival超出作用域了,应该在最外面定义int ival
    if(int ival=get_value())
        cout<<"ival="<<ival<<endl;
    if(!ival)
        cout<<"ival=0\n";
    //d     ival==0才是判断,ival=0是赋值,必为1
    if(ival=0)
        ival=getvalue();

 


 

5.8 什么叫“悬垂else”?C++是如何处理else子句的?

悬垂else是指在多个if嵌套的时候,出现一个else不知道是对应哪个if的
C++处理方式是,选择上方最近的还尚未匹配的if进行匹配

 


 

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

#include<iostream>
#include<vector>
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 <<endl
        << "Number of vowel e: \t" << eCnt <<endl
        << "Number of vowel i: \t" << iCnt <<endl
        << "Number of vowel o: \t" << oCnt <<endl
        << "Number of vowel u: \t" << uCnt <<endl;

    return 0;
}

 


 

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

#include <iostream>
using std::cin;
using std::cout;
using std::endl;
 
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;
}

 


 

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

#include <iostream>
using std::cin;
using std::cout;
using std::endl;

int main()
{
    unsigned aCnt = 0, eCnt = 0, iCnt = 0, oCnt = 0, uCnt = 0;
    unsigned blankCnt=0,tCnt=0,nCnt=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 ' ':
            ++blankCnt;
            break;
        case '\t':
            ++tCnt;
            break;
        case '\n':
            ++nCnt;
            break;
        }

    cout << "Number of vowel a(A): \t" << aCnt << endl
         << "Number of vowel e(E): \t" << eCnt << endl
         << "Number of vowel i(I): \t" << iCnt << endl
         << "Number of vowel o(O): \t" << oCnt << endl
         << "Number of vowel u(U): \t" << uCnt << endl
         << "Number of vowel ' ' : \t" << blankCnt << endl
         << "Number of vowel '\\t': \t" << tCnt << endl
         << "Number of vowel '\\n': \t" << nCnt << endl;

    return 0;
}

 


 

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

#include <iostream>
using std::cin;
using std::cout;
using std::endl;

int main()
{
    unsigned aCnt = 0, eCnt = 0, iCnt = 0, oCnt = 0, uCnt = 0;
    unsigned blankCnt = 0,tCnt = 0,nCnt = 0;
    unsigned 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 ' ':
            ++blankCnt;
            break;
        case '\t':
            ++tCnt;
            break;
        case '\n':
            ++nCnt;
            break;
        case 'l':
            if (prech == 'f') ++flCnt;
            break;
        case 'f':
            if (prech == 'f') ++ffCnt;
            break;
        }
        prech=ch;
    }
    cout << "Number of vowel a(A): \t" << aCnt << endl
         << "Number of vowel e(E): \t" << eCnt << endl
         << "Number of vowel i(I): \t" << iCnt << endl
         << "Number of vowel o(O): \t" << oCnt << endl
         << "Number of vowel u(U): \t" << uCnt << endl
         << "Number of vowel ' ' : \t" << blankCnt << endl
         << "Number of vowel '\\t': \t" << tCnt << endl
         << "Number of vowel '\\n': \t" << nCnt << endl
         << "Number of vowel 'ff': \t" << ffCnt << endl
         << "Number of vowel 'fl': \t" << flCnt << endl
         << "Number of vowel 'fi': \t" << fiCnt << endl;

    return 0;
}

 


 

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

    /*a     缺少了break语句 
    unsigned aCnt = 0, eCnt = 0, iouCnt = 0;
    char ch = next_text();
    switch (ch) {
        case 'a': aCnt++; 
        case 'e': eCnt++; 
        default : 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     ix的作用域被局限在了case1里面,应该在外面进行申明
    unsigned index = some_value();
    switch (index) {
        case 1:
            int ix = get_value();
            ivec[ ix ] = index;
            break;
        default:
            ix = static_cast<int>(ivec.size())-1;
            ivec[ ix ] = index;
    }
    */
    unsigned index = some_value();
    int ix;
    switch (index) {
        case 1:
            ix = get_value();
            ivec[ ix ] = index;
            break;
        default:
            ix = static_cast<int>(ivec.size())-1;
            ivec[ ix ] = index;
    }
    
    /*c     不能这样列举,要case 1: case 3:····
    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, 0:
            evencnt++;
            break;
    }
    */
    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 0:
            evencnt++;
            break;
    }

    /*d 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;
    }
    */
    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 编写一段程序,从标准输入中读取若干string对象并查找连续重复出现的单词,所谓连续重复出现的意思是:一个单词后面紧跟着这个单词本身。要求记录连续重复出现的最大次数以及对应的单词。如果这样的单词存在,输出重复出现的最大次数;如果不存在,输出一条信息说明任何单词都没有连续出现过。例如:如果输入是:how now now now brown cow cow那么输出应该表明单词now连续出现了3次。

#include <iostream>
#include<string>
using namespace std;

int main()
{
    string cur_word,pre_word=" ",max_word;
    int cur_num=1,max_num=0;
    while(cin>>cur_word){
        if(cur_word==pre_word)
            cur_num++;
        else
            cur_num=1;
        if(cur_num>max_num){
            max_num=cur_num;
            max_word=cur_word;
        }
        pre_word=cur_word;
    }
    cout<<max_word<<":"<<max_num<<endl;
    return 0;
}

 


 

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

    /*
    (a) for (int ix = 0; ix != sz; ++ix) {  ... }
        if (ix != sz)
            // . . .
    (b) int ix;
        for (ix != sz; ++ix) { /* ...  }
    (c) for (int ix = 0; ix != sz; ++ix, ++sz) { ... }
    */
    
    //a ix在for里面定义的,for外不能使用
    int ix;
    for (ix = 0; ix != sz; ++ix)  { /* ... */ }
    if (ix != sz)
    //b for的分号少了
    int ix;
    for (; ix != sz; ++ix) { /* ... */ }
    //c 如果循环里对sz和ix无修改,那么每轮两个值同时加一会导致循环永远无法结束
    for (int ix = 0; ix != sz; ++ix) { /*...*/ }
    

 


 

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

#include <iostream>
#include<string>
using namespace std;

int main()
{
    //while
    int ival;
    int sum_while=0;
    while(cin>ival)
        sum_while+=ival;
    cout<<sum_while<<endl;;
    
    //for
    for(int i=0;i<10;i++)
        sum_for+=i;
    cout<<sum_for<<endl;
    return 0;
}

/*
改写就算了,感觉没啥必要,
在限定范围,操作灵活的时候用while
在变化固定,类似于迭代的时候用for
*/

 


 

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

#include <iostream>
#include<string>
#include<vector>
using namespace std;

int main()
{
    vector<int> v1={1,2,3,4,5};
    vector<int> v2={1,2,3,4,5,7,9};

    auto n1=v1.size(),n2=v2.size();
    for(int i=0;i<n1&&i<n2;i++){
        if(v1[i]!=v2[i]){
            cout<<"dif!"<<endl;
            return -1;
        }
    }
    cout<<"same!"<<endl;
    return 0;
}

 


 

5.18 明下列循环的含义并改正其中的错误。

    //(a)   添加大括号
    do {
        int v1, v2;
        cout << "Please enter two numbers to sum:" ;
        if (cin >> v1 >> v2)
            cout << "Sum is: " << v1 + v2 << endl;
    }while (cin);
    //(b)   应该在while外部定义ival
    int ival;
    do {
        // . . .
    } while (ival = get_response());     
    //(c)   应该在while外部定义ival
    int ival = get_response();
    do {
        ival = get_response();         
    } while (ival);

 


 

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

#include <iostream>
#include<string>
#include<vector>
using namespace std;

int main()
{
    string s1,s2;
    cout<<"input 2 strings:"<<endl;
    cin>>s1;
    cin>>s2;
    do {
        s1.size()<=s2.size() ? cout<<s1<<endl : cout<<s2<<endl;
    } while (cin>>s1>>s2);

    return 0;
}

 


 

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

#include <iostream>
#include<string>
#include<vector>
using namespace std;

int main()
{
    string s;
    string pre="";
    while(cin>>s)
    {
        if(s==pre){
            cout<<"连续两次:"<<s<<endl;
            break;
        }
        pre=s;
    }
    if(pre!=s)
        cout<<"no such 2 words!"<<endl;
    return 0;
}

 


 

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

#include <iostream>
#include<string>
#include<vector>
using namespace std;

int main()
{
    string s;
    string pre="";
    while(cin>>s)
    {
        if(s[0]<'A'|| s[0]>'Z'){
            pre=s;
            continue;
        }

        if(s==pre){
            cout<<"连续两次:"<<s<<endl;
            break;
        }
        pre=s;
    }
    if(pre!=s)
        cout<<"no such 2 words!"<<endl;
    return 0;
}

 


 

5.22 本节的最后一个例子跳回到 begin,其实使用循环能更好的完成该任务,重写这段代码,注意不再使用goto语句。// 向后跳过一个带初始化的变量定义是合法的

begin:
int sz = get_size();
if (sz <= 0) {
goto begin;
}
    int sz;
    while(sz=get_size())
    {
        if(sz>0)
            break;
    }

 


 

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

#include <iostream>

using namespace std;

int main()
{
    int a,b;
    std::cin>>a>>b;
    std::cout<<static_cast<double>(a)/b<<std::endl;
    return 0;
}

 


 

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

#include <iostream>
#include<stdexcept>
using namespace std;

int main()
{
    int a,b;
    std::cin>>a>>b;
    if(b==0)
        throw runtime_error("b=0!\n");
    std::cout<<static_cast<double>(a)/b<<std::endl;
    return 0;
}

 


 

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

#include <iostream>
#include<stdexcept>
using namespace std;

int main()
{
    int a,b;
  
while(std::cin>>a>>b) { try{ if(b==0) throw runtime_error("b=0!\n"); std::cout << static_cast<double>(a) / b << std::endl; std::cout << "请输入两个整数: "; } catch(runtime_error err){ std::cout<<err.what(); cout << "\n再试一次? 输入 y 或 n:" << endl; char c; cin >> c; if (!cin || c == 'n') break; else cout << "请输入两个整数: "; } } return 0; }

 

 



结束。

 

posted @ 2023-08-11 15:58  para_dise  阅读(27)  评论(0)    收藏  举报