如何使用fgets获取输入长度并判断输入是否超过缓冲区大小
问题代码的错误点
- 对
sizeof运算符的理解错误:sizeof是编译期计算的,返回的是对应类型占用的内存字节数,和运行时输入的内容长度完全无关。你打印的几个值都是对应类型的固定大小:size_t在64位系统占8字节、指针占8字节、int占4字节、FILE*指针占8字节,所以不管输入什么都会输出固定值。 - 逻辑分支错误:
if分支后直接执行*more = 0,无论判断条件是否成立,more最终都会被赋值为0,前面的判断等于无效。 - 校验逻辑完全不符合
fgets的特性:fgets最多只会读取buf_len - 1个字符到缓冲区,末尾自动补\0,所以strlen(buf)的最大值永远是buf_len - 1,不可能大于buf_len,原来的判断条件永远不会成立。
正确实现逻辑
fgets的特性是:如果输入的整行内容(包括末尾的换行符)长度小于buf_len,会把换行符也读入缓冲区;如果输入长度大于等于buf_len,则只会读满buf_len - 1个字符,不会包含换行符,剩余内容留在系统输入缓冲区。我们可以通过是否读到换行符,结合字符串长度判断是否有未读完的内容:
int read_stdin(char *buf, int buf_len, int *more) { // 初始化more默认值为0 *more = 0; // 校验输入参数合法性 if (buf == NULL || buf_len <= 0 || more == NULL) { return -1; } // 读取输入,判断fgets是否调用失败 if (fgets(buf, buf_len, stdin) == NULL) { // 出错或者读到EOF return -1; } size_t input_len = strlen(buf); // 判断是否读到换行符 if (input_len > 0 && buf[input_len - 1] == '\n') { // 整行读完,可选:去掉末尾的换行符 buf[input_len - 1] = '\0'; input_len--; } else if (input_len == buf_len - 1) { // 缓冲区已满,还有剩余输入未读完 *more = 1; } // 返回实际读到的有效字符长度 return (int)input_len; }
校验规则说明
- 输入内容(不含末尾换行符)长度 ≤
buf_len - 1:能读到换行符,more设为0 - 输入内容(不含末尾换行符)长度 ≥
buf_len:缓冲区读满且没有换行符,more设为1
内容的提问来源于stack exchange,提问作者Gabriel Lam
相关产品推荐
相关产品推荐

