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

动态结构体数组实现与问题排查:选型、读取及打印异常

问题解答:结构体数组/链表选择与代码错误排查

一、结构体数组 vs 链表(用于快速排序)

直接结论:必须选动态结构体数组。
快速排序的核心依赖随机访问能力——要快速定位分区点、递归访问左右子数组。链表只能顺序遍历,无法直接访问任意位置的元素,用链表实现快排会彻底丧失其时间复杂度优势(从O(nlogn)退化到O(n²)),完全没必要。
动态数组通过malloc/realloc扩容,虽然扩容时有一定内存拷贝开销,但相比链表在排序上的低效,这个代价完全可以接受。而且可以通过设置初始容量、翻倍扩容的方式,把扩容的平均开销降到O(1)。

二、代码中的错误分析(无输出+内存分配问题)

1. malloc与realloc的明显错误

  • 扩容逻辑倒置:当前代码在读取完第num个元素后,把数组扩容到num*sizeof(struct Data)——但此时num已经递增,原来的数组已经有num个元素的空间(比如第一次循环后num=1,扩容到1个元素,等于没扩容)。正确逻辑应该是在读取前确保有足够空间,或者扩容到num+1的大小,为下一次读取预留位置。
  • 未检查内存分配返回值:malloc和realloc都可能返回NULL(内存不足时),直接赋值给records会导致后续操作触发空指针异常,程序崩溃。
  • 硬循环读取5次:不管文件实际有多少行,强制读取5次,若文件行数不足,fscanf会读取失败,导致数组中填充垃圾值,甚至程序崩溃。

2. 无打印输出的可能原因

  • 文件路径或存在性问题:如果records.csv不在程序运行的当前目录,或者文件损坏,fopen会失败,程序直接return 1,不会执行打印逻辑。
  • 格式字符串匹配失败:原代码中fscanf的格式串末尾加了\n,会匹配任意空白字符(包括换行、空格、制表符),如果文件行尾格式不符合,会导致fscanf卡住,循环无法正常结束,自然不会走到打印步骤。
  • 读取失败后未终止循环:硬读5次的逻辑下,若文件数据不足,fscanf失败后仍会继续循环,后续的数组元素未初始化,可能导致打印时程序异常终止。

修正后的代码示例

manager.h(无需修改)

#ifndef MANAGER_H
#define MANAGER_H

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

struct Data
{
    int id;
    char field1[50];
    int field2;
    float field3;
};

extern struct Data* records; 

int readFile();
#endif

manager.c(修正版)

#include "manager.h"

struct Data* records; 

int readFile(){
    FILE *file = fopen("records.csv","r");
    if(file == NULL){
        printf("Error opening file.\n");
        return 1;
    }

    // 初始分配4个元素的容量,减少扩容次数
    size_t capacity = 4;
    records = malloc(capacity * sizeof(struct Data));
    if(records == NULL){
        printf("Malloc failed: out of memory.\n");
        fclose(file);
        return 1;
    }

    int num = 0;
    // 用fscanf返回值判断是否成功读取4个字段,作为循环条件
    while(fscanf(file,"%d,%49[^,],%d,%f", &records[num].id, records[num].field1, &records[num].field2, &records[num].field3) == 4){
        num++;
        // 元素数量达到容量时,翻倍扩容
        if(num >= capacity){
            capacity *= 2;
            struct Data* temp = realloc(records, capacity * sizeof(struct Data));
            if(temp == NULL){
                printf("Realloc failed: out of memory.\n");
                free(records); // 释放已分配内存,避免泄漏
                fclose(file);
                return 1;
            }
            records = temp;
        }
        // 手动跳过行尾的换行符,避免干扰下一次读取
        int c;
        while((c = fgetc(file)) != '\n' && c != EOF);
    }

    fclose(file);

    // 打印所有有效读取的数据
    for (int i = 0; i < num; i++){
        printf("\n%d %s %d %.2f", records[i].id, records[i].field1, records[i].field2, records[i].field3);
    }

    // 可选:缩容到实际元素数量,节省内存
    struct Data* temp = realloc(records, num * sizeof(struct Data));
    if(temp != NULL){
        records = temp;
    }

    return 0;
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.11 00:35:17