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

C语言结构体实现学生信息存文件:首行输出异常求助

问题:C语言学生信息写入文件首行异常排查与解决

问题概述

编写了一段C语言代码,通过结构体存储学生信息并写入文件,功能是接收学生列表并保存,但生成的文件首行内容显示异常。

原代码

#include <stdio.h>
#include <comip.h>

#define MAX_STR_LEN 80

int main() {
    //creating file
    FILE *students_file;
    students_file = fopen("students_file.txt", "w");
    int students_num;
    puts("How many students do you have ? : ");
    scanf("%d", &students_num);
    struct students
    {
        char first_name[MAX_STR_LEN];
        char last_name[MAX_STR_LEN];
        char id[12];
        float average;
    };

    struct students *students = calloc(students_num, sizeof *students);

    fprintf(students_file, "number     id       firstname       lastname        average\n");
    for (int i = 1; i <= students_num; i++)
    {
        printf("Please enter student #%d first name : ", i);
        scanf("%79s", students[i].first_name);
        printf("Please enter student #%d last name : ", i);
        scanf("%79s", students[i].last_name);
        printf("Please enter student #%d id : ", i);
        scanf("%79s", students[i].id);
        printf("Please enter student #%d average : ", i);
        scanf("%f", &students[i].average);
        fprintf(students_file, "#%d.\t %s\t %s\t %s\t %f\n", i, students[i].id,  students[i].first_name, students[i].last_name, students[i].average);
    }
    fclose(students_file);

    return 0;
}

输入数据

> How many students do you have ? :
3
Please enter student #1 first name : mani
Please enter student #1 last name : aghaie
Please enter student #1 id : 1383ma
Please enter student #1 average : 19.72
Please enter student #2 first name : arash
Please enter student #2 last name : hamidi
Please enter student #2 id : 1384ah
Please enter student #2 average : 14.27
Please enter student #3 first name : pourya
Please enter student #3 last name : ghorbani
Please enter student #3 id : 1382pg
Please enter student #3 average : 16.52

异常现象

生成的文件首行出现乱码/异常字符,格式错乱。

问题排查

  1. 头文件错误:引入了无关的<comip.h>(Windows COM组件头文件),但未包含calloc所需的<stdlib.h>,导致calloc函数声明缺失,返回值被错误解析,可能造成内存分配异常。
  2. 数组下标越界:C语言数组下标从0开始,calloc分配了students_num个元素的数组,有效下标范围是0到students_num-1,但循环中使用i从1到students_num访问students[i],属于越界访问,触发未定义行为,会破坏内存中的数据(包括文件流的内部状态),进而导致文件首行写入异常。
  3. 未检查资源分配结果:未检查fopen和calloc的返回值,若文件打开失败或内存分配失败,会导致后续操作出错。

解决方案

  1. 替换头文件:移除<comip.h>,添加<stdlib.h>以正确使用calloc。
  2. 修正数组下标:将循环调整为从0开始,或访问时使用i-1作为下标,确保在有效范围内访问数组元素。
  3. 添加错误检查:检查fopen和calloc的返回值,避免空指针操作。

修正后的代码

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

#define MAX_STR_LEN 80

int main() {
    FILE *students_file = fopen("students_file.txt", "w");
    if (!students_file) {
        perror("Failed to open file");
        return 1;
    }

    int students_num;
    puts("How many students do you have ? : ");
    if (scanf("%d", &students_num) != 1 || students_num <= 0) {
        puts("Invalid number of students");
        fclose(students_file);
        return 1;
    }

    typedef struct {
        char first_name[MAX_STR_LEN];
        char last_name[MAX_STR_LEN];
        char id[12];
        float average;
    } Student;

    Student *students = calloc(students_num, sizeof(Student));
    if (!students) {
        perror("Failed to allocate memory");
        fclose(students_file);
        return 1;
    }

    fprintf(students_file, "number     id       firstname       lastname        average\n");
    for (int i = 0; i < students_num; i++) {
        printf("Please enter student #%d first name : ", i+1);
        scanf("%79s", students[i].first_name);
        printf("Please enter student #%d last name : ", i+1);
        scanf("%79s", students[i].last_name);
        printf("Please enter student #%d id : ", i+1);
        scanf("%11s", students[i].id); // 限制输入长度避免id数组越界
        printf("Please enter student #%d average : ", i+1);
        scanf("%f", &students[i].average);
        fprintf(students_file, "#%d.\t %s\t %s\t %s\t %.2f\n", i+1, students[i].id, students[i].first_name, students[i].last_name, students[i].average);
    }

    free(students);
    fclose(students_file);

    return 0;
}

额外优化:限制id的输入长度为11(因为id数组长度是12,留一个位置存字符串结束符),输出浮点数时保留两位小数更美观,添加了内存释放操作避免内存泄漏。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.11 06:15:02