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

C语言读取CSV文件单条正常多条报错:格式问题排查

CSV文件读取错误排查与修复(C语言场景)

问题现象

使用fscanf读取TXT格式CSV文件时,单条数据可正常读取,包含两条数据时触发File format incorrect.错误。

用户提供的文件内容:

1,Nanggroe Aceh Darussalam,Rumah Sakit,RSU Cut Nyak Dhien,Jl. Tm Bahrum No. 1 Langsa
2,Jawa Barat,Klinik Utama,dr. Sunarhadi,Raya Cikaret No. 12

原读取代码:

do{
    read = fscanf(file,
                    "%d,%100[^,],%100[^,],%100[^,],%100[^,]\n",          
                    &students[records].no, 
                    students[records].prov, 
                    students[records].tipe, 
                    students[records].nama,
                    students[records].alamat); 

    if (read == 5) records++;
    
    if (read != 5 && !feof(file)){
      printf("File format incorrect.\n");
      return 1;
    }
    
    if (ferror(file)){
      printf("Error reading file.\n");
      return 1;
    }

  } while (!feof(file));

期望输出:

No      : 1
Prov    : Nanggroe Aceh Darussalam
Tipe    : Rumah Sakit
Nama    : RSU Cut Nyak Dhien
Alamat  : Jl. Tm Bahrum No. 1 Langsa

No      : 2
Prov    : Jawa Barat
Tipe    : Klinik Utama
Nama    : dr. Sunarhadi
Alamat  : Raya Cikaret No. 12

错误原因

  1. 格式字符串匹配问题:最后一个字段使用%100[^,]会匹配所有非逗号字符,包括换行符,导致换行符被读入alamat字段。后续的\n格式符虽然会跳过空白,但读取最后一行时,若该行无末尾换行,fscanf尝试匹配\n会触发EOF,导致返回值异常。
  2. 循环逻辑缺陷:do...while(!feof(file))的写法会导致文件读完后多执行一次循环,此时fscanf返回EOF,触发read !=5的判断,进而抛出格式错误。

修复方案

改用fgets读取整行后再用sscanf解析,避免直接用fscanf处理跨换行的字段匹配问题,同时修正循环逻辑:

修正后的读取代码

#include <stdio.h>
#include <string.h>

#define MAX_LINE 512
#define MAX_RECORDS 100 // 根据实际需求调整数组大小

typedef struct {
    int no;
    char prov[101];
    char tipe[101];
    char nama[101];
    char alamat[101];
} Student;

int main() {
    FILE *file = fopen("data.txt", "r");
    if (!file) {
        printf("Failed to open file.\n");
        return 1;
    }

    Student students[MAX_RECORDS];
    int records = 0;
    char line[MAX_LINE];
    int read;

    while (fgets(line, MAX_LINE, file) != NULL) {
        // 去除行尾的换行符
        size_t len = strlen(line);
        if (len > 0 && line[len-1] == '\n') {
            line[len-1] = '\0';
        }

        // 解析单行数据
        read = sscanf(line,
                      "%d,%100[^,],%100[^,],%100[^,],%100[^,]",          
                      &students[records].no, 
                      students[records].prov, 
                      students[records].tipe, 
                      students[records].nama,
                      students[records].alamat); 

        if (read != 5) {
            printf("File format incorrect at line %d.\n", records + 1);
            fclose(file);
            return 1;
        }
        records++;

        if (records >= MAX_RECORDS) {
            printf("Exceeded maximum record limit.\n");
            fclose(file);
            return 1;
        }
    }

    if (ferror(file)) {
        printf("Error reading file.\n");
        fclose(file);
        return 1;
    }
    fclose(file);

    // 打印结果
    for (int i = 0; i < records; i++) {
        printf("No      : %d\n", students[i].no);
        printf("Prov    : %s\n", students[i].prov);
        printf("Tipe    : %s\n", students[i].tipe);
        printf("Nama    : %s\n", students[i].nama);
        printf("Alamat  : %s\n\n", students[i].alamat);
    }

    return 0;
}

修复说明

  1. 整行读取:用fgets读取完整一行,确保每次处理独立的一条数据,避免换行符干扰字段解析。
  2. 去除换行符:提前去掉行尾的换行符,让sscanf可以准确解析到行尾。
  3. 循环逻辑优化:while(fgets(...))直接判断是否读取到有效行,避免feof的时机问题。
  4. 边界检查:增加数组容量检查,防止越界。

测试结果

运行修正后的代码,将输出与用户期望完全一致的内容。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.08 23:15:38