C语言使用scanf输入含空格的多行字符串时遇到问题如何解决?
问题根源
你遇到的输入中断问题不是%[^\n]读不了空格(该格式符本身就是读到换行才停止,天然支持读取带空格的内容),核心原因是每次读完一行内容后,输入缓冲区中残留的换行符\n没有被消费,下一次进入循环执行scanf("%99[^\n]",...)时,第一个匹配到的字符就是\n,直接匹配失败返回0,后续输入就会卡住。
同时原有代码还有两个隐含问题:
while(!feof(stdin))的判断逻辑不可靠,feof是读操作失败后才会标记EOF,会导致最后一行多执行一次内存申请和输入逻辑- 没有校验
scanf的返回值,匹配失败时会往数组里写入无效内容
解决方案
因为你不能使用getchar系列函数,我们可以直接用scanf自带的格式符能力处理换行:在每次%[^\n]后面加%*1[\n],这里*代表忽略匹配到的内容、不会写入变量,刚好可以匹配并丢弃缓冲区里的换行符,完全符合你的使用限制。
修正后的完整代码如下:
#include <stdio.h> #include <stdlib.h> int main () { int i = 0; // 初始支持最多1000行输入,需要更多可以自行调整,或者加动态扩容逻辑 char **list = malloc(1000 * sizeof(char*)); if (list == NULL) { perror("内存申请失败"); return 1; } while(i < 1000) { // 加边界判断避免数组越界 list[i] = malloc(1000 * sizeof(char)); if (list[i] == NULL) { perror("内存申请失败"); return 1; } printf("Enter string with num %d: ", i+1); // %99[^\n]读取最多99个非换行字符,%*1[\n]匹配并丢弃后面的1个换行符 int ret = scanf("%99[^\n]%*1[\n]", list[i]); if (ret == EOF) { // 读到输入结束直接退出循环 free(list[i]); // 释放提前申请的当前行内存 break; } i++; } printf("\n"); for (int j = 0; j < i; j++) { printf("Your strings by num %d: %s\n", j+1, list[j]); free(list[j]); // 释放单条字符串内存,避免泄漏 } free(list); // 释放指针数组内存 return 0; }
修改说明
- 调整
scanf格式为"%99[^\n]%*1[\n]":不依赖禁用的函数/格式符即可处理残留换行,解决输入中断问题 - 替换不可靠的
while(!feof(stdin))逻辑,改为校验scanf返回值判断输入是否结束,避免无效的内存申请和输入 - 补充内存申请失败校验和使用后的内存释放逻辑,避免内存泄漏和程序崩溃
- 调整数组下标从0开始,符合C语言数组的常规使用习惯
- 如果需要支持更长的单行输入,调整
malloc(1000)的数值和scanf里的%99数值即可,注意要留1位空间给字符串结束符\0
内容的提问来源于stack exchange,提问作者mobdevkun
相关产品推荐
相关产品推荐

