You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

数组拷贝循环致元素全相同: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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.15 08:10:15