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

C语言读取txt逗号分隔浮点数存入二维数组仅首行正确如何解决

问题原因分析
    1. 表头读取逻辑错误
      你使用fscanf(fp, "%s,", DUID)读取表头,而%s格式符会读取到空白符(换行、空格等)才停止,会把整个第一行表头全部读入DUID,并不会在第一个逗号处停止,这一步虽然不会直接导致后续读取失败,但逻辑不符合你的预期。
    1. fscanf匹配失败后指针不移动,且错误判断逻辑缺失
      你的CSV文件中存在大量非数字内容:比如xxxxx/aaaa等非法字符串、两个逗号连在一起的空字段,%f格式符遇到这类非数字内容时,会直接匹配失败,返回成功匹配的字段数(而非EOF),同时文件指针停在错误位置不再移动,后续所有fscanf调用都会持续匹配失败,所以除了第一行数据刚好全部是合法数字读取成功外,剩下的所有行都读取失败,保留了数组初始化的0值。
    1. 退出逻辑错误
      你仅在fscanf返回EOF时才退出循环,但匹配失败时返回值是小于4的整数,不会触发break,循环会一直跑完32次,所有失败的读取位置都保留初始0值。
    1. 多余的fclose调用
      你对同一个文件指针调用了两次fclose,属于未定义行为,虽然不影响读取结果,但属于代码BUG。
修正方案

正确的读取逻辑应该是先逐行读取整行内容,再拆分每行的字段,对每个字段单独校验转换,避免非法字符导致后续读取全部失败。

修正后代码

#define _CRT_SECURE_NO_WARNINGS 1
#define ROWS 31
#define COLUMNS 4
#include <stdio.h>
#include <stdlib.h>
#include <string.h> 

void openFile(char* str) {
    FILE* fp;
    int x = 1;
    char s[124] = { 0 };
    while (x == 1) {
        printf("Type the filename to process >\n");
        scanf("%123s", s);
        if ((fp = fopen(s, "r")) == NULL) {
            printf("error: file not found\n\n");
            x = 1;
        } else {
            fclose(fp);
            x = 0;
        }
        strcpy(str, s);
    }
}

// 校验字符串是否为合法浮点数,是就返回转换后的值,否则返回0
float parseNumber(const char* str) {
    if (str == NULL || *str == '\0') return 0.0f;
    char* endptr;
    float val = strtof(str, &endptr);
    // 整个字符串都被转换才是合法数字
    if (endptr == str || *endptr != '\0') {
        return 0.0f;
    }
    return val;
}

int main() {
    FILE* fp;
    float data[ROWS][COLUMNS] = { 0 };
    char filename[124];
    char lineBuf[256]; // 每行缓存

    openFile(filename);
    fp = fopen(filename, "r");
    if (fp == NULL) return 1;

    // 丢弃第一行表头
    fgets(lineBuf, sizeof(lineBuf), fp);

    int rows = 0;
    // 逐行读取,最多读ROWS行
    while (rows < ROWS && fgets(lineBuf, sizeof(lineBuf), fp) != NULL) {
        // 去掉行尾的换行符
        lineBuf[strcspn(lineBuf, "\r\n")] = '\0';
        char* token = strtok(lineBuf, ",");
        int col = 0;
        while (token != NULL && col < COLUMNS) {
            data[rows][col] = parseNumber(token);
            token = strtok(NULL, ",");
            col++;
        }
        rows++;
    }

    fclose(fp);

    // 输出结果
    for (int row = 0; row < rows; row++) {
        printf("This is row %d = %f, %f, %f, %f\n", row, data[row][0], data[row][1], data[row][2], data[row][3]);
    }

    return 0;
}
改动说明
  1. 先调用fgets读取整行表头直接丢弃,符合预期逻辑
  2. 新增parseNumber函数处理非法字段,遇到空值、非数字字符串统一返回0,不会中断后续读取
  3. 使用strtok按逗号拆分每行的字段,逐字段转换,避免非法字符导致整个读取流程阻塞
  4. 移除了多余的fclose调用,修正了数组定义的ROWS、COLUMNS为实际需要的31、4,避免空间浪费

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.01 14:15:04