C语言读取多字符串存入二维数组代码输出异常求助
我来帮你拆解下这段代码出问题的原因,以及怎么修复:
问题根源
你看到的诡异输出,核心问题出在C语言字符串的终止符'\0'上,再加上数组空间分配不足:
- 你定义的二维数组是
char a[n][n],每个子数组的长度刚好是n。当你输入长度为n的字符串时,会把这个子数组的空间完全占满,根本没地方放C语言字符串必须的终止符'\0'。 - 你用的
scanf(" %[^\n]", a[i])会读取换行前的所有字符,但它不会自动在字符串末尾添加'\0'。而printf("%s")的工作逻辑是从起始地址一直读字符,直到碰到'\0'才停下——既然当前子数组里没有这个终止符,它就会越过边界去读后面内存里的内容(也就是你存在下一个子数组里的字符串),最终就出现了所有字符串串在一起的输出。
两种可靠的修正方案
方案一:调整数组大小+限制scanf读取长度
给每个字符串多分配1个字节存'\0',同时在scanf里限制最大读取字符数,避免越界:
#include<stdio.h> #include<stdlib.h> #include<string.h> int main(){ int i,n; scanf("%d",&n); // 每个字符串预留n+1个空间:n个有效字符 + 1个'\0' char a[n][n+1]; for(i=0;i<n;i++){ // %.*[^\n] 用*指定读取长度为n,最多读n个字符,自动补'\0' scanf(" %.*[^\n]", n, a[i]); } for(i=0;i<n;i++){ printf("%s\n",a[i]); } return 0; }
方案二:用fgets读取(更推荐,更安全)
fgets会自动给字符串加'\0',还能更好处理换行符问题,只是要注意清理缓冲区残留的换行:
#include<stdio.h> #include<stdlib.h> #include<string.h> int main(){ int i,n; scanf("%d",&n); // fgets会读入换行符,所以数组要留n+2的空间:n个字符 + 换行符 + '\0' char a[n][n+2]; // 吃掉scanf("%d")后留在缓冲区的换行符,避免第一次fgets读空行 getchar(); for(i=0;i<n;i++){ fgets(a[i], sizeof(a[i]), stdin); // 去掉fgets读进来的换行符(如果存在) a[i][strcspn(a[i], "\n")] = '\0'; } for(i=0;i<n;i++){ printf("%s\n",a[i]); } return 0; }
额外提醒
- 如果输入的字符串长度小于
n,方案一依然有效,scanf碰到换行就会停,自动补'\0'。 - 用
fgets时一定要记得处理scanf留下的换行符,不然第一次读取会拿到空行,影响结果。
内容的提问来源于stack exchange,提问作者K Akshay
相关产品推荐
相关产品推荐

