C Primer Plus 第6版 编程练习——第8章
1.设计一个程序,统计在读到文件结尾之前读取的字符数。
int main(int argc, char* argv[]) {system("chcp 65001");FILE* file = NULL;fopen_s(&file, "test.jpg", "rb"); // 以只读模式打开文件if (file == NULL) {perror("文件打开失败");return -1;}int ch;long count = 0;// 逐字符读取文件直到EOFwhile ((ch = fgetc(file)) != EOF) {count++;}fclose(file); // 关闭文件流printf("文件包含 %ld 个字符\n", count);return 0;
}
2.编写一个程序,在遇到BOEF之前,把输入作为字符流读取。程序要打印每个输入的字符及其相应的ASCII十进制值。注意,在ASCII序列中,空格字符前面的字符都是非打印字符,要特殊处理这些字符。如果非打印字符是换行符或制表符,则分别打\n或\t。否则,使用控制字符表示法。例如,ASCII的1是Ctrl+A,可显示为^A。注意,A的ASCI值是Ctrl+A的值加上64。其他非打印字符也有类似的关系。除每次遇到换行符打印新的一行之外,每行打印10对值。(注意:不同的操作系统其控制字符可能不同。)
#include <ctype.h> // 用于isprint函数int main() {system("chcp 65001");int ch;int count = 0; // 当前行已打印的字符对数printf("输入内容 (按Ctrl+Z结束):\n");while ((ch = getchar()) != EOF) {// 处理字符表示char rep[4] = { 0 }; // 存储字符表示if (ch == '\n') { // 换行符sprintf_s(rep, sizeof(rep), "\\n");}else if (ch == '\t') { // 制表符sprintf_s(rep, sizeof(rep), "\\t");}else if (!isprint(ch) && ch < 32) { // 其他非打印字符rep[0] = '^';rep[1] = ch + 64; // 转换为控制字符表示}else { // 可打印字符rep[0] = ch;}// 打印前处理空格分隔if (count > 0) {putchar(' ');}// 打印字符表示和ASCII值printf("%s %d", rep, ch);// 处理行尾和换行if (ch == '\n') {putchar('\n'); // 结束当前行count = 0; // 重置计数器}else {count++;if (count == 10) {putchar('\n');count = 0;}}}// 处理最后一行未换行的情况if (count > 0) {putchar('\n');}return 0;
}
3.编写一个程序,在遇到EOF之前,把输入作为字符流读取。该程序要报告输入中的大写字母和小写字母的个数。假设大小写字母数值是连续的。或者使用ctype.h库中合适的分类函数更方便.
#include <ctype.h> // 包含isupper()和islower()函数int main() {system("chcp 65001");int ch; // 存储输入的字符int upper_count = 0; // 大写字母计数器int lower_count = 0; // 小写字母计数器printf("请输入文本(按Ctrl+D或Ctrl+Z结束):\n");// 逐字符读取直到EOFwhile ((ch = getchar()) != EOF) {if (isupper(ch)) { // 检查是否为大写字母upper_count++;}else if (islower(ch)) { // 检查是否为小写字母lower_count++;}}// 输出统计结果printf("\n统计结果:\n");printf("大写字母数量: %d\n", upper_count);printf("小写字母数量: %d\n", lower_count);printf("字母总数: %d\n", upper_count + lower_count);return 0;
}
4.编写一个程序,在遇到EOF之前,把输入作为字符流读取。该程序要报告平均每个单词的字母数。不要把空白统计为单词的字母。实际上,标点符号也不应该统计,但是现在暂时不同考虑这么多(如果你比较在意这点,考虑使用ctype.h系列中的ispunct()函数)。
#include <ctype.h> // 包含isalpha()和isspace()函数int main() {system("chcp 65001");int ch; // 存储输入的字符int in_word = 0; // 标记是否在单词中 (0=不在, 1=在)int letter_count = 0; // 字母计数器int word_count = 0; // 单词计数器printf("请输入文本(按Ctrl+D或Ctrl+Z结束):\n");// 逐字符读取直到EOFwhile ((ch = getchar()) != EOF) {if (isalpha(ch)) { // 如果是字母letter_count++;if (!in_word) { // 如果不在单词中,开始新单词in_word = 1;word_count++;}}else if (isspace(ch)) { // 如果是空白字符(空格、制表符、换行等)in_word = 0; // 结束当前单词}// 注意:标点符号被忽略,不处理}// 计算并输出结果printf("\n统计结果:\n");printf("总字母数: %d\n", letter_count);printf("总单词数: %d\n", word_count);if (word_count > 0) {double avg_letters = (double)letter_count / word_count;printf("平均每个单词的字母数: %.2f\n", avg_letters);}else {printf("未检测到单词,无法计算平均值\n");}return 0;
}
5.修改程序清单8.4的猜数字程序,使用更智能的猜测策略。例如,程序最初猜50,询问用户是猜大了、猜小了还是猜对了。如果猜小了,那么下一次猜测的值应是50和100中值,也就是75。如果这次猜大了,那么下一次猜测的值应是50和75的中值,等等。使用二分查找(binary search)策略,如果用户没有欺骗程序,那么程序很快就会猜到正确的答案。
int main()
{int min = 1;int max = 100;int guess = (min + max) / 2;printf("Pick an integer from 1 to 100.I will try to guess it.\n");printf("Respond with a y if my guess is right \n");printf("and with a g if my guess is greater \n");printf("and with a l if my guess is lesser\n");printf("Un...is your number %d?\n", guess);char ch;while ((ch = getchar()) != 'y'){if (ch == 'l' || ch == 'g'){if (ch == 'g'){max = guess - 1;}else if (ch == 'l'){min = guess + 1;}guess = (min + max) / 2;printf("Well, then, is it %d?\n", guess);}}printf("I knew I could count do it!\n");return 0;
}
6.修改程序清单8.8中的get_first()函数,让该函数返回读取的第1个非空白字符,并在一个简单的程序中测试
char get_first(void)
{int ch;while ((ch = getchar()) == ' '){;}while(getchar() != '\n');return ch;
}int main(void)
{char ch;printf("Please enter a sentence:\n");ch = get_first();printf("The first character is %c.\n", ch);return 0;
}
。
7.修改第7章的编程练习8,用字符代替数字标记菜单的选项。用g代替5作为结束输入的标记。
#define PAY_RATE_1 8.75
#define PAY_RATE_2 9.33
#define PAY_RATE_3 10.00
#define PAY_RATE_4 11.20
int main()
{system("chcp 65001");printf("*****************************************************************\n");printf("Enter the number corresponding to the desired pay rate or action:\n");printf("a) $8.75/hr b) $9.33/hr\n");printf("c) $10.00/hr d) $11.20/hr\n");printf("q) quit\n");printf("*****************************************************************\n");while (1) {char choice;double pay_rate;if (scanf_s("%c", &choice, 1) == 1){switch (choice) { case 'a':pay_rate = PAY_RATE_1;break;case 'b':pay_rate = PAY_RATE_2;break;case 'c':pay_rate = PAY_RATE_3;break;case 'd':pay_rate = PAY_RATE_4;break;case 'q':return 0;default:continue;}printf("请输入工作小时数:");int hours;scanf_s("%d", &hours);double salary = pay_rate * (hours > 40 ? hours * 1.5 - 20 : hours);printf("工资:%f\n", salary);double tax = salary <= 300 ? salary * 0.15 : salary <= 450 ? salary * 0.2 - 15 : salary * 0.25 - 37.5;printf("税金:%f\n", tax);printf("净收入:%f\n", salary - tax);printf("*****************************************************************\n");printf("Enter the number corresponding to the desired pay rate or action:\n");printf("a) $8.75/hr b) $9.33/hr\n");printf("c) $10.00/hr d) $11.20/hr\n");printf("q) quit\n");printf("*****************************************************************\n");continue;}printf("请输入正确的选项!\n");}
}
8.编写一个程序,显示一个提供加法、减法、乘法、除法的菜单。获得用户选择的选项后,程序提示用户输入两个数字,然后执行用户刚才选择的操作。该程序只接受菜单提供的选项。程序使用 float 类型的变量存储用户输入的数字,如果用户输入失败,则允许再次输入。进行除法运算时,如果用户输入0作为第2个数(除数),程序应提示用户重新输入一个新值。该程序的一个运行示例如下:
Enter the operation of your choice:
a. add s. subtract
m. multiply d. divide
q. quit
a
Enter first number: 22.4
Enter second number: one
one is not an number.
Please enter a number, such as 2.5,-1.78E8,or 3: 1
22.4 + 1 = 23.4
Enter the operation of your choice:/
a. add s. subtract
m. multiply d. divide
q. quit
d
Enter first number: 18.4
Enter second number: 0
Enter a number other than 0: 0.2
18.4 / 0.2 = 92
Enter the operation of your choice:
a. add s. subtract
m. multiply d. divide
q. quit
q
Bye.
//清空输入缓冲区
void clear_input_buffer() {int c;while ((c = getchar()) != '\n' && c != EOF);
}int main() {char choice;float num1, num2;int valid_input;system("chcp 65001");while (1) {// 显示菜单printf("\nEnter the operation of your choice:\n");printf("a. add s. subtract\n");printf("m. multiply d. divide\n");printf("q. quit\n");// 获取用户选择并验证while (1) {choice = getchar();clear_input_buffer(); // 清除输入缓冲区// 检查是否有效选择if (choice == 'a' || choice == 's' || choice == 'm' || choice == 'd' || choice == 'q') {break;}else {printf("无效选项,请重新选择 (a, s, m, d, q): ");}}// 退出程序if (choice == 'q') {printf("Bye.\n");break;}// 获取第一个数字printf("Enter first number: ");while (1) {valid_input = scanf_s("%f", &num1);clear_input_buffer();if (valid_input == 1) {break;}else {printf("Please enter a number , such as 2.5, -1.78E8, or 3: ");}}// 获取第二个数字printf("Enter second number: ");while (1) {valid_input = scanf_s("%f", &num2);clear_input_buffer();if (valid_input != 1) {printf("Please enter a number , such as 2.5, -1.78E8, or 3: ");continue;}// 除法时检查除数是否为0if (choice == 'd' && num2 == 0) {printf("Enter a number other than 0: ");continue;}break;}// 执行运算并显示结果switch (choice) {case 'a':printf("%.2f + %.2f = %.2f\n", num1, num2, num1 + num2);break;case 's':printf("%.2f - %.2f = %.2f\n", num1, num2, num1 - num2);break;case 'm':printf("%.2f * %.2f = %.2f\n", num1, num2, num1 * num2);break;case 'd':printf("%.2f / %.2f = %.2f\n", num1, num2, num1 / num2);break;}}return 0;
}