用c语言设计一个学生成绩查询统计系统 内容要求:(1)分析数据的逻辑结构。(2)设计数据的存储结构。(诸如一个记录应包括哪些字段数据,每个字段的数据是什么类型的,应用什么数据结构来保存众多的记录)(3)根据学生姓名进行字典排序。(4)根据成绩进行由高到低排序。(可采用冒泡法或其他快速算法)(5)根据学号或姓名查找学生成绩。(可采用顺序查找或二分查找等方法,并实现查找结构的打印)(6)统计各分数段(≥90分、80-89分、70-79分、60-69分、60分以下)的学生人数及其所占比例,并打印统计的结果。(7)编写主要的C语言代码,尤其是对函数头部涉及的主要参数要进行注释说明。(8)系统的程序结构可以考虑采用多文件组合框架,也可以采用单文件多模块组合框架。写出main函数
时间: 2024-03-14 10:49:17 浏览: 332
学生成绩管理系统 数据结构课程设计
以下是一个简单的学生成绩查询统计系统的设计及实现,其中采用了结构体存储学生信息,同时实现了根据姓名和成绩进行排序、查找和统计分数段的功能。请注意,本系统仅作为示例,实际应用中还需要考虑更多的细节和异常情况处理。
1. 数据逻辑结构
每个学生包含以下字段数据:
- 学号(整型)
- 姓名(字符串)
- 英语成绩(整型)
- 数学成绩(整型)
- 物理成绩(整型)
- 总分(整型)
2. 数据存储结构
为了方便排序、查找和统计,我们可以采用结构体数组来存储所有学生的信息。同时,我们可以使用指针数组来实现根据姓名和成绩进行排序的功能。
具体实现如下:
```
#define MAX_STUDENTS 100 // 最大学生数
typedef struct {
int id; // 学号
char name[20]; // 姓名
int english; // 英语成绩
int math; // 数学成绩
int physics; // 物理成绩
int total; // 总分
} student;
student students[MAX_STUDENTS]; // 学生信息数组
student *name_sorted[MAX_STUDENTS]; // 按姓名排序的指针数组
student *score_sorted[MAX_STUDENTS]; // 按成绩排序的指针数组
int student_count = 0; // 学生数
```
3. 根据姓名进行字典排序
我们可以采用快速排序算法来实现根据姓名进行字典排序。具体实现如下:
```
void quick_sort_by_name(student **arr, int left, int right) {
if (left >= right) {
return;
}
int i = left;
int j = right;
student *pivot = arr[left];
while (i < j) {
while (i < j && strcmp(arr[j]->name, pivot->name) >= 0) {
j--;
}
arr[i] = arr[j];
while (i < j && strcmp(arr[i]->name, pivot->name) <= 0) {
i++;
}
arr[j] = arr[i];
}
arr[i] = pivot;
quick_sort_by_name(arr, left, i - 1);
quick_sort_by_name(arr, i + 1, right);
}
void sort_by_name() {
for (int i = 0; i < student_count; i++) {
name_sorted[i] = &students[i];
}
quick_sort_by_name(name_sorted, 0, student_count - 1);
}
```
在上面的代码中,我们定义了一个快速排序算法 `quick_sort_by_name`,它接受一个指向指针数组的指针,以及左右边界。在排序过程中,我们取最左边的元素作为枢轴,然后将数组中所有比枢轴小的元素移到左边,所有比枢轴大的元素移到右边,最后将枢轴放在正确的位置上。然后,我们递归对左右两个子数组进行排序。
在 `sort_by_name` 函数中,我们首先将所有学生的指针存储到 `name_sorted` 数组中,然后调用 `quick_sort_by_name` 函数进行排序。
4. 根据成绩进行由高到低排序
我们可以采用冒泡排序算法来实现根据成绩进行由高到低排序。具体实现如下:
```
void bubble_sort_by_score(student **arr, int n) {
for (int i = 0; i < n - 1; i++) {
for (int j = 0; j < n - i - 1; j++) {
if (arr[j]->total < arr[j + 1]->total) {
student *temp = arr[j];
arr[j] = arr[j + 1];
arr[j + 1] = temp;
}
}
}
}
void sort_by_score() {
for (int i = 0; i < student_count; i++) {
score_sorted[i] = &students[i];
}
bubble_sort_by_score(score_sorted, student_count);
}
```
在上面的代码中,我们定义了一个冒泡排序算法 `bubble_sort_by_score`,它接受一个指向指针数组的指针以及数组长度。在排序过程中,我们从左到右依次比较相邻的两个元素,如果左边的元素比右边的元素大,则交换它们的位置。这样一轮比较下来,最大的元素就会被交换到最右边。重复执行这个过程,直到整个数组都被排序。
在 `sort_by_score` 函数中,我们首先将所有学生的指针存储到 `score_sorted` 数组中,然后调用 `bubble_sort_by_score` 函数进行排序。
5. 根据学号或姓名查找学生成绩
我们可以采用顺序查找或二分查找等方法来实现查找学生成绩的功能。具体实现如下:
```
student *find_by_id(int id) {
for (int i = 0; i < student_count; i++) {
if (students[i].id == id) {
return &students[i];
}
}
return NULL;
}
student *find_by_name(char *name) {
for (int i = 0; i < student_count; i++) {
if (strcmp(students[i].name, name) == 0) {
return &students[i];
}
}
return NULL;
}
void print_student(student *s) {
printf("学号:%d,姓名:%s,英语成绩:%d,数学成绩:%d,物理成绩:%d,总分:%d\n", s->id, s->name, s->english, s->math, s->physics, s->total);
}
void find_student() {
int choice;
printf("请选择查找方式:\n");
printf("1. 根据学号查找\n");
printf("2. 根据姓名查找\n");
scanf("%d", &choice);
if (choice == 1) {
int id;
printf("请输入学号:\n");
scanf("%d", &id);
student *s = find_by_id(id);
if (s == NULL) {
printf("未找到该学生。\n");
} else {
print_student(s);
}
} else if (choice == 2) {
char name[20];
printf("请输入姓名:\n");
scanf("%s", name);
student *s = find_by_name(name);
if (s == NULL) {
printf("未找到该学生。\n");
} else {
print_student(s);
}
} else {
printf("无效的选择。\n");
}
}
```
在上面的代码中,我们实现了两个查找函数 `find_by_id` 和 `find_by_name`,它们分别接受一个参数(学号或姓名),并在学生信息数组中查找相应的学生。如果找到了,则返回该学生的指针;否则返回 NULL。
我们还定义了一个 `print_student` 函数,用于打印学生的详细信息。
最后,我们实现了一个 `find_student` 函数,该函数提示用户选择查找方式(根据学号或姓名),然后根据用户输入进行查找。
6. 统计各分数段的学生人数及其所占比例
我们可以遍历所有学生,根据其总分统计各分数段的学生人数。具体实现如下:
```
void print_stats() {
int count[5] = {0}; // 存储各分数段的学生人数
for (int i = 0; i < student_count; i++) {
if (students[i].total >= 90) {
count[0]++;
} else if (students[i].total >= 80) {
count[1]++;
} else if (students[i].total >= 70) {
count[2]++;
} else if (students[i].total >= 60) {
count[3]++;
} else {
count[4]++;
}
}
printf("总人数:%d,≥90分的学生人数:%d,占比:%.2f%%\n", student_count, count[0], count[0] * 100.0 / student_count);
printf("总人数:%d,80-89分的学生人数:%d,占比:%.2f%%\n", student_count, count[1], count[1] * 100.0 / student_count);
printf("总人数:%d,70-79分的学生人数:%d,占比:%.2f%%\n", student_count, count[2], count[2] * 100.0 / student_count);
printf("总人数:%d,60-69分的学生人数:%d,占比:%.2f%%\n", student_count, count[3], count[3] * 100.0 / student_count);
printf("总人数:%d,60分以下的学生人数:%d,占比:%.2f%%\n", student_count, count[4], count[4] * 100.0 / student_count);
}
```
在上面的代码中,我们定义了一个 `count` 数组,用于存储各分数段的学生人数。然后,我们遍历所有学生,根据其总分将其计入相应的分数段。最后,我们使用 printf 函数打印统计结果。
7. 主函数
最后,我们定义了一个主函数,该函数实现了以下功能:
- 显示菜单,让用户选择操作
- 根据用户选择调用相应的函数
具体实现如下:
```
void display_menu() {
printf("请选择操作:\n");
printf("1. 添加学生信息\n");
printf("2. 根据姓名排序\n");
printf("3. 根据成绩排序\n");
printf("4. 查找学生成绩\n");
printf("5. 统计各分数段的学生人数\n");
printf("0. 退出程序\n");
}
void add_student() {
if (student_count >= MAX_STUDENTS) {
printf("学生信息已满,无法添加新学生。\n");
return;
}
student s;
printf("请输入学号:\n");
scanf("%d", &s.id);
printf("请输入姓名:\n");
scanf("%s", s.name);
printf("请输入英语成绩:\n");
scanf("%d", &s.english);
printf("请输入数学成绩:\n");
scanf("%d", &s.math);
printf("请输入物理成绩:\n");
scanf("%d", &s.physics);
s.total = s.english + s.math + s.physics;
students[student_count++] = s;
printf("学生信息添加成功。\n");
}
int main() {
int choice;
while (1) {
display_menu();
scanf("%d", &choice);
switch (choice) {
case 0:
printf("程序已退出。\n");
return 0;
case 1:
add_student();
break;
case 2:
sort_by_name();
printf("按姓名排序完成。\n");
break;
case 3:
sort_by_score();
printf("按成绩排序完成。\n");
break;
case 4:
find_student();
break;
case 5:
print_stats();
break;
default:
printf("无效的选择。\n");
break;
}
}
}
```
在上面的代码中,我们首先定义了一个 `display_menu` 函数,用于打印菜单。然后,我们在主函数中使用一个无限循环,让用户不断选择操作。根据用户选择,我们调用相应的函数,最后返回菜单。
注:以上代码仅供参考,实际使用中应根据具体需求进行修改和完善。
阅读全文