C语言输入函数读取'\n'的优雅处理方案及相关问题排查
K&R 指针实现字符串拼接练习问题解答
针对提出的三个问题的具体解答
1. fgets()遇到换行完成读取的更优写法
你当前写的while(fgets(arr, MAXLINE, stdin)) {break;}属于无意义的包装:fgets()本身在成功读取到内容时会返回传入的数组指针,读取失败/触发EOF时返回NULL,直接判断返回值即可,不需要套循环加break。
更合理的写法需要同时处理「输入内容超过缓冲区长度,剩余字符残留在stdin」的边界情况,避免残留字符影响后续输入逻辑:
if (fgets(arr, MAXLINE, stdin) == NULL) { // 处理读取失败/EOF场景,直接将字符串置空 *arr = '\0'; return 0; } // 检查当前读取内容中是否包含换行符,判断是否读完整行 if (strchr(arr, '\n') == NULL) { int c; // 逐字符读取剩余缓冲区内容直到换行/EOF,清空残留 while ((c = getchar()) != '\n' && c != EOF); }
2. fgets()末尾换行符的处理
fgets()是C标准库规定的固定行为:只要缓冲区空间足够,就会把触发读取终止的'\n'存入目标字符串,没有内置参数可以自动跳过该换行符,必须手动覆写。
处理逻辑可以和上面的超长输入判断合并实现:
char *newline_pos = strchr(arr, '\n'); if (newline_pos != NULL) { // 找到换行符位置,直接替换为字符串结束符 *newline_pos = '\0'; } else { // 未找到换行符说明输入超长,清空缓冲区残留 int c; while ((c = getchar()) != '\n' && c != EOF); }
3. 连续两次弹出输入提示的原因与修复
该问题由两个bug共同导致:
- 第一,
scanf(" %d", &c)仅会跳过读取数字之前的空白字符,用户输入数字后敲击的回车符会残留在输入缓冲区中,后续第一次调用fgets()时会直接读到这个空换行,立刻返回空字符串,不会等待用户输入。 - 第二,你在
c == 1的重输分支中,手动调用了一次get_input(input2),随后又通过goto check再次调用了一次get_input(),等于连续触发了两次输入流程,自然会打印两次提示。
另外代码中存在类型不匹配问题:存储选项的变量c定义为char类型,但是%d格式符要求传入int*类型参数,会触发未定义行为,需要将c改为int类型。
修复步骤:
- 调用scanf读取选项后,手动清空输入缓冲区的所有残留字符直到换行/EOF
- 删除
c==1分支中多余的get_input(input2)调用
其他代码问题修正
原始代码还有几个容易触发bug的问题:
- 标准C中
main函数返回值应为int,写void main()属于不符合规范的写法 - 自定义的
str_cat函数最后多余写了一句*s = '\0':前面的拷贝循环while((*s++ = *t++) != '\0')已经将源字符串的结束符拷贝到目标位置,额外赋值会导致越界写入 - 原始长度判断写的
+2是把fgets读取的换行符算入了长度,处理掉换行符后只需要+1预留字符串结束符的空间即可 - 自定义函数的返回值与实际逻辑不匹配:
str_cat和get_input都没有实际返回值,不需要定义为int返回类型
修正后完整可运行代码
#include <stdio.h> #include <string.h> #define MAXLINE 1000 int get_input(char *s); void str_cat(char *s, char *t); int main() { char input1[MAXLINE], input2[MAXLINE]; int c; get_input(input1); check: get_input(input2); if ((strlen(input1) + strlen(input2) + 1) <= MAXLINE) { str_cat(input1, input2); printf("%s\n", input1); } else { input2[0] = '\0'; printf("String overflow\n Press: \n 1: Re-enter string. \n 2: Exit.\n"); scanf(" %d", &c); // 清空scanf残留的输入缓冲区内容 int tmp; while ((tmp = getchar()) != '\n' && tmp != EOF); if (c == 1) { input2[0] = '\0'; goto check; } } return 0; } int get_input(char *arr) { printf("Enter the string: \n"); if (fgets(arr, MAXLINE, stdin) == NULL) { *arr = '\0'; return 0; } // 处理末尾换行与超长输入残留 char *newline_pos = strchr(arr, '\n'); if (newline_pos != NULL) { *newline_pos = '\0'; } else { int c; while ((c = getchar()) != '\n' && c != EOF); } return 0; } void str_cat(char *s, char *t) { while (*s != '\0') { s++; } while ((*s++ = *t++) != '\0') { ; } }
内容的提问来源于stack exchange,提问作者limbo1927
相关产品推荐
相关产品推荐

