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
相关产品推荐
相关产品推荐

