《C Primer Plus》第8章复习题与编程练习

复习题

1. putchar(getchar())是一个有效表达式,它实现什么功能?getchar(putchar())是否也是有效表达式

实现输出显示缓存区的下一个字符。
不是,getchar()没有参数。

2. 下面的语句分别完成什么任务?

a. putchar(‘H’);
b. putchar(‘\007’);
c. putchar(‘\n’);
d. putchar(‘\b’);

a. 打印字符 H
b. 如果系统使用ASDII,发出一声警报
c. 把光标移动到下一行
d. 把光标后退一格

3. 假设有一个名为 count 的可执行程序,用于统计输入的字符数。设计一个使用 count 程序统计essay文件中字符数的命令行,并把统计结果保存在essayct文件中。

count < essay > essayct 或者 count > essayct < essay

4. 给定复习题3中的程序和文件,下面哪一条是有效的命令?

a .essayct < essay
b. count essay
c. essay > count

都不是。

5. EOF是什么?

由getchar() or scanf() 返回的一个特殊值,表明函数检测到文件的结尾。

6. 对于给定的输出(ch是int类型,而且是缓冲输入),下面各程序段的输出分别是什么?

a.输入如下:

If you quit, I will.[enter]

程序段如下:

while ((ch = getchar()) != 'i')
        putchar(ch);

b.输入如下:

Harhar[enter]

程序段如下:

while ((ch = getchar()) != '\n')
{
        putchar(ch++);
        putchar(++ch);
}

a. If you qu
b. HJacrthjacrt

7. C如何处理不同计算机系统中的不同文件和换行约定?

C的标准I/O库会把不同的文件映射成统一的流来处理。

8. 在使用缓冲输入的系统中,把数值和字符混合输入会遇到什么潜在的问题?

数值输入会跳过空格和换行符,但是字符输入不会。
输入数字的时候,空格和换行符还会留在缓存区,输入字符的时候会读取。
所以在编写程序时要在输入数字之后要处理空格和换行符。

编程练习

1. 统计字符数

设计一个程序,统计在读到文件结尾之前读取的字符数
代码:

// 8.1.cpp
#include <stdio.h>
#include <stdlib.h>
int main(void)
{
    char ch;
    FILE *fp;
    char fname[50]; // 存储文件名
    int count = 0;

    printf("Enter the file name: ");
    scanf("%s", fname);
    fp = fopen(fname, "r"); // 只读模式打开文件
    if (fp == NULL)
    {
        printf("Failed to open file.\n");
        exit(1); // 退出程序
    }
    // getc(fp)从打开的文件中获取一个字符
    while ((ch = getc(fp)) != EOF)
    {
        count++;
    }
    printf("文件%s的字符数:%d\n", fname, count);
    fclose(fp); // 关闭文件

    system("pause");
    return 0;
}

运行结果:

在这里插入图片描述

2. 打印字符-ASCII值对

编写一个程序,在遇到 EOF 之前,把输入作为字符流读取。程序要打印每个输入的字符及其相应的ASCII十进制值。
注意,在ASCII序列中,空格字符前面的字符都是非打印字符,要特殊处理这些字符。如果非打印字符是换行符或制表符,则分别打印\n或\t。否则,使用控制字符表示法。例如,ASCII的1是Ctrl+A,可显示为^A。注意,A的ASCII值是Ctrl+A的值加上64。其他非打印字符也有类似的关系。除每次遇到换行符打印新的一行之外,每行打印10对值。
(注意:不同的操作系统其控制字符可能不同。)

代码:

#include <stdio.h>
#include <stdlib.h>
int main(void)
{
    char ch;
    FILE *fp;
    char fname[50]; // 存储文件名
    int count = 0;

    printf("Enter the file name: ");
    scanf("%s", fname);
    fp = fopen(fname, "r"); // 只读模式打开文件
    if (fp == NULL)
    {
        printf("Failed to open file.\n");
        exit(1); // 退出程序
    }
    // getc(fp)从打开的文件中获取一个字符
    while ((ch = getc(fp)) != EOF)
    {

        if (ch == '\n')
        {
            printf("\\n:%d\n", ch);
            count = 0; // 每次遇到换行符打印新的一行
        }
        else if (ch == '\t')
        {
            printf("\\t:%d  ", ch);
        }
        else if (ch == ' ')
        {
            printf("' ':%d  ", ch);
        }
        else if (ch < ' ')
        {
            printf("^%c:%d  ", ch + 64, ch);
        }
        else
        {
            printf("%c:%d ", ch, ch);
        }
        if (++count % 10 == 0)
        {
            count = 0;
            putchar('\n');
        }
    }
    fclose(fp); // 关闭文件

    system("pause");
    return 0;
}

运行结果:

在这里插入图片描述

3. 报告输入中的大写字母和小写字母的个数

