能否用fgets或gets_s正确读取空字符?读取含空字符输入需用fgetc/fread吗?
读取含空字符的输入:fgets/gets_s的局限与正确方案
直接给你明确结论:fgets和gets_s都没法正确读取包含空字符的输入,如果你的需求是从stdin读取带空字符的内容,必须用fgetc或者fread这类面向原始字节的函数。
为什么fgets/gets_s不行?
这俩函数的设计目标是处理C语言里标准的“以空字符'\0'结尾的字符串”。对它们来说,空字符不是普通的输入数据,而是字符串的终止标志——一旦读取到'\0',函数就会停止读取,并且把这个'\0'作为字符串的结束符存在缓冲区里,后面的输入内容直接被忽略。哪怕你的输入里有多个字节,只要中间出现了'\0',它们就会认为读取完成了,根本没法完整捕获包含空字符的输入。
而且gets_s虽然是gets的“安全版本”(限制了读取长度),但核心逻辑还是围绕C风格字符串,同样把'\0'当终止符,所以完全不适用这种场景。
正确的做法:用fgetc或fread
这两个函数是直接操作原始字节的,不会把任何字节当成特殊的终止符(除了fgetc会识别EOF),能完整读取所有输入字节,包括空字符。
举两个简单的示例:
用fread批量读取
#include <stdio.h> int main() { char buffer[256]; // 读取最多256字节的输入,不管有没有空字符 size_t bytes_read = fread(buffer, 1, sizeof(buffer), stdin); printf("总共读取了 %zu 字节的数据\n", bytes_read); // 遍历输出每个字节的十六进制值,能看到空字符(0x00) for (size_t i = 0; i < bytes_read; i++) { printf("第 %zu 字节: 0x%02X\n", i, (unsigned char)buffer[i]); } return 0; }
用fgetc逐个读取
#include <stdio.h> int main() { char buffer[256]; size_t read_count = 0; int current_char; // 逐个读取直到EOF或者缓冲区满 while (read_count < sizeof(buffer) && (current_char = fgetc(stdin)) != EOF) { buffer[read_count++] = (char)current_char; } printf("总共读取了 %zu 字节的数据\n", read_count); return 0; }
这两种方式都能正确捕获包含空字符的输入,完全不受'\0'的影响。
内容的提问来源于stack exchange,提问作者anatolyg
相关产品推荐
相关产品推荐

