C++Primer练习[第五章]

//练习5.1 什么是空语句?什么时候会用到空语句?
//答:只含有一个单独的分号的语句是空语句。
//如果在程序的某个地方,语法上需要一条语句但是逻辑上不需要,此时应该使用空语句。


//练习5.2 什么是块?什么时候会用到块?
//答:块也就是复合语句。是指用花括号括起来的(可能为空的)语句和声明的序列。
//如果在程序的某个地方,语法上需要一条语句,但是逻辑上需要多条语句,则应该使用块(复合语句)。


//练习5.3 使用逗号运算符(参见4.10节,第140页)重写1.4.1节(第10页)的while循环,使它不再需要块,观察改写之后的代码的可读性提高了还是降低了?
//答:可读性降低了。
#include <iostream>
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()) {/*…*/ }
//(b)while (bool status = find(word)) {/*…*/ }
// if (!status) {/**/ }
//答:(a)有问题,编译不会通过。此例子含义应该是要循环迭代器直到迭代器到达s的尾后。
//string::iterator iter = s.begin();
//while ( iter != s.end()) {++iter; }
//(b)有问题,定义在控制结构体当中的变量只在相应语句的内部可见,一旦语句结束,变量也就超出其作用范围了。在循环外部无法访问status。此例子含义应该是要循环find(word)并在find(word)的返回值为false的时候退出循环,然后进行if判断,如果status为false执行操作(其实退出循环以后status就是false,此步骤为多余)
//bool status;
//while (status = find(word)) {/*…*/ }
// if (!status) {/**/ }


//练习5.5:写一段自己的程序,使用if else语句实现把数字转换成字母成绩的要求。
#include <iostream>
#include <string>
using std::string;
using std::cin;
using std::cout;
using std::endl;
int main()
{
string scores[6] = { "F","D","C","B","A","A++" };
cout << "请输入成绩:" << endl;
int grade;
string lettergrade;
cin >> grade;
if (grade == 100)
{
lettergrade = scores[5];
}
else
{
if (grade < 60)
{
lettergrade = scores[0];
}
else
{
lettergrade = scores[(grade - 50)/10];
if (grade % 10 > 7)
{
lettergrade += "+";
}
else
{
if (grade % 10 < 3)
{
lettergrade += "-";
}
}
}
}
cout << lettergrade << endl;
system("pause");
return 0;
}


