5.1 什么是空语句?何时会用到空语句?
空语句中只含有一个单独的分号,如果在程序的某个地方,语法上需要一条语句(如while和for),但逻辑上不需要,此时应该使用空语句。
5.2 什么是块,什么时候会用到块
复合语句是指用花括号括起来的(可能为空的)语句和声明的序列,复合语句也被称为块,一个块就是一个作用域。
语法上需要一条语句,但是逻辑上需要多条语句,则应该使用复合语句(块)。
5.3 使用逗号运算符重写1.4.1节的while循环,使它不再需要块,观察改写后的代码的可读性提高了还是降低了
while(val <= 10)
sum += val, ++val;
可读性降低了,虽然逗号运算符规定了求值顺序,但是如果在表达式改变了某个运算对象的值,在表达式的其他地方不要再使用这个运算对象。这里出现了val和++val,故不好
5.4 说明下列例子含义,如果存在问题,试着修改它
while(string::iterator iter != s.end()){} //a
while(bool status = find(word)){} //b
if(!status){}
a代码想要判断迭代器是否指向s尾后,但iter没有初始化
b代码想要在if中使用status,但status只在while语句中有效。
代码应修改为
string::iterator iter = s.begin();
while(iter != s.end()){}
while(bool status = find(word))
{
if(!status){}
}
5.7 改正下列代码段中的错误
(a)if(ival1 != ival2)
ival = ival2 //缺少分号
else ival1 = ival2;
(b)if(ival < minval)
minval = ival; // if语句只能控制一条语句,需加花括号将两条语句并为一个块
occurs = 1;
(c)if(int ival = get_value())
cout<<"ival = "<< ival << endl;
if(!ival) //ival作用域只在上一个if语句中,ival需要在if语句外声明
cout<<"ival = 0\n";
(d)if(ival = 0)//if语句条件表达式恒为false,故statement永不执行
ival = get_value();
改正后的代码:
(a)if(ival1 != ival2)
ival = ival2; //缺少分号
else ival1 = ival2;
(b)if(ival < minval)
{
minval = ival; // if语句只能控制一条语句,需加花括号将两条语句并为一个块
occurs = 1;
}
(c)int ival = get_value();
if(ival)
cout<<"ival = "<< ival << endl;
if(!ival) //ival作用域只在上一个if语句中,ival需要在if语句外声明
cout<<"ival = 0\n";
(d)if(ival == 0)//if语句条件表达式恒为false,故statement永不执行
ival = get_value();
5.8 什么是悬垂else?C++如何处理else子句的?
当一个if语句嵌套在另一个if语句内时,很可能if分支会多于else分支,我们怎么知道某个给定else和哪个if匹配即为悬垂else。
C++规定else与离它最近的尚未匹配的if匹配。
5.11 修改统计元音字母的程序,使其也能统计空格、制表符和换行符的数量
unsigned aCnt = 0, eCnt = 0, iCnt = 0, oCnt = 0, uCnt = 0, ffCnt = 0, flCnt = 0, fiCnt = 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;
case 'f':
{
cin >> ch;
switch (ch)
{
case 'f':
++ffCnt;
break;
case 'l':
++flCnt;
break;
case 'i':
++fiCnt;
break;
default:
break;
}
}
break;
default:
break;
}
}
cout << "Number of vowel a: " << aCnt << endl;
cout << "Number of vowel e: " << eCnt << endl;
cout << "Number of vowel i: " << iCnt << endl;
cout << "Number of vowel o: " << oCnt << endl;
cout << "Number of vowel u: " << uCnt << endl;
cout << "Number of ff: " << ffCnt << endl;
cout << "Number of fl: " << flCnt << endl;
cout << "Number of fi: " << fiCnt << endl;
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_line();
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);
}
修改后的代码:
(a)unsigned aCnt = 0, eCnt = 0, iouCnt = 0;
char ch = next_text();
switch(ch){
//与分支'a','e' 以及default 所执行的语句结尾没有break,会导致
//ch与'a'分支匹配时,aCnt,eCnt以及iouCnt都递增
case 'a' : aCnt++;break;
case 'e' : eCnt++;break;
case 'i': case 'o' : case 'u' :iouCnt++;break;
}
(b)unsigned index = some_value();
int ix;
switch(index){
case 1:
{
ix = get_line();
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标签只能是整型 常量表达式
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)constexpr unsigned ival = 512, jval = 1024, kval = 4096;
unsigned bufsize;
unsigned swt = get_bufCnt();
switch(swt){
case ival: //错误,case 标签只能是整型常量表达式,而这里是无符号整型变量
bufsize = ival * sizeof(int);
break;
case jval:
bufsize = jval * sizeof(int);
break;
case kval:
bufsize = kval * sizeof(int);
}
5.14 编写一段程序,从标准输入中读取若干string对象并查找连续重复出现的单词。所谓连续重复出现的意思是:一个单词后面紧跟着这个单词本身。要求记录连续重复出现的最大次数以及对应的单词。如果这样的单词存在,输出重复出现的最大次数,如果不存在,输出一条信息说明任何单词都没有连续出现过。如输入为: how now now now brown cow cow,那么输出应该表明now连续出现了3次。
//思路:记录前一次输入的单词。
string word, preword, wordMax;
int cnt = 0, cntMax = 0;
while (cin >> word)
{
if (preword == word)
++cnt;
else
{
if (cnt > cntMax)
{
wordMax = preword;
cntMax = cnt;
}
cnt = 1;
}
preword = word;
}
if (cntMax > 1)
cout << wordMax << " occurs " << cntMax << " times!" << endl;
5.15 说明下列循环的含义并改正其中错误
(a)
for(int ix = 0;ix != sz;++ix){/*....*/}
if(ix != sz)//ix生命周期在for语句结束后就消失
//....
(b)
int ix;
for(ix != sz;++ix){}//for语句头必须由三个部分构成,init-statement,condition,expression,可以不写但必须用分号隔开
(c)
for(int ix = 0;ix != sz;++ix,++sz){}
修改后:
(a)
int ix;
for(ix = 0;ix != sz;++ix){/*....*/}
if(ix != sz)//ix生命周期在for语句结束后就消失
//....
(b)
int ix;
for(;ix != sz;++ix){}//for语句头必须由三个部分构成,init-statement,condition,expression,可以不写但必须用分号隔开
(c)
for(int ix = 0;ix != sz;++ix){}
5.16 while循环特别使用于那种条件保持不变,反复执行操作的情况,例如,当文件未达到文件末尾时不断读取下一个值。for循环则更像是按步骤迭代,它的索引值在某个范围内依次变化。根据每种循环的习惯用法各自编写一段程序,然后分别用另一种循环改写。如果只能使用一种循环,你更倾向于使用那种呢?
//while
void p5_16_1()
{
vector<string> svec{ "hello", "world", "Cpp", "is","hard", "to", "learn" };
vector<string>::iterator it = svec.begin();
while (it != svec.end())
{
cout << *it << " ";
++it;
}
cout << endl;
}
//for
void p5_16_2()
{
vector<string> svec{ "hello", "world", "Cpp", "is","hard", "to", "learn" };
for(vector<string>::iterator it = svec.begin();it != svec.end();++it)
{
cout << *it << " ";
}
cout << endl;
}
我更倾向于for,因为for结构清晰,便于理解。
5.18 说明下列循环含义并改正其错误
(a) //do只能控制一条语句,若要控制多条语句需用括号构成一个块。
do
int v1, v2;
cout << "Please enter two numbers to sum:";
if(cin >> v1 >> v2)
cout<<"Sum is: "<< v1 + v2 << endl;
while(cin);
(b)
do{
//..
}while(int ival = get_response());//变量定义不可以放在do的条件部分
(c)
do{
int ival = get response();
}while(ival);//do条件部分的变量必须定义在循环体外
改正后:
(a) //do只能控制一条语句,若要控制多条语句需用括号构成一个块。
do{
int v1, v2;
cout << "Please enter two numbers to sum:";
if(cin >> v1 >> v2)
cout<<"Sum is: "<< v1 + v2 << endl;
}while(cin);
(b)
int ival = get_response();
do{
//..
}while(ival = get_response());//变量定义不可以放在do的条件部分
(c)
int ival;
do{
ival = get response();
}while(ival);//do条件部分的变量必须定义在循环体外
|