C语言拾遗
2024-04-22 23:00:46

引子

我平时常用C写一些自用小工具,凯撒密码破解器啦,辅助包管理器啦……但也发现了许多C语言中,自己一直忽略的小细节。

1. 获取带任意多空格的字符串

如果缓冲区内有换行符,则:

1
2
getchar(); 
scanf("%[^\n]", buffer);

若无,则将第一句去掉。第二行代码中间的正则表达式意思是,遇到换行符,则停止读取。

scanf()蛮危险,也可以使用逐个字符读取的方法。

2. fflush(stdout)

printf()的行为出现异常,比如:

  • 打印到屏幕上的顺序出现颠倒、错乱。
  • 输出了本不应该输出的字符。

试试在代码中的相应部分添加fflush(stdout)。上述两个异常,第一个异常原因未知。第二个的原因是缓冲区太小,内容太多导致溢出。

fflush()说明如下:

For output streams (and for update streams on which the last operation was output), writes any unwritten data from the stream’s buffer to the associated output device.

For input streams (and for update streams on which the last operation was input), the behavior is undefined.

If stream is a null pointer, all open output streams are flushed, including the ones manipulated within library packages or otherwise not directly accessible to the program.

这里提到的一点很重要,fflush(stdin)是一个UB(Undefined Behavior,未定义行为),如果需要清除输入缓冲区里的内容,建议具体问题具体分析,一个例子:

1
2
3
4
5
int FlushStdin() {
int c;
while((c = getchar()) != '\n');
return SUCCESS;
}

3. EOF和feof()

当判断是否是文件结尾的时候,不要使用如下的方法:

1
current_character == EOF

要使用如下的方法:

1
feof(current_character) != 0

因为EOF代表-1,而有的文件结尾不是-1。注意,feof()若判断为文件结尾,返回非0值。

4. switch…case…与if…else…效率比较

前者效率高,因为前者在汇编层面依靠跳转表实现,先判断值,随后直接判断跳转到哪里。后者则通过生成一串判断指令+条件跳转、非条件跳转指令实现。

参考资料

C语言,如何读取带空格的字符串 - 小白一枚

cppreference - fflush()

Prev
2024-04-22 23:00:46
Next