第14章 用户接口处理相关编码准则

2019-08-09  本文已影响0人  FelixDai

14.1 确保保存输入值的变量足够大

考虑数组和数据类型大小能够保存输入值

14.2 转换说明符和参数个数应保持一致

C语言的哲学是,为最大限度发挥程序员能动性,向其提供最大限度的自由。C语言相信程序员的能力,此处所说的“能力”同样包含发现并解决可能出现的问题的能力。换言之,C语言认为发现并解决可能出现的问题是程序员的责任。

我们可以从printf()函数中找到体现这一观点的示例。程序员需要保证printf()函数的转换说明符的个数和输出参数列表保持一致,C语言并不会检查二者是否一致。

个数不一致的情况又可以分为两种。一是输出参数的个数多于转换字符。

printf ("输出%d和%d", num1, num2, num3, num4);

此时编译器选择忽略num3和num4,这不会引起任何问题。当然,没有引起问题并不意味着应该编写这种形式的代码。

第二种情况是,转换说明符多余输出参数的个数。这种情况下,容易出现问题。因此,使用printf()函数是,要始终保持转换说明符与输出参数的个数保持一致。这一点同样适用于scanf()函数。

14.3 使用fgets()和sscanf()函数而非scanf()函数

C语言中,最常用的函数应该就是printf()函数和scanf()函数,但scanf()函数存在一个问题,它对文件末尾出现的EOF的处理并不稳定。出现这种情况的原因是,scanf()函数读入字符串的过程城中,中间遇到空白字符或特殊字符后,会停止读入。因此,最好在一开始就按照能够处理空白和特殊字符的方式进行编码,即应该编写能够读取整行输入值的程序。

Windows环境下,EOF对应的键盘输入值为 ^Z(Ctrl+Z),UNIX中对应的是 ^D(Ctrl+D)

要实现这种功能,应该依次使用fgets()函数和sscanf()函数。fgets()函数可以包含特殊字符和空白字符在内的整行内容,并保存到标准输入设备的缓存中的函数,而这些内容又可以被sscanf()函数读取并转存入变量。

#include <stdio.h>
char console_line[80]; // 控制台界面中一行字符串能达到的最大长度
int number;

int main(void) {
    printf("请输入数值:");
    fgets(console_line, sizeof(console_line), stdin);
    sscanf(console_line, "%d", &number);
    // …略…
    printf("%d的2倍是%d。\n", number, number * 2);
    return 0;
}

14.4 使用fflush()函数清空标准输入/输出设备缓冲

出现运行时错误时,程序无法正常终止。运行时错误通常出现在栈溢出、数据一处、除以0、引用错误地址等情况中,而问题在于,出现这种运行时错误后,程序是在没有清空标准输入/输出设备的缓冲的状态下终止的。如下示例所示:

#include <stdio.h>
int main(void) {
    int num1 = 1;
    int num2 = 0;
    printf("运行时错误出现前\n");
    num1 = num1 / num2;
    printf("运行时错误出现后\n");
    return 0;
}

编译执行该程序时,界面上不会出现任何内容。为什么会这样呢?执行除以0操作并触发运行时错误前,明明试图输出“运行时错误出现前”这句信息。根据printf()函数的原理,该语句并不立刻输出到界面,而是将其输出到缓冲。随着程序的正常运行,缓冲保存的语句再输出到界面。但该程序将缓冲保存的语句输出到界面前,就因出现运行时错误而提前终止,这条信息也就因此被遗留在缓冲内。

为了防止出现这种问题,我们需要使用fflush()函数。该函数可以将缓冲内容强制输出到输入/输出设备。因此,执行以下程序可以在界面看到输出信息。

#include <stdio.h>
int main(void) {
    int num1 = 1;
    int num2 = 0;
    
    printf("运行时错误出现前\n");
    fflush(stdout); // 将上一条语句从缓冲强制传送到输出设备

    // …略…

    num1 = num1 / num2;
    printf("运行时错误出现后\n");
    return 0;
}

使用fflush()函数可能影响程序运行速度,但它同时可以在出现运行时错误时完全清空缓冲,保证下一个程序的稳定性。

上一篇 下一篇

猜你喜欢

热点阅读