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

C语言动态分配字符串数组实现学生成绩统计代码故障求助

C语言动态数组存储学生信息与平均分计算问题排查与修正

原代码核心错误分析

  • 字符串数组分配错误:要存储no个学生姓名(每个是字符串),需要char**类型的二维指针,而非char*。原代码char* g = (char*)malloc(no* sizeof(char));仅分配了no个字符的空间,无法存储多个字符串。
  • 逗号表达式滥用:while (n != no , n++)这类写法中,逗号表达式的结果是右侧值,导致循环条件失效,实际会变成无限循环(直到n溢出)。正确的循环条件应使用n < no,或改用for循环更直观。
  • 姓名读取错误:
    • 单个姓名内存分配错误:g[n] = malloc(no* sizeof(char));按学生数量分配内存完全不合理,应按姓名最大长度(比如256字节)分配。
    • 读取格式错误:scanf_s("%c", &g[n]);用%c只能读取单个字符,无法读取完整姓名,且未处理输入缓冲区的换行符,会导致读取异常。
  • 成绩数组逻辑混乱:
    • 类型不匹配:char* w = (double*)malloc(p * sizeof(double));将double*强制转为char*,后续访问会触发类型错误。
    • 无意义的重复分配:循环内w[n] = malloc(p * sizeof(char));完全错误,w是成绩数组(double*),不需要给每个元素再分配内存,且n是学生索引,此时访问w[n]会触发越界。
  • 循环变量未重置:i、op等循环变量在处理新学生时未重置为0,导致后续循环无法执行。
  • 平均分计算与输出错误:
    • 计算逻辑错误:b = w[op] / n;没有累加成绩,直接用单个成绩除以学生数量,完全不符合平均分计算逻辑。
    • 输出错误:printf(" e %f\n", & b);传递了b的地址而非值,会输出错误内容。

修正后的完整代码

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

#define NAME_MAX_LEN 256  // 定义姓名最大长度

typedef struct {
    char* name;
    double* grades;
    int grade_count;
    double average;
} Student;  // 用结构体统一存储学生信息,逻辑更清晰

int main()
{
    int student_count = 0;
    printf("请输入学生数量:\n");
    scanf_s("%d", &student_count);
    
    // 分配学生结构体数组
    Student* students = malloc(student_count * sizeof(Student));
    if (students == NULL) {
        printf("内存分配失败!\n");
        return 1;
    }

    // 逐个输入学生信息
    for (int i = 0; i < student_count; i++) {
        // 分配姓名内存
        students[i].name = malloc(NAME_MAX_LEN * sizeof(char));
        if (students[i].name == NULL) {
            printf("姓名内存分配失败!\n");
            return 1;
        }
        
        printf("请输入第%d个学生的姓名:", i+1);
        // 清除scanf_s留下的换行符,避免读取空字符串
        getchar();
        fgets(students[i].name, NAME_MAX_LEN, stdin);
        // 去掉fgets读取的换行符
        students[i].name[strcspn(students[i].name, "\n")] = '\0';

        // 输入该学生的科目数量
        printf("请输入该学生的成绩数量:\n");
        scanf_s("%d", &students[i].grade_count);
        
        // 分配成绩数组内存
        students[i].grades = malloc(students[i].grade_count * sizeof(double));
        if (students[i].grades == NULL) {
            printf("成绩内存分配失败!\n");
            return 1;
        }

        // 输入成绩并计算平均分
        double total = 0.0;
        for (int j = 0; j < students[i].grade_count; j++) {
            printf("请输入第%d门成绩:", j+1);
            scanf_s("%lf", &students[i].grades[j]);
            total += students[i].grades[j];
        }
        students[i].average = total / students[i].grade_count;
    }

    // 输出所有学生的平均分
    printf("\n===== 学生平均分结果 =====\n");
    for (int i = 0; i < student_count; i++) {
        printf("学生%s的平均分:%.2lf\n", students[i].name, students[i].average);
    }

    // 释放内存,避免泄漏
    for (int i = 0; i < student_count; i++) {
        free(students[i].name);
        free(students[i].grades);
    }
    free(students);

    return 0;
}

关键知识点说明

  • 动态字符串数组:存储多个字符串需要char**(或结构体中的char*数组),每个元素单独分配内存,确保能存储完整字符串。
  • 输入处理:使用fgets读取姓名可以避免scanf跳过空格的问题,同时要处理输入缓冲区的换行符;读取double类型浮点数时,对应格式符是%lf。
  • 结构体的使用:用结构体封装学生的姓名、成绩数组、成绩数量和平均分,代码逻辑更清晰,便于维护。
  • 内存管理:所有动态分配的内存(姓名、成绩数组、学生数组)都要记得释放,避免内存泄漏。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.10 11:05:22