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

如何用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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.01 20:50:28