编写一个程序,在遇到 EOF 之前,把输入作为字符流读取。该程序要报告输入中的大写字母和小写字母的个数。假设大小写字母数值是连续的。或者使用ctype.h库中合适的分类函数更方便。

代码:

#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
int main(void)
{
    char ch;
    FILE *fp;
    char fname[50]; // 存储文件名
    int count_upper = 0, count_lower = 0;

    printf("Enter the file name: ");
    scanf("%s", fname);
    fp = fopen(fname, "r"); // 只读模式打开文件
    if (fp == NULL)
    {
        printf("Failed to open file.\n");
        exit(1); // 退出程序
    }
    // getc(fp)从打开的文件中获取一个字符
    while ((ch = getc(fp)) != EOF)
    {
        if (isupper(ch))
            count_upper++;
        if (islower(ch))
            count_lower++;
    }
    printf("大写字母个数:%d,小写字母个数:%d\n", count_upper, count_lower);
    fclose(fp); // 关闭文件

    system("pause");
    return 0;
}

运行结果:

在这里插入图片描述

4. 平均每个单词的字母数

编写一个程序,在遇到EOF之前,把输入作为字符流读取。该程序要报告平均每个单词的字母数。不要把空白统计为单词的字母。实际上,标点符号也不应该统计,但是现在暂时不同考虑这么多(如果你比较在意这点,考虑使用ctype.h系列中的ispunct()函数)。

代码:

#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
int main(void)
{
    char ch;
    FILE *fp;
    char fname[50]; // 存储文件名
    int count_alpha = 0, count_word = 0;
    bool start_count = false;

    printf("Enter the file name: ");
    scanf("%s", fname);
    fp = fopen(fname, "r"); // 只读模式打开文件
    if (fp == NULL)
    {
        printf("Failed to open file.\n");
        exit(1); // 退出程序
    }
    // getc(fp)从打开的文件中获取一个字符
    while ((ch = getc(fp)) != EOF)
    {
        // 如果没有开始计数并且字符是个字母,则开始计数
        if (isalpha(ch) && start_count == false)
        {
            start_count = true;
        }
        // 如果已经有开始计数并且字符不是个字母,则停止计数,单词数量+1
        else if (!isalpha(ch) && start_count == true)
        {
            start_count = false;
            count_word++;
        }
        // 如果已经有开始计数并且字符是个字母,开始字母计数,字母数量+1
        else if (isalpha(ch) && start_count == true)
        {
            count_alpha++;
        }
    }
    printf("总共读取了%d个单词,%d个字母,平均每个单词%f个字母。\n", count_word, count_alpha, (float)count_alpha / count_word);
    fclose(fp); // 关闭文件

    system("pause");
    return 0;
}

words.txt:

在这里插入图片描述

运行结果:

在这里插入图片描述

5. 猜数字

修改程序清单8.4的猜数字程序,使用更智能的猜测策略。例如,程序最初猜50,询问用户是猜大了、猜小了还是猜对了。如果猜小了,那么下一次猜测的值应是50和100中值,也就是75。如果这次猜大了,那么下一次猜测的值应是50和75的中值,等等。使用二分查找(binary search)策略,如果用户没有欺骗程序,那么程序很快就会猜到正确的答案。

代码:

#include <stdio.h>
#include <stdlib.h>
int main(void)
{
    int guess = 50;
    int gmax = 100, gmin = 1; // 猜测的最大值和最小值
    char response;

    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 and with an n if it's wrong.\n");
    printf("Uh...is your number %d?\n", guess);
    while ((response = getchar()) != 'y')
    {
        if (response == 'l')
        {
            gmax = guess;
            guess = (gmin + gmax) / 2;
            printf("Well, then, is it %d?\n", guess);
        }
        else if (response == 'u')
        {
            gmin = guess;
            guess = (gmin + gmax) / 2;
            printf("Well, then, is it %d?\n", guess);
        }
        else
        {
            printf("Sorry, I understand only l, u or y.\n");
        }
        while (getchar() != '\n')
            continue;
    }
    printf("I knew I could do it!\n");

    system("pause");
    return 0;
}

运行结果:

在这里插入图片描述

程序解释:

在这里插入图片描述

6.修改 get_first() 函数

修改程序清单8.8中的 get_first() 函数,让该函数返回读取的第1个非空白字符,并在一个简单的程序中测试。

代码:

#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
char get_first(FILE *fp);
int main(void)
{
    char ch;
    FILE *fp;
    char fname[50]; // 存储文件名

    printf("Enter the file name: ");
    scanf("%s", fname);
    fp = fopen(fname, "r"); // 只读模式打开文件
    if (fp == NULL)
    {
        printf("Failed to open file.\n");
        exit(1); // 退出程序
    }
    ch = get_first(fp);
    printf("%c\n", ch);
    fclose(fp);

    system("pause");
    return 0;
}
char get_first(FILE *fp)
{
    char ch;
    while (isspace(ch = getc(fp)))
        continue;
    return ch;
}

words.txt:

在这里插入图片描述

