📃 基于C语言的学生试卷分数统计程序设计及实现
🧈 前言
最近有个朋友找我帮做C语言作业,话不多说,直接上代码,一定注意看清要求是否差不多。
🥪 程序要求
-
程序运行时,首先必须接收总评成绩的计算比例,针对该课程,平时成绩和期末考试成绩所占的比例分别为20%和80%。
-
接收若干同学的平时成绩和期末考试成绩,计算出总评成绩。
-
输出所有学号、平时成绩、期末卷面成绩和总评成绩,输出各分数段的分数分布情况。
-
画出各分数段的直方图。
-
计算平时成绩、期末成绩和总评成绩的平均分和标准差,以及期末考试卷面的及格率、最高分和最低分等。
这个作业是给了部分程序代码的,我看了下,实现的时候就避免使用实例代码额外的方法,就类似于只使用结构体数组存储这种。注释得也比较清楚,就不分析了。
🍤 代码
#include "stdio.h"
#include "string.h"
#include "conio.h"
#include "math.h"
#define FLT_MIN 1.175494351e-38F
#define FLT_MAX 3.402823466e+38F
#define MAX_NUM 34 // 最大学生人数
typedef struct student
{
int number; // 学号
float score[3]; // 平时、期末、总评成绩
} STUDENT;
int accept_data(STUDENT stu[], int grade_count[], int stu_count); // 学生数据输入 + 成绩计算 + 数据存储
void show_stu_data(STUDENT stu[], int grade_count[], int stu_count); // 所有学生信息显示
void draw(int grade_count[], int grade_count_length, int stu_count); // 直方图绘制
void caculate(float *score_min, float *score_max, float *pass, float ave[], float f[], STUDENT stu[], int stu_count); // 及格率 & 平均分 & 标准差计算
void show_data(float score_min, float score_max, float pass, float ave[], float f[]); // 平时成绩、期末成绩、总评成绩平均值&标准差显示
int accept_data(STUDENT stu[], int grade_count[], int stu_count = 0)
/*
学生数据输入 + 成绩计算 + 数据存储
:param stu[]: 学生结构体数组
:param grade_count[]: 学生总评成绩分布数组
:param stu_count: 当前学生总数, 默认为0
:return stu_count: 当前学生总数
*/
{
int a1, a2;
printf("\n请输入计算总评成绩时使用平时成绩与期末成绩的比例, 用整数表示: ");
scanf("%d%d", &a1, &a2);
while (stu_count < MAX_NUM)
{
printf("请输入学号:");
scanf("%d", &stu[stu_count].number);
if (stu[stu_count].number == -1) // 序号—1跳出循环
{
return stu_count;
}
printf("请输入学生的平时成绩和期末成绩:");
bool flag = true;
while (flag)
{ // 重复读入两个数,正确为止
scanf("%f%f", &stu[stu_count].score[0], &stu[stu_count].score[1]);
if (stu[stu_count].score[0] <= 100 && stu[stu_count].score[0] >= 0 &&
stu[stu_count].score[1] <= 100 && stu[stu_count].score[1] >= 0)
flag = false; // 输入数据合理
else
printf("\n错误数据, 请再次输入学生的平时成绩和期末成绩:");
}
stu[stu_count].score[2] = 1.0 * a1 / 100 * stu[stu_count].score[0] + 1.0 * a2 / 100 * stu[stu_count].score[1];
// 学生分布计数
int temp = int(stu[stu_count].score[2] / 10);
grade_count[temp]++;
stu_count++;
}
return stu_count;
}
void show_stu_data(STUDENT stu[], int grade_count[], int stu_count)
/*
输出所有学生信息
:param stu[]: 学生结构体数组
:param grade_count[]: 学生总评成绩分布数组
:param stu_count: 当前学生总数
:return stu_count: 当前学生总数
*/
{
printf("\n-------------学生成绩信息-------------\n");
for (int i = 0; i < stu_count; i++)
{
printf("%4d ", stu[i].number);
for (int j = 0; j < 3; j++)
printf("%4.2f ", stu[i].score[j]);
printf("\n");
}
printf("\n-----------------成绩分布状况-----------------\n");
for (int i = 0; i < 10; i++)
{
printf("%d ", grade_count[i]);
}
printf("\n");
}
void draw(int grade_count[], int grade_count_length, int stu_count)
/*
直方图绘制
:param grade_count[]: 学生总评成绩分布数组
:param grade_count_length: 分数段类型数
:return: null
*/
{
int i, j;
const int width_length = 4; // x 段长
const int high_length = 2; // y 段长
const int width = 44; // x 长度
const int high = 22; // y 长度
char screen[high + high_length][width + width_length]; // 画布 包含标记
// 画布初始化
for (i = 0; i < high + high_length; i++)
{
for (j = 0; j < width + width_length; j++)
{
screen[i][j] = 0;
}
}
// 画布数据标准化
printf("\n-------------------模拟直方图-----------------\n");
for (i = 0; i < grade_count_length; i++)
{
grade_count[i] = (int)(float(high) * grade_count[i] / stu_count);
}
// X&Y轴
for (i = 0; i < width; i++)
{
screen[high + high_length - 1][i] = '-';
}
for (i = 1; i < high + high_length; i++)
{
screen[i][0] = '|';
}
screen[high + high_length - 1][width + width_length - 1] = 'X';
screen[0][0] = 'Y';
screen[1][0] = '^';
screen[high + high_length - 1][width] = '>';
// 柱形
for (i = 0; i < grade_count_length; i++)
{
for (j = grade_count[i]; j > 0; j--)
{
screen[high + high_length - j - 1][(i + 1) * 4] = '*';
}
}
// 绘图
for (i = 0; i < high + high_length; i++)
{
for (j = 0; j < width + width_length; j++)
if (screen[i][j] != 0)
printf("%c", screen[i][j]);
else
printf(" ");
printf("\n");
}
printf(" 0 10 20 30 40 50 60 70 80 90 100\n");
}
void caculate(float *score_min, float *score_max, float *pass, float ave[], float f[], STUDENT stu[], int stu_count)
/*
及格率 & 平均分 & 标准差计算
:param *score_min: 卷面成绩最低分
:param *score_max: 卷面成绩最高分
:param *pass: 及格率
:param ave[]: 平时成绩、期末成绩和总评成绩 平均分
:param f[]: 平时成绩、期末成绩和总评成绩 标准差
:param stu[]: 学生结构体数组
:param stu_count: 当前学生总数
:return: null
*/
{
for (int i = 0; i < stu_count; i++)
{
if ((stu[i].score[1]) > *score_max) // 若高于最高分,更新最高分
*score_max = stu[i].score[1];
if ((stu[i].score[1]) < *score_min) // 若低于最低分,更新最低分
*score_min = stu[i].score[1];
if (stu[i].score[1] >= 60)
(*pass)++;
}
*pass = (*pass) / stu_count * 100.0; // 及格率
for (int i = 0; i < 3; i++) // 平均分
{
float sum = 0;
for (int j = 0; j < stu_count; j++)
{
sum += stu[j].score[i];
}
ave[i] = sum / stu_count;
}
for (int i = 0; i < 3; i++) // 标准差
{
double sum = 0;
for (int j = 0; j < stu_count; j++)
{
sum += pow(double(stu[j].score[i] - ave[0]), 2.0);
}
f[i] = float(sqrt(sum / stu_count));
}
}
void show_data(float score_min, float score_max, float pass, float ave[], float f[])
/*
平时成绩、期末成绩、总评成绩平均值&标准差显示
:param score_min: 卷面成绩最低分
:param score_max: 卷面成绩最高分
:param pass: 及格率
:param ave[]: 平时成绩、期末成绩和总评成绩 平均分
:param f[]: 平时成绩、期末成绩和总评成绩 标准差
:return: null
*/
{
char str1[3][22] = {"平时成绩平均分", "期末成绩平均分", "总评成绩平均分"};
char str2[3][22] = {"平时成绩标准差", "期末成绩标准差", "总评成绩标准差"};
printf("\n及格率=%6.2f 最低分=%6.2f 最高分=%6.2f\n", pass, score_min, score_max);
for (int j = 0; j < 3; j++)
printf("\n%s = %6.2f %s = %6.2f\n", str1[j], ave[j], str2[j], f[j]);
}
int main()
{
int stu_count = 0; // 当前学生人数
int grade_count_length = 11; // 分数段类型数
int grade_count[11] = {0}; // 总评成绩分布
float score_min = FLT_MAX; // 卷面成绩最小值
float score_max = FLT_MIN; // 卷面成绩最大值
float pass = 0.0; // 及格率
float ave[3] = {0.0}; // 平时成绩、期末成绩和总评成绩 平均值
float f[3] = {0.0}; // 平时成绩、期末成绩和总评成绩 标准差
STUDENT stu[MAX_NUM];
stu_count = accept_data(stu, grade_count, stu_count); // 学生信息输入
show_stu_data(stu, grade_count, stu_count); // 学生信息显示
draw(grade_count, grade_count_length, stu_count); // 成绩分布直方图绘制
caculate(&score_min, &score_max, &pass, ave, f, stu, stu_count); // 所有成绩及格率、最高分、最低分计算
show_data(score_min, score_max, pass, ave, f); // 期末成绩的最高分、最低分以及平时期末和总评成绩的平均分和标准差显示
return 0;
}
🍡 测试结果
🥯 题外话
最近不是chatGPT比较火吗,我就把要求拿上去试了一下,给出的结果基本一致,以下是它给出的结果。
-
chatGPT给的代码
#include <stdio.h> #include <stdlib.h> #include <math.h> #define NUM_STUDENTS 3 // 定义学生数量 #define SCORE_LEVELS 10 // 定义分数段数量 typedef struct student { // 定义学生结构体 char id[10]; // 学号 float score_regular; // 平时成绩 float score_final; // 期末成绩 float score_total; // 总评成绩 } Student; // 函数声明 void get_proportions(float *regular_proportion, float *final_proportion); // 获取成绩计算比例 void input_scores(Student *students); // 输入学生成绩 void calculate_total_scores(Student *students, float regular_proportion, float final_proportion); // 计算学生总评成绩 void print_students(Student *students); // 输出学生成绩 void print_score_distribution(Student *students); // 输出分数分布情况 void draw_histogram(Student *students); // 画出各分数段的直方图 void calculate_statistics(Student *students); // 计算各种统计信息 int main(void) { float regular_proportion, final_proportion; // 定义平时成绩和期末成绩所占比例 // 获取成绩计算比例 get_proportions(®ular_proportion, &final_proportion); Student students[NUM_STUDENTS]; // 定义学生数组 // 输入学生成绩 input_scores(students); // 计算学生总评成绩 calculate_total_scores(students, regular_proportion, final_proportion); // 输出学生成绩 print_students(students); // 输出分数分布情况 print_score_distribution(students); // 画出各分数段的直方图 draw_histogram(students); // 计算各种统计信息 calculate_statistics(students); return 0; } // 获取成绩计算比例 void get_proportions(float *regular_proportion, float *final_proportion) { // 平时成绩所占比例为20% *regular_proportion = 0.2; // 期末成绩所占比例为80% *final_proportion = 0.8; } // 输入学生成绩 void input_scores(Student *students) { for (int i = 0; i < NUM_STUDENTS; i++) { printf("请输入第%d个学生的学号、平时成绩和期末成绩:\n", i + 1); scanf("%s%f%f", students[i].id, &students[i].score_regular, &students[i].score_final); } } // 计算学生总评成绩 void calculate_total_scores(Student *students, float regular_proportion, float final_proportion) { for (int i = 0; i < NUM_STUDENTS; i++) { // 总评成绩 = 平时成绩 * 平时成绩所占比例 + 期末成绩 * 期末成绩所占比例 students[i].score_total = students[i].score_regular * regular_proportion + students[i].score_final * final_proportion; } } // 输出学生成绩 void print_students(Student *students) { printf("学号\t平时成绩\t期末卷面成绩\t总评成绩\n"); for (int i = 0; i < NUM_STUDENTS; i++) { printf("%s\t%.1f\t\t%.1f\t\t%.1f\n", students[i].id, students[i].score_regular, students[i].score_final, students[i].score_total); } } // 输出分数分布情况 void print_score_distribution(Student *students) { int distribution[SCORE_LEVELS] = {0}; // 定义分数分布数组,并将所有元素初始化为0 // 统计分数分布 for (int i = 0; i < NUM_STUDENTS; i++) { int score = (int)students[i].score_total / 10; // 计算分数所属的分数段 distribution[score]++; // 将对应分数段的值加1 } printf("分数段\t人数\n"); for (int i = 0; i < SCORE_LEVELS; i++) { printf("%d-%d\t%d\n", i * 10, i * 10 + 9, distribution[i]); } } // 画出各分数段的直方图 void draw_histogram(Student *students) { int distribution[SCORE_LEVELS] = {0}; // 定义分数分布数组,并将所有元素初始化为0 // 统计分数分布 for (int i = 0; i < NUM_STUDENTS; i++) { int score = (int)students[i].score_total / 10; // 计算分数所属的分数段 distribution[score]++; // 将对应分数段的值加1 } // 画出直方图 for (int i = 0; i < SCORE_LEVELS; i++) { printf("%d-%d: ", i * 10, i * 10 + 9); for (int j = 0; j < distribution[i]; j++) { putchar('*'); } putchar('\n'); } } // 计算各种统计信息 void calculate_statistics(Student *students) { float sum_regular = 0, sum_final = 0, sum_total = 0; // 定义平时成绩、期末成绩和总评成绩的总和 float square_sum_regular = 0, square_sum_final = 0, square_sum_total = 0; // 定义平时成绩、期末成绩和总评成绩的平方和 float pass_count = 0; // 定义及格人数 float max_regular = 0, max_final = 0, max_total = 0; // 定义平时成绩、期末成绩和总评成绩的最大值 float min_regular = 100, min_final = 100, min_total = 100; // 定义平时成绩、期末成绩和总评成绩的最小值 for (int i = 0; i < NUM_STUDENTS; i++) { // 统计平时成绩、期末成绩和总评成绩的总和和平方和 sum_regular += students[i].score_regular; square_sum_regular += students[i].score_regular * students[i].score_regular; sum_final += students[i].score_final; square_sum_final += students[i].score_final * students[i].score_final; sum_total += students[i].score_total; square_sum_total += students[i].score_total * students[i].score_total; // 统计及格人数 if (students[i].score_final >= 60) { pass_count++; } // 更新平时成绩、期末成绩和总评成绩的最大值 if (students[i].score_regular > max_regular) { max_regular = students[i].score_regular; } if (students[i].score_final > max_final) { max_final = students[i].score_final; } if (students[i].score_total > max_total) { max_total = students[i].score_total; } // 更新平时成绩、期末成绩和总评成绩的最小值 if (students[i].score_regular < min_regular) { min_regular = students[i].score_regular; } if (students[i].score_final < min_final) { min_final = students[i].score_final; } if (students[i].score_total < min_total) { min_total = students[i].score_total; } } // 计算平时成绩、期末成绩和总评成绩的平均分 float average_regular = sum_regular / NUM_STUDENTS; float average_final = sum_final / NUM_STUDENTS; float average_total = sum_total / NUM_STUDENTS; // 计算平时成绩、期末成绩和总评成绩的标准差 float std_dev_regular = sqrt((square_sum_regular - sum_regular * sum_regular / NUM_STUDENTS) / (NUM_STUDENTS - 1)); float std_dev_final = sqrt((square_sum_final - sum_final * sum_final / NUM_STUDENTS) / (NUM_STUDENTS - 1)); float std_dev_total = sqrt((square_sum_total - sum_total * sum_total / NUM_STUDENTS) / (NUM_STUDENTS - 1)); // 计算期末考试卷面的及格率 float pass_rate = pass_count / NUM_STUDENTS; // 输出统计信息 printf("平时成绩的平均分:%.1f\n", average_regular); printf("平时成绩的标准差:%.1f\n", std_dev_regular); printf("平时成绩的最大值:%.1f\n", max_regular); printf("平时成绩的最小值:%.1f\n", min_regular); printf("期末成绩的平均分:%.1f\n", average_final); printf("期末成绩的标准差:%.1f\n", std_dev_final); printf("期末成绩的最大值:%.1f\n", max_final); printf("期末成绩的最小值:%.1f\n", min_final); printf("总评成绩的平均分:%.1f\n", average_total); printf("总评成绩的标准差:%.1f\n", std_dev_total); printf("总评成绩的最大值:%.1f\n", max_total); printf("总评成绩的最小值:%.1f\n", min_total); printf("期末考试卷面的及格率:%.1f%%\n", pass_rate * 100); }
-
运行结果
-
个人评价
从结果来看,chatGPT效果确实很惊人,注释也很清楚,好多基础内容都可以交给它做,嘿嘿~~ 不过不知道后续还会持续免费试用不。