一、复习题
1. 请看下面两个计算空格和换行符的数目的代码片段:…。第二个版本比第一个版本好在哪里?
答:读取空格字符时,第一个版本需要判断两次,而第二个版本只需要判断一次。所以,第二个版本效率略高。
2. 在程序清单6.2中,用ch+1 替换++ch将发生什么情况呢?
答:char类型在进行算数运算时会自动转换为int类型,所以表达式ch+1的结果为int类型,cout输出数字而不是字符。
3. 请认真考虑下面的程序:…。假设输入如下:…。则输出将是什么?
答:if语句中误用了赋值运算符,即ch = ‘$’,导致表达式的值始终为true,且ch的值被修改。输出如下:
Hi!
H$i$!$
$S$e$n$d$ $ct1 = 9, ct2 = 9
4. 创建表示下述条件的逻辑表达式:…。
答:
a. weight >= 115 || weight <= 125
b. ch == ‘q’ || ch == ‘Q’
c. x % 2 == 0 && x != 26
d. x % 2 == 0 && x % 26 != 0
e. (donation >= 1000 && donation <= 2000) || guest == 1
f. (ch >= ‘a’ && ch <= ‘z’) || (ch >= ‘A’ && ch <= ‘Z’)
5. 在英语中,"I will not not speak(我不会不说)"的意思与“I willspeak(我要说)”相同。在C++中,!!x是否与x相同。
答:若x为bool类型,则!!x与x为相同的bool值。若x为其他类型,则!!x依然为bool值,则两者的类型不同。
6. 创建一个条件表达式,其值为变量的绝对值。也就是说,如果变量x为正,则表达式的值为x,如果x为负,则表达式的值为-x。
答:x > 0 ? x : -x 或者 x >= 0 ? x : -x
7. 用switch语句改写下面的代码片段:…。
答:
switch (ch)
{
case 'A' :
a_grade++;
break;
case 'B' :
b_grade++;
break;
case 'C' :
c_grade++;
break;
case 'D' :
d_grade++;
break;
default:
f_grade++;
break;
}
8. 对于程序清单6.10,与使用数字相比,使用字符(如a和c)表示菜单选项和case标签有何有点呢?
答:choice为int类型时,若用户不小心输入字符,则造成非法输入,程序无法正常运行。choice为char类型时,可以读取键盘输入的所有字符,若输入错误,则跳到default语句进行处理,然后重新输入。使用char类型,可以提高程序的容错率。
9. 请看下面的代码片段:…。请重写该代码片段,不要使用break和continue语句。
答:
int line = 0;
char ch;
while (cin.get(ch) && ch != 'Q')
{
if (ch == '\n)
line++;
}
二、编程练习
1. 编写一个程序,读取键盘输入,知道遇到@符号为止,并回显输入(数字除外),同时将大写字符转换为小写,将小写字符转换为大写(别忘了cctype函数系列)。
/ 头文件
#include <iostream>
#include <cctype>
// 标准名称空间std
using namespace std;
int main()
{
char ch;
cout << "Enter the character: " << endl;
// 通过循环读取输入字符,直到遇到'@'
while ((ch = cin.get()) != '@')
{
// 不是数字字符
if (!isdigit(ch))
{
// 大写字符变小写
if (isupper(ch))
ch = tolower(ch);
// 小写字符变大写
if (islower(ch))
ch = toupper(ch);
// 显示字符
cout << ch;
}
}
return 0;
}
2. 编写一个程序,最多将10个donation值读入一个double数组中(也可以使用模板类array)。在程序遇到数字时将结束输入,并报告这些数字的平均值以及数组中有多少数字大于平均值。
double数组
int main()
{
double input, donations[10]; // 存储输入
int num = 0; // 记录输入数字的个数
double sum = 0; // 计算输入总和
while (num < 10)
{
cout << "Enter a number: ";
cin >> input;
// 如果输入非数字
if (!cin)
{
// 重置输入
cin.clear();
// 清空错误输入
while (cin.get() != '\n')
continue;
// 结束输入
break;
}
// 存储输入的数,计算总和,计数器+1
sum += input;
donations[num] = input;
++num;
}
// 计算平均值
double average = sum / num;
// 统计超过平均值的数的个数
int num_overAverage = 0;
for (int i = 0; i < num; i++)
{
if (donations[i] > average)
num_overAverage++;
}
// 输出
cout << "Average: " << average << endl;
cout << "Over average: " << num_overAverage << endl;
return 0;
}
array模板
// 头文件
#include <iostream>
#include <array>
// 标准名称空间std
using namespace std;
int main()
{
// 存储输入
array<double, 10> donations;
double input;
double sum = 0; // 存储输入数的总和
double num = 0; // 存储输入数的个数
// 输入
do
{
cout << "Please enter a number: ";
// 如果非法输入
if (!(cin >> input))
{
// 重置输入
cin.clear();
// 清空错误输入
while (cin.get() != '\n')
continue;
// 结束输入
break;
}
else
{
// 计算总和,存储数据,计数
sum += input;
donations[num] = input;
++num;
}
} while (num < 10);
// 计算平均数
double average = sum / num;
// 统计超过平均数的个数
int num_overAverage = 0;
for (int i = 0; i < num; ++i)
{
if (donations[i] > average)
++num_overAverage;
}
// 输出
cout << "Average: " << average << endl;
cout << "Over average: " << num_overAverage << endl;
return 0;
}
3. 编写一个菜单驱动程序的雏形。该程序显示一个提供4个选项的菜单——每个选项用字母标记。…。
// 头文件
#include <iostream>
// 标准名称空间std
using namespace std;
// 打印菜单
void menu();
int main()
{
// 显示菜单
menu();
// 输入
char ch;
ch = cin.get();
// 无效输入则重新输入
while (ch != 'c' && ch != 'p' && ch != 't' && ch != 'g')
{
// 清除无效输入
while (cin.get() != '\n')
continue;
// 重新输入
cout << "Please enter a c, p, t, or g: ";
ch = cin.get();
}
// 选择
switch (ch)
{
case 'c':
break;
case 'p':
break;
case 't':
cout << "A maple is a tree." << endl;
break;
case 'g':
break;
}
return 0;
}
// 打印菜单
void menu()
{
cout << "Please enter one of the following choices:" << endl;
cout << "c) carnivore p) pianist" << endl;
cout << "t) tree g) game" << endl;
}
4. 加入Benevolent Order of Programmer后,在BOP大会上,人们便可以通过加入者的真实姓名、头衔或秘密BOP姓名来了解他(她)。…。
// 符号常量声明
const int strsize = 20;
// bop结构声明
struct bop
{
char fullname[strsize]; // 真实姓名
char title[strsize]; // 头衔
char bopname[strsize]; // 秘密BOP姓名
int preference; // 0 = fullname, 1 = title, 2 = bopname
};
// 打印菜单
void menu();
// 打印姓名
void print_by_name(bop arr[]);
// 打印头衔
void print_by_title(bop arr[]);
// 打印秘密BOP姓名
void print_by_bopname(bop arr[]);
// 打印偏好
void print_by_preference(bop arr[]);
int main()
{
// 显示菜单
menu();
// 创建bop结构数组并初始化
bop bopArr[5] = {
{"Wimp Macho", "Programmer", "MIPS", 0},
{"Raki Rhodes", "Junior Programmer", "", 1},
{"Celia Laiter", "", "MIPS", 2},
{"Hoppy Hipman", "Analyst Trainee", "", 1},
{"Pat Hand", "", "LOOPY", 2}
};
// 输入
char ch;
while ((ch = cin.get()) != 'q')
{
switch (ch)
{
case 'a':
print_by_name(bopArr);
break;
case 'b':
print_by_title(bopArr);
break;
case 'c':
print_by_bopname(bopArr);
break;
case 'd':
print_by_preference(bopArr);
break;
default:
cout << "Input error ! Please re-enter." << endl;
}
// 清空输入
while (cin.get() != '\n')
continue;
// 下一个输入
cout << "Next choice:";
}
return 0;
}
// 打印菜单
void menu()
{
cout << "a. display by name b. display by title" << endl;
cout << "c. display by bopname d. display by preference" << endl;
cout << "q. quit" << endl;
}
// 打印姓名
void print_by_name(bop arr[])
{
for (int i = 0; i < 5; i++)
{
cout << arr[i].fullname << endl;
}
}
// 打印头衔
void print_by_title(bop arr[])
{
for (int i = 0; i < 5; ++i)
{
cout << arr[i].title << endl;
}
}
// 打印秘密BOP姓名
void print_by_bopname(bop arr[])
{
for (int i = 0; i < 5; ++i)
{
cout << arr[i].bopname << endl;
}
}
// 打印偏好
void print_by_preference(bop arr[])
{
for (int i = 0; i < 5; ++i)
{
switch (arr[i].preference)
{
case 0:
cout << arr[i].fullname << endl;
break;
case 1:
cout << arr[i].title << endl;
break;
case 2:
cout << arr[i].bopname << endl;
break;
}
}
}
5. 在Neutronia王国,货币单位是tvarp,收入所得税的计算方式如下。…。
int main()
{
// 输入工资,计算税收
double wages = 0; // 工资
double tax = 0; // 税收
cout << "Please enter your wages: ";
while (cin >> wages && wages >= 0)
{
// 计算税收
if (wages <= 5000)
tax = 0;
else if (wages <= 15000)
tax = (wages - 5000) * 0.1;
else if (wages <= 35000)
tax = (wages - 15000) * 0.15 + 1000;
else
tax = (wages - 35000) * 0.2 + 3000 + 1000;
// 输出
cout << "Your tax: " << tax << endl;
// 下一个
cout << endl; // 每次输入隔开
cout << "Please enter your wages: ";
}
return 0;
}
6. 编写一个程序,记录捐给“维护合法权利团队”的资金。…。
// Donors结构声明
struct Donor
{
char name[20]; // 姓名
double money_donated; // 捐款金额
};
int main()
{
// 输入捐款人数
int num_donated;
cout << "Please enter the number of donations: ";
cin >> num_donated;
cout << endl;
// 申请对应数量的结构数组
Donor* pdonors = new Donor[num_donated];
// 输入
for (int i = 0; i < num_donated; ++i)
{
// 丢弃换行符
cin.get();
cout << "Enter the name of donor: ";
cin.getline(pdonors[i].name, 20);
cout << "Enter donation amount: ";
cin >> pdonors[i].money_donated;
cout << endl; // 隔开每个人的信息
}
// 设置捐款大于15000为重要捐款人
// 重要捐款人
int empty = 1; // 判断是否有捐款者
cout << "Grand Patrons: " << endl;
for (int i = 0; i < num_donated; ++i)
{
if (pdonors[i].money_donated > 15000)
{
cout << pdonors[i].name << ": " << pdonors[i].money_donated << endl;
empty = 0;
}
}
if (empty)
cout << "NONE" << endl;
empty = 1; // 重置
// 其他捐款者(捐款金额大于10000)
cout << "Patrons:" << endl;
for (int i = 0; i < num_donated; i++)
{
if (pdonors[i].money_donated >= 10000 && pdonors[i].money_donated <= 15000)
cout << pdonors[i].name << ": " << pdonors[i].money_donated << endl;
}
// 释放申请空间
free(pdonors);
return 0;
}
7. 编写一个程序,它每次读取一个单词,直到用户输入q。然后,该程序指出有多少个单词原音开头,有多少个单词以辅音开头,还有多少个单词不属于这两类。…。
// 头文件
#include <iostream>
#include <cstring>
#include <cctype>
// 标准名称空间std
using namespace std;
int main()
{
int vowel = 0; // 元音单词的数量
int consonant = 0; // 辅音单词的数量
int others = 0; // 其他单词的数量
// 输入
char words[20];
cout << "Enter words (q to quit) :" << endl;
while (cin >> words && strcmp(words, "q") != 0)
{
char ch = words[0]; // 输入单词的第一个字母
if (isalpha(ch)) // 是单词
{
switch (ch)
{
case 'a':
case 'e':
case 'i':
case 'o':
case 'u':
++vowel;
break;
default:
++consonant;
}
}
else // 不是单词
{
++others;
}
}
// 输出
cout << vowel << " words beginning with vowels" << endl;
cout << consonant << "words beginning with consonants" << endl;
cout << others << " others" << endl;
return 0;
}
8. 编写一个程序,它打开一个文件,诸葛自负读取该文件,知道打到文件末尾,然后指出该文件中包含多少个字符。
// 头文件
#include <iostream>
#include <fstream>
#include <cstdlib>
// 标准名称空间
using namespace std;
int main()
{
// 创建ifstream对象
ifstream fcin;
// 打开文件
fcin.open("snow.txt");
// 检测文件是否成功打开
if (!fcin.is_open())
{
cout << "Open error." << endl;
exit(EXIT_FAILURE);
}
// 输入
char ch; // 如果使用ch = cin.get()需要创建为int类型
int num_char = 0; // 统计字符个数
while (fcin.get(ch)) // 检测EOF
{
++num_char;
}
// 输出
cout << "The number of the characters: " << num_char << endl;
// 关闭文件
fcin.close();
return 0;
}
9. 重做编程练习6,从文件中读取所需信息…。
// 头文件
#include <iostream>
#include <fstream>
#include <cstdlib>
// 标准名称空间std
using namespace std;
// Donors结构声明
struct Donor
{
char name[20]; // 姓名
double money_donated; // 捐款金额
};
int main()
{
// 创建ifstream对象
ifstream fcin;
// 打开文件
fcin.open("Donors.txt");
// 检测打开文件是否成功
if (!fcin.is_open())
{
cout << "Open error." << endl;
exit(EXIT_FAILURE);
}
// 输入捐款人数
int num_donated;
cout << "从文件中读取捐款人数:";
fcin >> num_donated;
cout << endl;
// 申请对应数量的结构数组
Donor* pdonors = new Donor[num_donated];
// 输入
cout << "从文件中读取捐款人的信息:" << endl;
for (int i = 0; i < num_donated; ++i)
{
// 丢弃换行符
fcin.get();
// 从文件中读取信息
cout << i + 1 << ":";
fcin.getline(pdonors[i].name, 20);
fcin >> pdonors[i].money_donated;
cout << endl;
}
cout << endl; // 分割
// 设置捐款大于15000为重要捐款人
// 重要捐款人
int empty = 1; // 判断是否有捐款者
cout << "Grand Patrons: " << endl;
for (int i = 0; i < num_donated; ++i)
{
if (pdonors[i].money_donated > 15000)
{
cout << pdonors[i].name << ": " << pdonors[i].money_donated << endl;
empty = 0;
}
}
// 判断是否有捐款者
if (empty)
cout << "NONE" << endl;
empty = 1; // 重置
cout << endl; // 隔开两个类型
// 其他捐款者(捐款金额大于10000)
cout << "Patrons:" << endl;
for (int i = 0; i < num_donated; i++)
{
if (pdonors[i].money_donated >= 10000 && pdonors[i].money_donated <= 15000)
cout << pdonors[i].name << ": " << pdonors[i].money_donated << endl;
}
// 判断是否有捐款者
if (empty)
cout << "NONE" << endl;
// 释放申请空间
free(pdonors);
// 关闭文件
fcin.close();
return 0;
}