//练习5.6:改写上一题的程序,使用条件运算符(参见4.7节,第134页)代替ifelse语句。
#include <iostream>
#include <string>
using std::string;
using std::cin;
using std::cout;
using std::endl;
int main()
{
string scores[6] = { "F","D","C","B","A","A++" };
cout << "请输入成绩:" << endl;
int grade;
string lettergrade;
cin >> grade;
(grade == 100) ? (lettergrade = scores[5])
: (grade < 60) ? (lettergrade = scores[0])
: (lettergrade = scores[(grade - 50) / 10], (grade % 10 > 7) ? (lettergrade += "+")
: (grade % 10 < 3) ? (lettergrade += "-")
: ""
);
cout << lettergrade << endl;
system("pause");
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(!val)
// cout << "ival = 0\n";
//(d) if (ival = 0)
// ival = get_value();
//答:
//(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;
// else
// cout << "ival = 0\n";
//(d) if (ival == 0)
// ival = get_value();


//练习5.8:什么是悬垂else ? C++语言是如何处理else子句的?
//答:当一个if语句嵌套在另一个if语句内部时,判断某个给定的else是和哪个if匹配的问题称作垂直else。
//C++语言规定else与离它最近的尚未匹配的if匹配。


//练习5.9:编写一段程序,使用一系列if语句统计从cin读入的文本中有多少个元音字母。
#include <iostream>
using std::cin;
using std::cout;
using std::endl;
int main()
{
char c;
int count = 0;
while (cin >> c)
{
if (c == 'A' || c == 'a')
{
++count;
}
else if (c == 'E' || c == 'e')
{
++count;
}
else if (c == 'I' || c == 'i')
{
++count;
}
else if (c == 'O' || c == 'o')
{
++count;
}
else if (c == 'U' || c == 'u')
{
++count;
}
}
cout << "总共有 " << count << " 个元音" << endl;
system("pause");
return 0;
}


//练习5.10:我们之前实现的统计元音字母的程序存在一个问题:如果元音字母以大写字母形式出现,不会被统计在内。编写一段程序,既统计元音字母的小写形式,也统计大写形式,也就是说,新程序遇到'a'和'A'都应该递增aCnt的值,以此类推。
#include <iostream>
using std::cin;
using std::cout;
using std::endl;
int main()
{
char ch;
int aCnt = 0;
while (cin >> ch)
{
switch (ch)
{
case 'a': case'e': case 'i': case 'o': case 'u':
case 'A': case'E': case 'I': case 'O': case 'U':
++aCnt;
break;
default:
break;
}
}
cout << "总共有 " << aCnt << " 个元音" << endl;
system("pause");
return 0;
}


//练习5.11:修改统计元音字母的程序,使其也能统计空格,制表符和换行符的数量。
#include <iostream>
#include <string>
using std::string;
using std::cin;
using std::cout;
using std::endl;
int main()
{
int aCnt = 0;
int kgCnt = 0;
int zbfCnt = 0;
int hhfCnt = 0;
string str;
getline(cin, str);
for(auto ch:str)
{
switch (ch)
{
case 'a': case'e': case 'i': case 'o': case 'u':
case 'A': case'E': case 'I': case 'O': case 'U':
++aCnt;
break;
case ' ':
++kgCnt;
break;
case '\t':
++zbfCnt;
break;
case '\n':
++hhfCnt;
break;
default:
break;
}
}
cout << "总共有 " << aCnt << " 个元音 " << kgCnt << " 个空格 " << zbfCnt << " 个制表符 " << hhfCnt << " 个换行符 " << endl;
system("pause");
return 0;
}


//练习5.12:修改统计元音字母的程序,使其能统计以下含有两个字符的字符序列的数量:ff,fl和fi。
#include <iostream>
#include <string>
using std::string;
using std::cin;
using std::cout;
using std::endl;
int main()
{
int ffCnt = 0;
int flCnt = 0;
int fifCnt = 0;
bool isf = false;
string str;
getline(cin, str);
for(auto ch:str)
{
switch (ch)
{
case 'f':
if (isf)
{
++ffCnt;
isf = false;
}
else
{
isf = true;
}
break;
case 'l':
if (isf)
{
++flCnt;
isf = false;
}
break;
case 'i':
if (isf)
{
++fifCnt;
isf = false;
}
break;
default:
break;
}
}
cout << "总共有 " << ffCnt << " 个ff " << flCnt << " 个fl " << fifCnt << " 个fi " << endl;
system("pause");
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 = javl * sizeof(int);
// break;
//case kval: 
// bufsize = kval * sizeof(int);
// break;
//}
//答:
//(a)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)unsigned index = some_value();
//switch(index) {
//case 1:
// {
// int ix = get_value();
// ivec[ ix ] = index; 
// }
// break;
//default:
// {
// int ix = ivec.size() – 1;
// ivec[ ix ] = index;
// }
//}
//(c)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)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 = javl * 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 std::string;
using std::cin;
using std::cout;
using std::endl;
int main()
{
int maxCount = 0, count = 0;
string maxStr,str,strfront;


while(cin >> str)
{
if(strfront.empty())
{
++count;
if (count > maxCount)
{
maxCount = count;
maxStr = str;
}
}
else
{
++count;
if (count > maxCount)
{
maxCount = count;
if (strfront == str)
{
maxStr = str;
}
else
{
maxStr = strfront;
}
}
if (strfront != str)
{
count = 0;
}
}
strfront = str;
}


if (maxCount == 0)
{
cout << "任何单词都没有连续出现过" << endl;
}
else
{
cout << "单词 " << maxStr << " 连续出现了 " << maxCount << " 次" << endl;
}
system("pause");
return 0;
}


//练习5.15:说明下列循环的含义并改正其中的错误。
//(a)for (int ix = 0; ix != sz; ++ix) {/*…*/ }
// if (ix != sz)
// //… 
//(b)int ix;
// for (ix != sz; ++x) {/*…*/ }
//(c)for (int ix = 0; ix != sz; ++ix, ++ sz) {/*…*/ }
//答:(a)含义应该是ix初始化为0,在ix!=sz的时候执行循环体操作,并再退出循环后,如果ix!=sz就执行一段操作。但是ix的作用域只在for语句里面。
//改为
//int ix = 0;
//for (; ix != sz; ++ix) {/*…*/ }
// if (ix != sz)
// //… 
//或者
//for (int ix = 0; ix != sz; ++ix) {/*…*/ 
// if (ix != sz)
// //… }
//(b)含义应该是跟a一致,但是for语句语法错误
//改为:
//(b)int ix;
// for (; ix != sz; ++x) {/*…*/ }
//(c)同时对两个变量对比,则结果要么一开始相等不进入循环体,要么就是无限循环。
//改为
//(c)for (int ix = 0; ix != sz; ++ix) {/*…*/ }


//练习5.16:while循环特别适用于那种条件保持不变,反复执行操作的情况,例如,当未达到文件末尾时不断读取下一个值。For循环则更像是在按步骤迭代,它的索引值在某个范围内依次变化。根据每种循环的习惯用法各自编写一段程序,然后分别用另一种循环改写。如果只能用一种循环,你倾向于使用哪种呢?为什么 ?
//答:我更倾向于for循环。比较简洁直观。
//while循环习惯
#include <iostream>
using std::cin;
using std::endl;
using std::cout;
int main()
{
char c;
while (cin >> c)
{
cout << c << " ";
}
cout << endl;


system("pause");
return 0;

}


//for循环习惯
#include <iostream>
using std::endl;
using std::cout;
int main()
{
for (int i = 0; i < 10; ++i)
{
cout << i << " ";
}
cout << endl;
system("pause");
return 0;

}


//while循环习惯,改用for
#include <iostream>
using std::cin;
using std::endl;
using std::cout;
int main()
{
char c;
for(char c; cin >> c;)
{
cout << c << " ";
}
cout << endl;


system("pause");
return 0;

}


//for循环习惯,改用while
#include <iostream>
using std::endl;
using std::cout;
int main()
{
int i = 0;
while(i < 10)
{
cout << i << " ";
++i;
}
cout << endl;
system("pause");
return 0;
}


//练习5.17:假设有两个包含整数的vector对象,编写一段程序,检验其中一个vector对象是否是另一个的前缀。为了实现这一目标,对于两个不等长的vector对象,只需挑出长度较短的那个,把它的所有元素和另一个vector对象比较即可。例如,如果两个vector对象的元素分别是0,1,1,2和0,1,1,2,3,5,8,则程序的返回结果为真。
#include <iostream>
#include <vector>
using std::vector;
using std::cout;
using std::endl;
int main()
{
vector<int> vec1{ 0,1,1,2 }, vec2{ 0,1,1,2,3,5,8 };
bool isequ = true;
for (decltype(vec1.size())i = 0; i != (vec1.size() < vec2.size() ? vec1.size() : vec2.size()); ++i)
{
if (vec1[i] != vec2[i])
{
isequ = false;
break;
}
}
if (isequ)
{
cout << "是前缀" << endl;
}
else
{
cout << "不是前缀" << endl;
}


system("pause");
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)do {
// //...
// } while (int ival = get_response());
//(c)do {
// int ival = get_response();
// } while (ival); 
//答:(a)含义应为使用do while语句循环输入v1,v2并计算出和。
//改正为:
// int v1, v2;
// do
// {
// cout << "please enter two numbers to sum : ";
// if (cin >> v1 >> v2)
// cout << "sum is : " << v1 + v2 << endl;
// }
// while (cin);
//(b)含义应为执行do while语句,直到get_response()的值为0。
//改正为:
//int ival;
//do {
// //...
// } while (ival = get_response());
//(c)含义同(b)
//改正为:
//int ival;
//do {
// ival = get_response();
// } while (ival);


//练习5.19:编写一段程序,使用do while循环重复地执行下述任务:首先提示用户输入两个sting对象,然后挑出较短的那个并输出它。
#include <iostream>
#include <string>
using std::string;
using std::cin;
using std::cout;
using std::endl;
int main()
{
string str1, str2;
do 
{
cout << "请输入两个string对象" << endl;
getline(cin, str1);
getline(cin, str2);
cout << (str1.size() <= str2.size() ? str1 : str2) << endl;
} while (cin);


system("pause");
return 0;
}


//练习5.20:编写一段程序,从标准输入中读取string对象的序列直到连续出现两个相同的单词或者所有单词都读完为止。使用while循环一次读取一个单词,当一个单词连续出现两次时使用break语句终止循环。输出连续重复出现的单词,或者输入一个消息说明没有任何单词是连续重复出现的。
#include <iostream>
#include <string>
using std::string;
using std::cin;
using std::cout;
using std::endl;
int main()
{
string word;
string old_word;
while (cin >> word)
{
if (old_word != "" && word == old_word)
{
cout << "出现重复单词:" << word << endl;
break;
}
old_word = word;
}
if (word != old_word)
{
cout << "没有重复单词" << endl;
}
system("pause");
return 0;
}


//练习5.21:修改5.5.1节(第171页)练习题的程序,使其找到的重复单词必须以大写字母开头。
#include <iostream>
#include <string>
#include <cstring>
using std::string;
using std::cin;
using std::cout;
using std::endl;
int main()
{
string word;
string old_word;
while (cin >> word)
{
if (!word.empty() && !isupper(word[0]))
{
continue;
}
if (old_word != "" && word == old_word)
{
cout << "出现重复单词:" << word << endl;
break;
}
old_word = word;
}
if (word != old_word)
{
cout << "没有重复单词" << endl;
}
system("pause");
return 0;
}


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


//练习5.23:编写一段程序,从标准输入读取两个整数,输出第一个整数除以第二个整数的结果。
#include <iostream>
using std::cin;
using std::cout;
using std::endl;

int main()
{
int i1, i2;
cout << "请输入两个整数" << endl;
cin >> i1 >> i2;


if (i2 != 0)
{
cout << i1 / i2 << endl;
}
else
{
cout << "被除数不能为0" << endl;
}

system("pause");
return 0;
}


//练习 5.24:修改你的程序,使得当第二个数是0时抛出异常。先不要设定catch子句,运行程序并真的为除数输入0,看看会发生什么?
#include <iostream>
#include <stdexcept>
using std::cin;
using std::cout;
using std::endl;
using std::runtime_error;

int main()
{
int i1, i2;
cout << "请输入两个整数" << endl;
cin >> i1 >> i2;

if (i2 == 0)
{
throw runtime_error("被除数不能为0");
}
cout << i1 / i2 << endl;

system("pause");
return 0;
}


//练习5.25:修改上一题的程序,使用try语块去捕获异常。Catch子句应该为用户输出一条提示信息,询问其是否输入新数并重新执行try语块的内容
#include <iostream>
#include <stdexcept>
using std::cin;
using std::cout;
using std::endl;
using std::runtime_error;

int main()
{
int i1, i2;
while (true)
{
cout << "请输入两个整数" << endl;
cin >> i1 >> i2;
try
{
if (i2 == 0)
{
throw runtime_error("被除数不能为0");
}
cout << i1 / i2 << endl;
break;
}
catch (runtime_error err)
{
cout << err.what() << endl;
cout << "是否重新输入?(y/n)" << endl;
char c;
cin >> c;
if (!cin || c == 'n')
{
break;
}
}
}

system("pause");
return 0;

}


猜你喜欢

转载自blog.csdn.net/sukeychen/article/details/80427714