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

C语言新手求助:创建存储未知行数文件数据的二维数组

嘿,作为C语言新手碰到这种动态数据存储的问题太正常啦!我来一步步帮你理清楚怎么搞定这个需求~

首先得说一句:用结构体数组来存储这些数据会比二维数组合适得多,因为你的数据包含不同类型(字符串、整数、浮点数),二维数组很难兼顾不同类型的存储——如果硬要用二维数组,只能把所有数据存成字符串,后续处理会非常麻烦。所以我先给你讲推荐的结构体方案,最后再提二维数组的实现方式。

推荐方案:使用结构体数组

1. 定义结构体

先定义一个结构体来对应每行的4个字段,这样每个字段的类型都能匹配:

#include <stdio.h>
#include <stdlib.h>

// 定义存储每个人数据的结构体
typedef struct {
    char role[20];    // 存储student/teacher,长度根据实际情况调整
    char name[50];    // 存储唯一姓名
    int age;          // 年龄(整数)
    float weight;     // 体重(浮点数)
} Person;

2. 统计文件行数(提前分配内存)

因为不知道总行数,我们可以先遍历一次文件统计行数,再分配对应大小的内存:

// 辅助函数:统计文件行数
int count_lines(FILE *fp) {
    int count = 0;
    char buffer[256];
    // 逐行读取直到文件末尾
    while (fgets(buffer, sizeof(buffer), fp) != NULL) {
        count++;
    }
    // 把文件指针移回开头,方便后续读取数据
    fseek(fp, 0, SEEK_SET);
    return count;
}

int main() {
    // 打开输入文件
    FILE *fp = fopen("input.txt", "r");
    if (fp == NULL) {
        perror("Failed to open input.txt");  // 打印错误原因
        return 1;
    }

    // 统计行数
    int total_people = count_lines(fp);
    // 分配结构体数组的内存
    Person *people = (Person*)malloc(total_people * sizeof(Person));
    if (people == NULL) {
        perror("Failed to allocate memory");
        fclose(fp);
        return 1;
    }

    // 逐行读取数据到结构体数组
    for (int i = 0; i < total_people; i++) {
        // 假设每行用空格分隔数据,格式要和文件匹配
        fscanf(fp, "%s %s %d %f", 
               people[i].role, people[i].name, &people[i].age, &people[i].weight);
    }

    // 示例:打印读取到的数据
    printf("Successfully read %d records:\n", total_people);
    for (int i = 0; i < total_people; i++) {
        printf("Role: %s | Name: %s | Age: %d | Weight: %.1f\n",
               people[i].role, people[i].name, people[i].age, people[i].weight);
    }

    // 一定要释放内存+关闭文件,避免泄漏
    free(people);
    fclose(fp);
    return 0;
}
进阶版:动态扩容(无需提前统计行数)

如果文件特别大,或者不想先遍历一次统计行数,可以用realloc边读边扩容内存,这样更灵活:

int main() {
    FILE *fp = fopen("input.txt", "r");
    if (fp == NULL) {
        perror("Failed to open input.txt");
        return 1;
    }

    int capacity = 4;  // 初始容量,先存4条数据
    Person *people = (Person*)malloc(capacity * sizeof(Person));
    if (people == NULL) {
        perror("Failed to allocate memory");
        fclose(fp);
        return 1;
    }

    int current_count = 0;
    Person temp_person;

    // 逐行读取,直到文件结束
    while (fscanf(fp, "%s %s %d %f", 
                  temp_person.role, temp_person.name, &temp_person.age, &temp_person.weight) == 4) {
        // 如果当前数据量达到容量,就扩容(比如翻倍)
        if (current_count == capacity) {
            capacity *= 2;
            Person *temp_ptr = (Person*)realloc(people, capacity * sizeof(Person));
            if (temp_ptr == NULL) {
                perror("Failed to reallocate memory");
                free(people);
                fclose(fp);
                return 1;
            }
            people = temp_ptr;
        }
        // 把临时数据存入数组
        people[current_count++] = temp_person;
    }

    // 打印结果
    printf("Successfully read %d records:\n", current_count);
    for (int i = 0; i < current_count; i++) {
        printf("Role: %s | Name: %s | Age: %d | Weight: %.1f\n",
               people[i].role, people[i].name, people[i].age, people[i].weight);
    }

    free(people);
    fclose(fp);
    return 0;
}
如果你非要用二维数组(不推荐)

