You need to enable JavaScript to run this app. C语言逐字符存储逗号分隔格式文件到链表节点时,user、text字段打印为空白
优惠活动
大模型
产品
解决方案
定价
更多

C语言逐字符存储逗号分隔格式文件到链表节点时,user、text字段打印为空白

核心问题根因

你遇到的整段字符串打印空白,本质是写入user、text数组时没有重置写入偏移量,直接复用了读取ID阶段累计的循环索引,导致有效字符全部写到了数组的中后段,数组开头位置全是未初始化的堆内存垃圾。
拿测试文件第一行37,userf,hello举实际执行流程:

  • 读取ID段的循环走完后,索引值i会停在第一个逗号的下一位,也就是字符串里userf的首字符位置,此时i=3
  • 进入用户名读取循环后,你直接拿这个累计的i当post->user的数组下标写内容:
    • 第一个字符u被写到post->user[3]的位置
    • 后续s/e/r/f依次写入索引4/5/6/7
    • 循环碰到第二个逗号退出时,把字符串结束符\0写到post->user[8]
  • 此时post->user的内存状态完全不符合C语言字符串的存储要求:数组前3个索引位置是malloc分配的随机垃圾值,只有索引3-7存了实际的用户名,索引8才是结束符。当你用%s打印这个数组时,程序会从索引0开始逐字符找结束符,如果malloc出来的内存开头刚好是字节0(空字符),就会直接判定字符串为空,输出全空白——这刚好对应你调试时“逐字符写入检查内容正确,但整段打印为空”的现象。

text字段的写入逻辑存在完全一样的偏移问题,所以也会出现整段为空的情况。

附带的其他代码隐患
  • 用malloc分配的message节点没有做内存初始化,next指针是随机值,后续链表遍历大概率触发内存访问异常
  • 读取text的循环仅判断是否碰到换行符,没有处理文件最后一行无换行的边界场景,容易越界读取缓冲区内容
  • 写的末尾逗号判断逻辑完全失效:post->text[strlen(post->text)]这个位置本来就是字符串结束符\0,永远不可能等于逗号,整段判断没有任何实际作用
  • 没有对各字段的写入长度做校验,遇到超长用户名、超长文本时会直接造成数组越界,破坏相邻内存数据
修正方案
  • 每写入一个独立的字符串字段时,单独定义自己的写入偏移变量,不要复用跨字段的累计索引
  • 优先用calloc替代malloc分配节点内存,自动把堆内存清0,从根源上避免垃圾值干扰字符串识别
  • 写入每个数组时增加长度校验,防止越界
  • 增加空字符判断作为循环退出条件,兼容无换行的文件末尾场景

修正后的核心逻辑参考:

while(fgets(contents, 250, fp) != NULL) {
    int buf_idx = 0; // 全局遍历文件行缓冲区的索引
    char id_buf[16] = {0};
    // calloc自动清零分配的内存,避免垃圾值
    message *post = calloc(1, sizeof(message));
    post->next = NULL;

    // 读取ID段
    int id_pos = 0;
    while(contents[buf_idx] != ',' && contents[buf_idx] != '\0') {
        id_buf[id_pos++] = contents[buf_idx++];
        if(id_pos >= sizeof(id_buf)) break; // 防越界
    }
    id_buf[id_pos] = '\0';
    buf_idx++; // 跳过分隔用的逗号

    // 读取用户名字段
    int user_pos = 0;
    while(contents[buf_idx] != ',' && contents[buf_idx] != '\0') {
        post->user[user_pos++] = contents[buf_idx++];
        if(user_pos >= sizeof(post->user)) break; // 防越界
    }
    post->user[user_pos] = '\0';
    buf_idx++; // 跳过分隔用的逗号

    // 读取文本字段
    int text_pos = 0;
    while(contents[buf_idx] != '\n' && contents[buf_idx] != '\0') {
        post->text[text_pos++] = contents[buf_idx++];
        if(text_pos >= sizeof(post->text)) break; // 防越界
    }
    post->text[text_pos] = '\0';

    post->id = atoi(id_buf);
    addNodeToList(headmessage, post);
}

注:修正后每个字段的写入都是从数组索引0开始的,结束符紧跟在有效字符后面,完全符合C语言字符串的存储要求,不会再出现打印空白的问题。

内容的提问来源于stack exchange,提问作者Macer

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.30 09:54:10