运行结果:

在这里插入图片描述

7. 修改第7章的编程练习8

修改第7章的编程练习8,用字符代替数字标记菜单的选项。用q代替5作为结束输入的标记

代码:

#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
#define PAY_RATE1 8.75
#define PAY_RATE2 9.33
#define PAY_RATE3 10.00
#define PAY_RATE4 11.20
#define TIME_BASE 40
#define OVERTIME 1.5
#define BREAK1 300
#define BREAK2 450
#define RATE1 0.15
#define RATE2 0.20
#define RATE3 0.25
void print_prompt(void);
int main(void)
{
    char ch;
    bool judge = false; // 这里的标志位必须为false,以防用户一开始就输入非数字
    double pay_rate;
    double hours;
    double gross, tax, net;

    print_prompt();
    while (scanf("%c", &ch) == 1)
    {
        judge = true; //每次循环标志位置为true
        switch (ch)
        {
        case 'a':
            pay_rate = PAY_RATE1;
            break;
        case 'b':
            pay_rate = PAY_RATE2;
            break;
        case 'c':
            pay_rate = PAY_RATE3;
            break;
        case 'd':
            pay_rate = PAY_RATE4;
            break;
        case 'q':
            printf("Bye!\n");
            break;
        default:
            printf("\nSorry, I understand only a, b, c, d, q, Please try again:\n");
            while (getchar() != '\n')
                continue;
            print_prompt();
            judge = false;
        }

        if (judge)
            break;
    }
    if (judge && ch != 'q')
    {
        printf("Enter your work hours in a week: ");
        scanf("%lf", &hours);
        if (hours > TIME_BASE)
            hours = TIME_BASE + (hours - TIME_BASE) * OVERTIME;
        gross = hours * pay_rate;
        if (gross < BREAK1)
            tax = gross * RATE1;
        else if (gross < BREAK2)
            tax = BREAK1 * RATE1 + (gross - BREAK1) * RATE2;
        else
            tax = BREAK1 * RATE1 + (BREAK2 - BREAK1) * RATE2 + (gross - BREAK2) * RATE3;
        net = gross - tax;
        printf("gross: %.2lf, tax: %.2lf, net: %.2lf\n", gross, tax, net);
    }

    system("pause");
    return 0;
}
void print_prompt(void)
{
    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");
}

运行结果:

在这里插入图片描述

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 a number.
Please enter a number, such as 2.5, -1.78E8, or 3: 1
22.4 + 1 = 23.4

代码:

#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
char get_first(void);
char get_choice(void);
float get_num(void);
void add(void);
void subtract(void);
void multiply(void);
void divide(void);
int main(void)
{
    char choice;
    while ((choice = get_choice()) != 'q')
    {
        switch (choice)
        {
        case 'a':
            add();
            break;
        case 's':
            subtract();
            break;
        case 'm':
            multiply();
            break;
        case 'd':
            divide();
            break;
        default:
            printf("\nSorry, I understand only a, s, m, d, q, Please try again:\n");
            break;
        }
    }
    printf("Bye!\n");

    system("pause");
    return 0;
}

char get_first(void)
{
    int ch;

    while (isspace(ch = getchar()))
        ;
    while (getchar() != '\n')
        ;
    return ch;
}

char get_choice(void)
{
    int ch;

    printf("Enter the operation of your choice:\n");
    printf("a. add          s. subtract\n");
    printf("m.multiply      d. divide\n");
    printf("q.quit\n");
    ch = get_first();
    return ch;
}

float get_num(void)
{
    float number;
    char ch;

    while (scanf("%f", &number) != 1)
    {
        while ((ch = getchar()) != '\n')
            putchar(ch); // 处理错误输出
        printf(" is not a number.\n");
        printf("Please enter a number, such as 15, -1.78E8, or 3: ");
    }
    return number;
}

void add(void)
{
    float num1, num2;
    printf("Enter first number: ");
    num1 = get_num();
    printf("Enter second number: ");
    num2 = get_num();
    printf("%f + %f = %f\n", num1, num2, num1 + num2);
}

void subtract(void)
{
    float num1, num2;
    printf("Enter first number: ");
    num1 = get_num();
    printf("Enter second number: ");
    num2 = get_num();
    printf("%f - %f = %f\n", num1, num2, num1 - num2);
}

void multiply(void)
{
    float num1, num2;
    printf("Enter first number: ");
    num1 = get_num();
    printf("Enter second number: ");
    num2 = get_num();
    printf("%f * %f = %f\n", num1, num2, num1 * num2);
}

void divide(void)
{
    float num1, num2;
    printf("Enter first number: ");
    num1 = get_num();
    printf("Enter second number: ");
    while ((num2 = get_num()) == 0)
    {
        printf("Enter a number other than 0: ");
    }
    printf("%f / %f = %f\n", num1, num2, num1 / num2);
}

运行结果:

在这里插入图片描述

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

UestcXiye

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值