如何用C语言读取contacts.csv文件中的多行数据?
问题分析与修复方案
原代码核心问题
- 链表节点分配逻辑错误:一次性给
*head分配50个Contact内存,但链表需要逐个节点动态分配;初始节点的next是野值,第一次循环后*head = (*head)->next会变成无效地址或NULL,直接终止循环。 - fscanf格式串错误:格式串末尾的换行符干扰读取,还重复写了两次
&((*head)->company),导致字段解析错位,后续phone、address等字段读错位置。 - 返回值判断逻辑错误:
fscanf返回成功读取的字段数,应该判断是否等于实际字段数(你的CSV每行是11个字段),而非>0,避免部分匹配导致的数据错误。 - 丢失链表头指针:循环中直接修改
*head,原头指针被覆盖,函数返回后外部无法访问整个链表。
修正后的代码
#include <stdio.h> #include <stdlib.h> #include <string.h> // 假设Contact结构体定义如下(可根据实际定义调整) typedef struct Contact { int id; char firstName[50]; char middleName[50]; char lastName[50]; char company[50]; char phone[50]; char address[100]; char birthday[20]; char website[100]; char note[200]; int status; struct Contact *next; } Contact; int deserialize(Contact **head) { FILE *file = fopen("contacts.csv", "r"); // 文本文件用"r"模式打开即可 if (file == NULL) { perror("打开文件失败"); return 0; } Contact *current = NULL; *head = NULL; // 初始化头指针为NULL while (1) { // 为每个新节点单独分配内存 Contact *newNode = (Contact *)malloc(sizeof(Contact)); if (newNode == NULL) { perror("内存分配失败"); // 可添加内存释放逻辑避免泄漏 return 0; } memset(newNode, 0, sizeof(Contact)); // 初始化节点内存,避免野值 // 读取11个字段,匹配CSV实际字段数 int readCount = fscanf(file, "%d,%[^,],%[^,],%[^,],%[^,],%[^,],%[^,],%[^,],%[^,],%[^,],%d", &newNode->id, newNode->firstName, newNode->middleName, newNode->lastName, newNode->company, newNode->phone, newNode->address, newNode->birthday, newNode->website, newNode->note, &newNode->status); if (readCount == EOF) { // 读取到文件末尾 free(newNode); break; } if (readCount != 11) { // 字段数不匹配则跳过当前行 printf("行格式错误,读取到%d个字段\n", readCount); free(newNode); continue; } newNode->next = NULL; if (*head == NULL) { *head = newNode; // 第一个节点作为链表头 current = newNode; } else { current->next = newNode; // 追加到链表尾部 current = newNode; } printf(" head: %s\n", newNode->firstName); } fclose(file); return 1; }
额外说明
- 你的CSV每行实际是11个字段(比如
4,d,d,d,,,,,,,,0:1个int + 3个char +7个空字段 +1个int),需确保格式串字段数与实际一致。 - 打开文本文件用
"r"模式即可,"rb"是二进制模式,不适合读取CSV文本。 - 用
memset初始化节点内存,避免未初始化的字符串出现乱码。
内容的提问来源于stack exchange,提问作者nomnom
相关产品推荐
相关产品推荐

