使用fscanf写入char**数组时,写入过程打印正常,完成后遍历打印输出异常
输出异常的核心原因
你遇到的输出差异根本不是两种打印方式的区别导致的,是代码本身存在严重的内存管理错误,只是写入阶段的临时打印刚好没有触发内存覆盖的问题,才出现了“单步打印正常、整体遍历混乱”的假象。
代码中的具体错误点
- 对
char**数组的内存分配逻辑理解偏差。你通过malloc(1000*sizeof(char*))申请的空间,仅仅是1000个可以存储char*指针的容器,这些指针本身没有被初始化,全部是指向随机内存位置的野指针,没有指向任何可合法写入字符的缓冲区。 fscanf的传参完全错误。stop_words[i]本身就是char*类型,作为字符串读取的目标地址直接传入即可,但你写的&stop_words[i]是char**类型,和函数要求的入参类型完全不匹配。这行代码实际执行时,会把读取到的字符串内容,直接硬写入野指针指向的随机内存地址,完全不受控。- 循环判断存在经典bug。用
while(!feof(fp))做循环条件,会导致读到文件末尾时多执行一次循环,进一步加剧野指针写内存的问题。
两种打印场景的表现差异来源
- 写入过程中临时打印:每次fscanf刚把一串字符写入某块随机内存,紧接着就从同一地址读取打印,此时这块内存还没有被后续的写入操作覆盖,因此能读到刚写入的完整字符串,看起来输出正常。
- 全部写入完成后遍历打印:循环后续的每一次fscanf操作,都会往新的野指针对应的随机内存写字符串。由于野指针的指向是随机的,且相邻的野指针指向的内存位置通常很近,新写入的字符串会直接覆盖之前已经存储的旧字符串的尾部。你看到的
immediatimportanimportanindex这类混乱输出,就是后面写入的单词内容截断、覆盖了前面存储的单词的后半段,最终遍历读到的就是被反复拼接、截断的无效字符串。
正确实现的注意事项
- 给每个数组元素单独分配合法的字符缓冲区。每读取一个单词前,先给对应的
stop_words[i]申请足够长度的可写内存,比如按最长单词255字节计算,执行stop_words[i] = malloc(256 * sizeof(char))。 - 修正fscanf的调用方式。去掉多余的取地址符,同时限制读取长度避免溢出,写成
fscanf(fp, "%255s", stop_words[i])。 - 修正循环判断逻辑。不要用
feof做循环条件,直接判断fscanf的返回值是否匹配预期,写成while(fscanf(fp, "%255s", stop_words[i]) == 1) { i++; },确保循环在真正读到有效单词时才执行自增。 - 遍历打印时只遍历到实际有效单词的索引i值,不要遍历到固定的1000次避免访问未初始化的指针。
内容的提问来源于stack exchange,提问作者Hakan Alp
相关产品推荐
相关产品推荐

