练习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.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;
}
#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;
}
#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.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;
}
#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;
}
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;
}