数组拷贝循环致元素全相同:C语言文件字符串读取问题
问题分析与解决
嘿,这个问题我刚学C的时候也踩过一模一样的坑!核心问题出在你对指针的理解上:
你每次循环里执行 fileContents[stringsInFile] = buff;,这里并不是把buff里的字符串复制到数组元素里,而是把buff这个数组的内存地址赋值给了数组的每个元素。而buff是一块固定的栈内存区域,每次fgets都会把新读取的字符串覆盖到这块内存里。所以当循环结束后,所有数组元素都指向同一块内存,自然显示的都是最后一次读取的字符串啦。
修复方案
你需要为每个字符串单独分配内存,把buff里的内容复制到新内存中,而不是直接赋值地址。这里有两种常用方法:
方法1:使用strdup(最简单)
strdup会自动分配足够的内存,然后把字符串复制进去,非常方便:
// 先修正数组的定义:原代码用fileSize(字节数)作为数组长度不合理,应该先统计字符串数量 rewind(fp); long stringsInFile = 0; char buff[255]; // 第一次循环统计字符串总数 while (fgets(buff, 255, fp)) { stringsInFile++; } rewind(fp); // 分配存储字符串指针的数组(用malloc更灵活,避免变长数组的栈溢出风险) char** fileContents = malloc(stringsInFile * sizeof(char*)); if (!fileContents) { perror("malloc failed"); fclose(fp); return 1; } stringsInFile = 0; while (fgets(buff, 255, fp)) { // 复制字符串到新内存 fileContents[stringsInFile] = strdup(buff); // 注意:strdup可能分配失败,实际代码里最好加个判断 if (!fileContents[stringsInFile]) { perror("strdup failed"); // 还要记得释放已经分配的内存,避免泄漏 for (long i = 0; i < stringsInFile; i++) { free(fileContents[i]); } free(fileContents); fclose(fp); return 1; } stringsInFile++; }
方法2:手动malloc + strcpy
如果不想用strdup(有些环境可能需要自己实现),可以手动分配内存再复制:
// 同样先统计字符串数量... stringsInFile = 0; while (fgets(buff, 255, fp)) { // 计算需要的内存长度(+1是为了存储字符串结束符'\0') size_t strLen = strlen(buff); fileContents[stringsInFile] = malloc(strLen + 1); if (!fileContents[stringsInFile]) { // 错误处理同上 perror("malloc failed"); // 清理已分配内存 for (long i = 0; i < stringsInFile; i++) { free(fileContents[i]); } free(fileContents); fclose(fp); return 1; } // 复制字符串 strcpy(fileContents[stringsInFile], buff); stringsInFile++; }
额外注意事项
- 原代码中
char* fileContents[fileSize];是变长数组(VLA),虽然C99支持,但如果文件很大,可能会导致栈溢出,用malloc分配堆内存更安全。 - 记得最后要释放所有分配的内存,避免内存泄漏:
for (long i = 0; i < stringsInFile; i++) { free(fileContents[i]); } free(fileContents); fgets会把换行符\n也读进来,如果不需要的话,可以手动去掉(比如用strchr找到'\n'后替换成'\0')。
内容的提问来源于stack exchange,提问作者vulcao
相关产品推荐
相关产品推荐