因为二维数组要求所有元素类型相同,所以只能把所有字段都存成字符串。这种方式内存管理更复杂,后续处理数值类型还要手动转换,仅作参考:

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

#define MAX_FIELDS 4       // 每行4列
#define MAX_FIELD_LEN 50   // 每个字段的最大长度

int main() {
    FILE *fp = fopen("input.txt", "r");
    if (fp == NULL) {
        perror("Failed to open input.txt");
        return 1;
    }

    // 先统计行数
    int line_count = 0;
    char buffer[256];
    while (fgets(buffer, sizeof(buffer), fp) != NULL) line_count++;
    fseek(fp, 0, SEEK_SET);

    // 分配二维指针数组:data[行][列]
    char ***data = (char***)malloc(line_count * sizeof(char**));
    if (data == NULL) {
        perror("Failed to allocate memory");
        fclose(fp);
        return 1;
    }

    // 为每行分配字段指针
    for (int i = 0; i < line_count; i++) {
        data[i] = (char**)malloc(MAX_FIELDS * sizeof(char*));
        if (data[i] == NULL) {
            // 内存分配失败时,要释放之前已分配的内存,避免泄漏
            for (int j = 0; j < i; j++) {
                for (int k = 0; k < MAX_FIELDS; k++) free(data[j][k]);
                free(data[j]);
            }
            free(data);
            fclose(fp);
            return 1;
        }
        // 为每个字段分配内存并读取数据
        for (int j = 0; j < MAX_FIELDS; j++) {
            data[i][j] = (char*)malloc(MAX_FIELD_LEN * sizeof(char));
            if (data[i][j] == NULL) {
                // 同样要释放已分配的内存
                for (int x = 0; x <= i; x++) {
                    for (int y = 0; y < j; y++) free(data[x][y]);
                    free(data[x]);
                }
                free(data);
                fclose(fp);
                return 1;
            }
            fscanf(fp, "%s", data[i][j]);
        }
    }

    // 打印数据
    printf("Successfully read %d records:\n", line_count);
    for (int i = 0; i < line_count; i++) {
        printf("Role: %s | Name: %s | Age: %s | Weight: %s\n",
               data[i][0], data[i][1], data[i][2], data[i][3]);
    }

    // 逐层释放内存
    for (int i = 0; i < line_count; i++) {
        for (int j = 0; j < MAX_FIELDS; j++) free(data[i][j]);
        free(data[i]);
    }
    free(data);
    fclose(fp);
    return 0;
}
额外注意事项
  • 如果你的姓名包含空格(比如Mary Ann),fscanf会把空格当成分隔符,导致读取错误。这时候可以用fgets读取整行,再用strtok分割:
    char buffer[256];
    while (fgets(buffer, sizeof(buffer), fp) != NULL) {
        // 去掉换行符
        buffer[strcspn(buffer, "\n")] = '\0';
        // 按空格分割字符串
        char *token = strtok(buffer, " ");
        strcpy(temp_person.role, token);
        token = strtok(NULL, " ");
        strcpy(temp_person.name, token);
        token = strtok(NULL, " ");
        temp_person.age = atoi(token);
        token = strtok(NULL, " ");
        temp_person.weight = atof(token);
        // 存入数组...
    }
    
  • 所有内存分配后都要检查是否成功,避免空指针访问导致程序崩溃
  • 使用完动态分配的内存一定要释放,避免内存泄漏

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.20 07:22:37