前言
我发现相比于写知识点,还是写把习题答案写下来可能比较好一点。把知识点写下来太繁杂了,当然我觉得十分重要或者比较难懂的知识点还是会写下来,由于c++ primer的习题本就比较少,所以我也有信心可以把习题全部做完。
习题
5.1节练习
5.1
什么是空语句?什么时候会用到空语句?
答:语句中之后一个分号,可以在while循环中用空语句中起到阻塞作用
5.2
什么是块?什么时候会用到块?
答:用花括号括起来的那个区域?在逻辑上需要多条语句的时候需要使用。
5.3
使用逗号运算符重写1.4.1节的while循环,使它不再需要块,观察改写之后的可读性是提高了还是降低了
#include<iostream>
#include<string>
#include<vector>
using namespace std;
int main() {
int sum = 0, val = 1;
while (val <= 10)
sum += val, ++val;
cout << "sum of 1 to 10 inclusize is " << sum << endl;
return 0;
};
可读性降低了。
5.2节练习
5.4
说明下列例子的含义,如果存在问题,试着修改它。
(a)while(string::iterator iter!=s.end()){}
答:当迭代器iter的值不等于s.end()时,执行while()块中
(b)while(bool status=find(word)){}
if(!status){}
答:当status==false时跳出循环,执行if语句
5.3.1节练习
5.5
写一段自己的程序,使用if else语句实现把数学成绩转换成字母成绩的要求
答:
#include<iostream>
#include<string>
#include<vector>
using namespace std;
int main() {
int score;
cin >> score;
if (score / 10 >=9) {
cout << "A" << endl;
}
else if (score / 10 ==8) {
cout << "B" << endl;
}
else if (score / 10 == 7) {
cout << "C" << endl;
}
else if (score / 10 == 6) {
cout << "D" << endl;
}
else {
cout << "E" << endl;
}
return 0;
};
5.6
改写上一题程序,使用条件运算符代替if else语句
答:
#include<iostream>
#include<string>
#include<vector>
using namespace std;
int main() {
int score;
cin >> score;
int count = score / 10;
char char_score = (count >= 9) ? 'A' : (count == 8) ? 'B' : (count == 7) ? 'C' : (count == 6) ? 'D' : 'E';
cout << char_score << endl;
return 0;
};
5.7
改写下列代码段中的错误
(a)if(ival1!=ival2)
ival1=ival2
else ival1=ival2=0;
答:ival1=ival2;
(b)if(ival<minval)
minval=ival;
occurs=1;
答:occurs=1未在if语句中,需要加上语句块
(c)if(int ival=get_value())
cout<<"ival="<<ival<<endl;
if(!ival)
cout<<"ival=0\n";
答:在if条件中定义的ival只能在if语句块中使用
(d)if(ival=0)
ival=get_value();
答:ival=0是赋值语句,这样ival永远都是0,if中的语句永远都不会执行
5.8
什么是"悬挂else"?c++是如何处理else子句的?
答:当if语句和else嵌套使用时,需要决定else匹配那个if这就是悬挂else c++是根据就近原则,else 与离得最近的if 匹配
5.3.2节练习
5.9
编写一段程序,使用一系列if语句统计从cin读入的文本中有多少元音字母。
答:
#include<iostream>
#include<string>
#include<vector>
using namespace std;
int main() {
string s;
int aCnt = 0;
cin >> s;
for (auto &ch : s) {
if (ch == 'a' ||ch=='A' ||ch=='e' ||ch== 'E' ||ch== 'i' ||ch== 'I' ||ch== 'o' ||ch== 'O' ||ch== 'u' ||ch== 'U') {
++aCnt;
}
}
cout << aCnt << endl;
return 0;
};
5.10
我们之前按统计的元音字母没有包括大小写,这次把大小写包括进去。
答:同上
5.11
修改统计元音字母的程序,使其也能够统计空格、制表符、和换行符的数量
答:
#include<iostream>
#include<string>
#include<vector>
using namespace std;
int main() {
string s;
int aCnt = 0;
int space_cnt = 0;
int table_cnt = 0;
int row_cnt = 0;
getline(cin, s);
for (auto &ch : s) {
if (ch == 'a' ||ch=='A' ||ch=='e' ||ch== 'E' ||ch== 'i' ||ch== 'I' ||ch== 'o' ||ch== 'O' ||ch== 'u' ||ch== 'U') {
++aCnt;
}
if (ch == ' ')
space_cnt++;
if (ch == '\t')
table_cnt++;
if (ch == '\n')
row_cnt++;
}
cout << space_cnt << endl;
cout << table_cnt << endl;
cout << row_cnt << endl;
cout << aCnt << endl;
return 0;
};
5.12
修改统计元音字母的程序,使其能够统计一下含有两个字符序列的数量 ff fl fi
答:
#include<iostream>
#include<string>
#include<vector>
using namespace std;
int main() {
string s;
getline(cin, s);
int ff_cnt, fl_cnt, fi_cnt;
ff_cnt = fl_cnt = fi_cnt = 0;
for (int i = 0; i < s.size(); i++) {
if (s[i] == 'f') {
if (i + 1 < s.size()) {
switch (s[i + 1]) {
case 'f':ff_cnt++;
break;
case 'l':fl_cnt++;
break;
case 'i':fi_cnt++;
break;
}
}
}
}
cout << "ff_cnt:" << ff_cnt << endl;
cout << "fl_cnt:" << fl_cnt << endl;
cout << "fi_cnt:" << fi_cnt << 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++;
}
答:没有在case后加上break
(b)unsigned index=some_value();
switch(index){
case 1:
int ix=get_value();
ivec[ix]=index;
default :
ix=ivec.size()-1;
ivec[ix]=index;
}
答:在default分支中使用了未定义的ix,将ix在switch外定义比较好
(c)unsigned eventCnt=0,oddCnt=0;
int digit=get_num()%10;
switch(digit){
case 1,3,5,7,9:
oddCnt++;
break;
case 2,4,6,8,10
eventCnt++;
break;
}
答:逗号运算符用错了,逗号运算符表示从左往右运算,但是case只能选择一个,可以
case 1:
case 3:
case 5:
case 7:
case 9:
oddCnt++;
break;
(d)unsigned ival=512,javl=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;
}
答:case标签必须是整型常量表达式,所以需要const unsigned ival=512,javl=1024,kval=4096;
5.4.1节练习
5.14
编写一段程序,从标准输入中读取若干个string对象并查找连续重复出现单词。所谓连续重复出现就是:一个单词后面
紧跟这个单词本身。要求记录的连续出现次数以及对应的单词。如果这样的单词存在,输出重复出现的最大次数:如果
不存在,输出一条信息说明任何单词都没有连续出现过。例
如:如果输入是 how now now now brown cow cow
那么输出应该表明单词now出现了三次
答:
//我的
#include<iostream>
#include<string>
#include<vector>
#include<map>
using namespace std;
int main() {
string s;
int max_count = 0;
int num = 0;
string *str=new string[1000];
getline(cin, s);
int i = 0;
while (s[i] == ' ')
i++;
for (int j=i; j < s.size(); j++) {
if (s[j] == ' '||j==s.size()-1) {
if (j == s.size() - 1)
j++;
str[num++] = s.substr(i, j - i);
cout << str[num - 1] << endl;
i = j;
while (s[i] == ' '&&i<s.size())
i++;
j = i;
}
}
string target_str;
for (int i = 0; i < num; i++) {
int count = 0;
if (str[i].compare(str[i + 1])==0) {
int j = i;
while (str[i].compare(str[j]) == 0&&j<num) {
j++;
count++;
}
}
if (count > max_count) {
max_count = count;
target_str = str[i];
}
}
if (!max_count)cout << "no this string" << endl;
else
cout << "max_count_string:" << target_str << " " << "count:" << max_count << endl;
return 0;
};
//答案
#include<iostream>
#include<string>
#include<vector>
#include<map>
using namespace std;
int main() {
string currstring, prestring = "";
string max_count_string;
int max_count = 1;
int count = 1;
while (cin >> currstring) {
if (currstring == prestring) {
count++;
if (count > max_count) {
max_count = count;
max_count_string = currstring;
}
}
else {
count = 1;
}
prestring = currstring;
}
if (max_count>1) {
cout << "max_count_string:" << max_count_string << " count:" << max_count << endl;
}
else
cout << "no this string" << endl;
return 0;
};
5.4.2节练习
5.15
说明下列循环含义并改正其中的错误。
(a)for(int ix=0;ix!=sz;++ix){}
if(ix!=sz)
答:在for循环中定义的ix不能用在for块外
(b)int ix;
for(ix!=sz;++ix){}
答:for循环中需要两个分号来分隔
(c)for(int ix=0;ix!=sz;++ix,++sz){}
答:会是个死循环
5.16
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>
#include<map>
using namespace std;
int main() {
vector<int>a = { 0,1,1,2 };
vector<int>b = { 0,1,1,2,3,4,5 };
int len = a.size() > b.size() ? b.size() : a.size();
bool ispre=false;
for (int i = 0; i < len; i++) {
if (a[i] != b[i]) {
cout << "不是前缀" << endl;
ispre = true;
break;
}
}
if (!ispre)cout << "是前缀" << endl;
return 0;
};
5.4.4练习
5.18
说明下列循环的含义并纠正其中的错误。
(a)do
int v1,v2;
cout<<"Please enter two number 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)
答:出现在条件语句的变量必须要定义在循环体之外
5.19
编写一段程序,使用do while循环重复的执行下列任务:首先提示用户输入两个string对象,然后输出短的string
答:
#include<iostream>
#include<string>
#include<vector>
#include<map>
using namespace std;
int main() {
string a, b;
do {
cout << "输入两个string" << endl;
cin >> a >> b;
cout << ((a.size() < b.size()) ? a : b )<< endl;
} while (cin);
return 0;
};
5.1.1节练习
5.20
编写一段程序,从标准输入中读取string对象的序列直到连
续出现两个相同的单词或者所有单词都读完为止。使用while循环一次读取一个单词,当一个单词连续出现时使用
break语句终止循环。输出连续重复出现的单词,或者输出一个消息说明没有任何单词是连续出现的。
答:
#include<iostream>
#include<string>
#include<vector>
#include<map>
using namespace std;
int main() {
string currString, preString = "";
bool flag = false;
while (cin >> currString) {
if (currString == preString) {
cout << currString << endl;
flag = true;
break;
}
preString = currString;
}
if (!flag)
cout << "no this string" << endl;
return 0;
};
5.5.2节练习
5.21
修改5.1.1节(171页)练习题的程序,使找到的重复单词必须以大写字母开头。
答:
#include<iostream>
#include<string>
#include<vector>
#include<map>
using namespace std;
int main() {
string currString, preString = "";
bool flag = false;
while (cin >> currString) {
if (currString == preString) {
if (!isupper(currString[0]))
continue;
cout << currString << endl;
flag = true;
break;
}
preString = currString;
}
if (!flag)
cout << "no this string" << endl;
return 0;
};
5.5.3练习
5.22
本节的最后一个例子跳回到begin其实使用循环能更好的完成任务。重写该代码,注意不要使用goto语句
答:
int sz;
do{
sz=get_size();
}while(sz<=0);
5.6.3节练习
5.23
编写一段程序,从标准输入读取两个整数,输出第一个整数除以第二个整数的结果。
答:
#include<iostream>
#include<string>
#include<vector>
#include<map>
using namespace std;
int main() {
int a, b;
cout << "Please enter two number" << endl;
cin >> a >> b;
cout << "the result is:" << a / (double)b << endl;
return 0;
};
5.24
修改你的程序,使得当第二个数是0使抛出异常。先不要设置catch子句,运行程序并真的为除数输入0,看看会发生啥。
答:
#include<iostream>
#include<string>
#include<vector>
#include<map>
using namespace std;
int main() {
int a, b;
cout << "Please enter two number" << endl;
cin >> a >> b;
if (b == 0)
throw runtime_error("除数不能为0");
double result = a / (double)b;
cout << "the result is:" << result << endl;
return 0;
};
5.25
修改上一题程序,使用try语句块去捕获异常,catch子句应该为用户输出一条提示信息,询问其是否输入新数并重新执行try语句块的内容。
答:
#include<iostream>
#include<string>
#include<vector>
#include<map>
using namespace std;
int main() {
int a, b;
cout << "Please enter two number" << endl;
begin:try {
cin >> a >> b;
if (b == 0) {
throw runtime_error("除数不能为0");
}
}
catch (runtime_error) {
cout << "是否重新输入(y/n)" << endl;
char ch;
cin >> ch;
if (ch == 'y' || ch == 'Y')
goto begin;
else
return 0;
}
double result = a / (double)b;
cout << "the result is:" << result << endl;
return 0;
};