#include <stdio.h>
#include <stdlib.h>
#include<string.h>
typedef struct student {
int xuehao;
char name[30];
char zhuanye[30];
int Class;
char sex[6];
float ZGPA;
float KGPA;
} Student;
typedef struct keyanjingsai{
char name[50];
}Keyan;
typedef struct course {
int daihao;
char name[30];
float GPA;
float xuefen;
float chengji;
} Course;
typedef struct Lcourse {
struct course data;
struct Lcourse *next;
} CourseListNode;
typedef struct Lkeyan{
struct keyanjingsai data;
struct Lkeyan *next;
}KeyanListNode;
typedef struct Lstudent {
struct student data;
struct Lcourse *chead;
struct Lkeyan *khead;
struct Lstudent *next;
}StudentListNode;
Student stinputdata(Student StudentNode)
{
printf("请依次输入以下信息:姓名,学号,专业,班级,性别(男,女)\n");
scanf("%s %d %s %d %s",StudentNode.name,&StudentNode.xuehao,StudentNode.zhuanye,&StudentNode.Class,StudentNode.sex);
return StudentNode;
}
//输入课程编号,课程名称,课程学分,课程成绩
Course coinputdata(Course CourseNode)
{
while (1) {
printf("请依次输入以下信息:课程编号,课程名称,课程学分,课程成绩(如果输入信息有误,将课程成绩输入小于0或者大于100即可重新输入)\n");
scanf("%d %s %f %f",&CourseNode.daihao,CourseNode.name,&CourseNode.xuefen,&CourseNode.chengji);
if (CourseNode.chengji >= 0 && CourseNode.chengji <= 100) {
break; // 成绩满足条件,跳出循环
} else {
printf("输入的成绩无效,请确保成绩在0-100范围内!\n");
}
}
float a=0;
a = CourseNode.chengji;
if (a < 60) {CourseNode.GPA = 0; }
else if (a >= 90) { CourseNode.GPA = 4.0; }
else if (a<64&&a >= 60) { CourseNode.GPA = 1.0; }
else if (a < 67&&a>=64) { CourseNode.GPA = 1.3; }
else if (a < 70 && a >= 67) { CourseNode.GPA = 1.7; }
else if (a < 74 && a >= 70) { CourseNode.GPA = 2.0; }
else if (a < 77 && a >= 74) { CourseNode.GPA = 2.3; }
else if (a < 80 && a >= 77) { CourseNode.GPA = 2.7; }
else if (a < 84 && a >= 80) { CourseNode.GPA = 3.0; }
else if (a < 87 && a >= 84) { CourseNode.GPA = 3.3; }
else if (a < 90 && a >= 87) { CourseNode.GPA = 3.7; }
return CourseNode;
}
Keyan putdata(Keyan Keyannode){
printf("请输入科研竞赛获奖信息\n");
scanf("%s",&Keyannode.name);
return Keyannode;
}
struct Lstudent* initStudentList() {
return NULL;
}
struct Lstudent* addStudentToList(struct Lstudent* head) {
Student newStudent;
struct Lstudent* newNode = (struct Lstudent*)malloc(sizeof(struct Lstudent));
if (!newNode) {
printf("内存分配失败!\n");
return head;
}
newStudent = stinputdata(newStudent);
// 检查学号是否已存在
struct Lstudent* currStudent = head;
while (currStudent != NULL) {
if (currStudent->data.xuehao == newStudent.xuehao) {
printf("学号 %d 已存在,不能重复添加,请重新输入!\n", newStudent.xuehao);
free(newNode); // 释放新分配的内存
return head;
}
currStudent = currStudent->next;
}
newNode->khead=NULL;
newNode->chead=NULL;
newNode->data = newStudent;
newNode->next = head;
return newNode;
}
void printStudentList(struct Lstudent* head) {
while (head != NULL) {
printf("姓名:%s,学号:%d,班级:%d,性别:%s,课程平均绩点:%.2f, 总平均成绩:%.2f\n",
head->data.name,
head->data.xuehao,
head->data.Class,
head->data.sex,
head->data.KGPA,
head->data.ZGPA);
head = head->next;
}
}
CourseListNode* addCourseToListForStudent(CourseListNode** chead) {
// 调用输入函数获取课程信息
Course newCourse = coinputdata((Course){});
// 创建新节点并分配内存
CourseListNode* newNode = (CourseListNode*)malloc(sizeof(CourseListNode));
if (!newNode) {
printf("内存分配失败!\n");
return *chead;
}
// 将获取的课程信息赋值给新节点
newNode->data = newCourse;
newNode->next = *chead;
*chead = newNode;
return newNode;
}
KeyanListNode* addKeyan(KeyanListNode** khead){
Keyan newKeyan = putdata((Keyan){});
KeyanListNode* newNode = (KeyanListNode*)malloc(sizeof(KeyanListNode));
if (!newNode) {
printf("内存分配失败!\n");
return *khead;
}
newNode->data = newKeyan;
newNode->next = *khead;
*khead = newNode;
return newNode;
}
void printStudentCourses(CourseListNode* chead) {
CourseListNode* current = chead;
if(current==NULL){
printf("无课程信息\n");
}
while (current != NULL) {
printf("课程编号:%d,课程名称:%s,课程学分:%.1f,课程成绩:%.1f,课程绩点:%.1f\n",
current->data.daihao, current->data.name, current->data.xuefen, current->data.chengji,current->data.GPA);
current = current->next;
}
}
void printStudentKeyan(KeyanListNode* khead) {
KeyanListNode* current = khead;
if(current==NULL){
printf("无科研竞赛信息\n");
}
while (current != NULL) {
printf("科研竞赛获奖信息:%s,\n",
current->data.name);
current = current->next;
}
}
struct Lstudent* findStudentByXuehao(struct Lstudent* studentsHead, int targetXuehao) {
struct Lstudent* currStudent = studentsHead;
while (currStudent != NULL) {
if (currStudent->data.xuehao == targetXuehao) {
return currStudent; // 找到匹配的学生节点,返回其指针
}
currStudent = currStudent->next;
}
return NULL; // 如果没有找到匹配的学生,则返回NULL
}
struct Lstudent* findStudentByName(struct Lstudent* studentsHead, const char* targetName) {
struct Lstudent* currStudent = studentsHead;
while (currStudent != NULL) {
if (strcmp(currStudent->data.name, targetName) == 0) { // 按照姓名进行比较
return currStudent; // 找到匹配的学生节点,返回其指针
}
currStudent = currStudent->next;
}
return NULL; // 如果没有找到匹配的学生,则返回NULL
}
void save(struct Lstudent* head, const char* filename) {
FILE* fp = fopen(filename, "ab");
if (fp == NULL) {
printf("无法打开文件进行写入!\n");
return;
}
while (head != NULL) {
// 写入学生信息
fprintf(fp,"s");
fprintf(fp, " %d %s %s %d %s %.2f %.2f\n",
head->data.xuehao, head->data.name,head->data.zhuanye,head->data.Class, head->data.sex,
head->data.ZGPA, head->data.KGPA);
// 写入课程信息
CourseListNode* courseNode = head->chead;
KeyanListNode* keyanNode = head->khead;
while (courseNode != NULL) {
fprintf(fp,"c");
fprintf(fp, " %d %s %.1f %.1f %.1f\n",
courseNode->data.daihao, courseNode->data.name,
courseNode->data.xuefen, courseNode->data.chengji,courseNode->data.GPA);
courseNode = courseNode->next;
}
while (keyanNode != NULL) {
fprintf(fp,"k");
fprintf(fp, " %s\n",
keyanNode->data.name);
keyanNode = keyanNode->next;
}
head = head->next;
}
int result = fclose(fp);
if (result != 0) {
perror("fclose failed");
} else {
printf("文件写入成功并关闭\n");
}
}
void load(struct Lstudent** head, const char* filename) {
*head = NULL; // 如果没读到任何数据需要返回空链表
FILE* fp = fopen(filename, "r");
if (fp == NULL) {
printf("无法打开文件进行读取!\n");return;
}
// 临时存储学生信息
Student tempStudent;
CourseListNode* tempCourseNode = NULL;
KeyanListNode* tempKeyanNode = NULL;
struct Lstudent* currentStudent = NULL;
struct Lstudent* prevStudent = NULL;
while (1) {
/* 把你的文件格式改成空格分隔,每行开头用一个字符标记是学生还是课程
* 为什么非要把简单的问题复杂化,给自己增加解析难度呢
* S 33 yu 15 男 0.00 0.00
C 3 英语 4.00 150.00
C 2 数学 3.00 140.00
C 1 语文 2.00 120.00
S 123 he 15 男 0.00 0.00
...
*/
char scmark;
fscanf(fp, " %c", &scmark);
if (scmark == 's') {
// 学生
int readCount = fscanf(fp, "%d%s%s%d%s%f%f",
&tempStudent.xuehao, tempStudent.name,tempStudent.zhuanye, &tempStudent.Class, tempStudent.sex,
&tempStudent.ZGPA, &tempStudent.KGPA);
// 抵达文件尾或无效数据
if (readCount != 7)
break;
// 创建新的学生节点
currentStudent = (struct Lstudent*) malloc(sizeof(struct Lstudent));
if (currentStudent == NULL) {
printf("内存分配失败!\n");
break;
}
currentStudent->data = tempStudent;
currentStudent->chead = NULL;
currentStudent->khead=NULL;
currentStudent->next = NULL;
// 如果这不是第一个学生节点,将其链接到链表末尾
if (prevStudent != NULL) {
prevStudent->next = currentStudent;
} else { // 第一个学生节点,更新链表头
*head = currentStudent;
}
prevStudent = currentStudent;
}
else if (scmark == 'c') {
// 课程
// 读取并添加课程信息
tempCourseNode = (CourseListNode*) malloc(sizeof(CourseListNode));
if (tempCourseNode == NULL) {
printf("内存分配失败!\n");
break;
}
int readCount = fscanf(fp, "%d%s%f%f%f",
&tempCourseNode->data.daihao, tempCourseNode->data.name,
&tempCourseNode->data.xuefen, &tempCourseNode->data.chengji,&tempCourseNode->data.GPA);
// 抵达文件尾或无效数据
if (readCount != 5) {
// 需要释放tempCourseNode否则内存泄漏
free(tempCourseNode);
break;
}
if (currentStudent) {
tempCourseNode->next = currentStudent->chead;
currentStudent->chead = tempCourseNode;
}
}else if(scmark == 'k'){
tempKeyanNode=(KeyanListNode*)malloc(sizeof(KeyanListNode));
if(tempKeyanNode==NULL){
printf("内存分配失败!\n");
break;
}
int readCount = fscanf(fp, "%s",&tempKeyanNode->data.name);
// 抵达文件尾或无效数据
if (readCount != 1) {
// 需要释放tempCourseNode否则内存泄漏
free(tempKeyanNode);
break;
}
if (currentStudent) {
tempKeyanNode->next = currentStudent->khead;
currentStudent->khead = tempKeyanNode;
}
}
else
break;
}
fclose(fp);
}
void freeStudentList(struct Lstudent* head) {
struct Lstudent* currentStudent = head;
struct Lstudent* nextStudent;
while (currentStudent != NULL) {
CourseListNode* courseNode = currentStudent->chead;
CourseListNode* nextCourseNode;
KeyanListNode* keyanNode = currentStudent->khead;
KeyanListNode* nextKeyanNode;
while (courseNode != NULL) {
nextCourseNode = courseNode->next;
free(courseNode);
courseNode = nextCourseNode;
}
while(keyanNode!=NULL){
nextKeyanNode = keyanNode->next;
free(keyanNode);
keyanNode = nextKeyanNode;
}
nextStudent = currentStudent->next;
free(currentStudent);
currentStudent = nextStudent;
}
}
void printStudentListAndCourses(struct Lstudent* head) {
while (head != NULL) {
printf("学生信息:学号:%d,姓名:%s,专业:%s, 班级:%d,性别:%s,总平均成绩:%.2f,课程平均绩点:%.2f\n",
head->data.xuehao, head->data.name, head->data.zhuanye,head->data.Class, head->data.sex,
head->data.ZGPA, head->data.KGPA);
// 打印课程信息
CourseListNode* courseNode = head->chead;
if(courseNode==NULL){
printf("无课程信息\n");
}
while (courseNode != NULL) {
printf("课程信息:课程编号:%d,课程名称:%s,课程学分:%.1f,课程成绩:%.1f,课程绩点:%.1f\n",
courseNode->data.daihao, courseNode->data.name,
courseNode->data.xuefen, courseNode->data.chengji,courseNode->data.GPA);
courseNode = courseNode->next;
}
KeyanListNode* keyanNode = head->khead;
if(keyanNode==NULL){
printf("无科研竞赛信息\n");
}
while(keyanNode!=NULL){
printf("科研竞赛信息:%s\n",keyanNode->data.name);
keyanNode = keyanNode->next;
}
printf("\n\n");
head = head->next;
}
}
void printtargetstudent(struct Lstudent* head){
if(head != NULL) {
printf("姓名:%s,学号:%d,专业:%s,班级:%d,性别:%s,课程平均绩点:%.2f, 总平均成绩:%.2f\n",
head->data.name,
head->data.xuehao,
head->data.zhuanye,
head->data.Class,
head->data.sex,
head->data.KGPA,
head->data.ZGPA);
}
}
void cover(struct Lstudent* head, const char* filename) {
FILE* fp = fopen(filename, "wb");
if (fp == NULL) {
printf("无法打开文件进行写入!\n");
return;
}
if (head == NULL) {
return;
}
while (head != NULL) {
// 写入学生信息
fprintf(fp,"s");
fprintf(fp, " %d %s %s %d %s %.2f %.2f\n",
head->data.xuehao, head->data.name,head->data.zhuanye,head->data.Class, head->data.sex,
head->data.ZGPA, head->data.KGPA);
// 写入课程信息
CourseListNode* courseNode = head->chead;
KeyanListNode* keyanNode = head->khead;
while (courseNode != NULL) {
fprintf(fp,"c");
fprintf(fp, " %d %s %.1f %.1f %.1f\n",
courseNode->data.daihao, courseNode->data.name,
courseNode->data.xuefen, courseNode->data.chengji,courseNode->data.GPA);
courseNode = courseNode->next;
}
while (keyanNode != NULL) {
fprintf(fp,"k");
fprintf(fp, " %s\n",keyanNode->data.name);
keyanNode = keyanNode->next;
}
head = head->next;
}
int result = fclose(fp);
if (result != 0) {
perror("fclose failed");
} else {
printf("文件写入成功并关闭\n");
}
}
void KGPA(struct Lstudent* head) {
if (head == NULL) {
return;
}
float a = 0, b = 0, c = 0, d = 0, e = 0;
struct Lstudent* p = head;
struct Lcourse* q;
while (p != NULL) {
if (p->chead == NULL) {
p->data.KGPA = 0.00;
p = p->next;
continue;
}
q = p->chead;
while (q != NULL) {
a = q->data.GPA;
b = q->data.xuefen;
c = a * b;
d = d + c;
e = e + b;
q = q->next;
}
if (e == 0) {
p->data.KGPA = 0.00;
} else {
p->data.KGPA = d / e;
}
d = 0;
e = 0;
p = p->next;
}
}
int countStudents(struct Lstudent* studentsHead) {
int studentCount = 0;
struct Lstudent* currStudent = studentsHead;
while (currStudent != NULL) {
studentCount++;
currStudent = currStudent->next;
}
return studentCount;
}
int countCoursesForStudent(struct Lstudent* student) {
int courseCount = 0;
CourseListNode* currentCourse = student->chead;
while (currentCourse != NULL) {
courseCount++;
currentCourse = currentCourse->next;
}
return courseCount;
}
void ZGPA(struct Lstudent* head) {
if (head == NULL) {
return;
}
float a = 0, b = 0, c = 0, d = 0, e = 0;
struct Lstudent* p = head;
struct Lcourse* q;
while (p != NULL) {
if (p->chead == NULL) {
p->data.ZGPA = 0.00;
p = p->next;
continue;
}
q = p->chead;
while (q != NULL) {
a = q->data.chengji;
b = q->data.xuefen;
c = a * b;
d = d + c;
e = e + b;
q = q->next;
}
if (e == 0) {
p->data.ZGPA = 0.00;
} else {
p->data.ZGPA = d / e;
}
d = 0;
e = 0;
p = p->next;
}
}
struct Lstudent* deleteStudentByXuehao(struct Lstudent* head, int targetXuehao) {
struct Lstudent* curr = head;
struct Lstudent* prev = NULL;
while (curr != NULL && curr->data.xuehao != targetXuehao) {
prev = curr;
curr = curr->next;
}
if (curr != NULL) {
CourseListNode* courseNode = curr->chead;
KeyanListNode* keyanNode = curr->khead;
CourseListNode* Coursetemp;
KeyanListNode* keyantemp;
while (courseNode != NULL) {
Coursetemp = courseNode->next;
free(courseNode);
courseNode = Coursetemp;
}
while (keyanNode != NULL) {
keyantemp = keyanNode->next;
free(keyanNode);
keyanNode = keyantemp;
}
if (prev == NULL) {
head = curr->next;
} else {
prev->next = curr->next;
}
free(curr);
}
else{
printf("未找到\n");
}
return head;
}
CourseListNode* deleteCourseOfStudentByDaihao(struct Lstudent* studentNode, int targetDaihao) {
if (studentNode == NULL || studentNode->chead == NULL) {
printf("该学生课程信息为空\n");
return NULL;
}
CourseListNode* prev = NULL;
CourseListNode* curr = studentNode->chead;
while (curr != NULL && curr->data.daihao != targetDaihao) {
prev = curr;
curr = curr->next;
}
if (curr != NULL) {
if (prev == NULL) {
studentNode->chead = curr->next;
} else {
prev->next = curr->next;
}
CourseListNode* p = curr;
curr = curr->next;
free(p);
printf("已删除\n");
}
else{
printf("未找到课程编号\n");
}
return curr;
}
CourseListNode* deleteCourseOfStudentByName(struct Lstudent* studentNode, char * targetName) {
if (studentNode == NULL || studentNode->chead == NULL) {
printf("该学生课程信息为空\n");
return NULL;
}
CourseListNode* prev = NULL;
CourseListNode* curr = studentNode->chead;
while (curr != NULL && strcmp(curr->data.name, targetName) != 0) {
prev = curr;
curr = curr->next;
}
if (curr != NULL) {
if (prev == NULL) {
studentNode->chead = curr->next;
} else {
prev->next = curr->next;
}
CourseListNode* p = curr;
curr = curr->next;
free(p);
printf("已删除\n");
}
else{
printf("未找到\n");
}
return curr;
}
struct CourseListNode* clearStudentCourses(struct Lstudent* targetStudent) {
CourseListNode* courseNode = targetStudent->chead;
CourseListNode* tempCourseNode;
while (courseNode != NULL) {
tempCourseNode = courseNode->next;
free(courseNode);
courseNode = tempCourseNode;
}
targetStudent->chead = NULL;
targetStudent->data.KGPA = 0;
targetStudent->data.ZGPA = 0;
return (struct CourseListNode*) targetStudent->chead;
}
//清空所有学生信息
struct Lstudent* clearStudentList(struct Lstudent* head,const char* filename) {
struct Lstudent* current = head;
struct Lstudent* next;
while (current != NULL) {
next = current->next;
CourseListNode* courseNode = current->chead;
KeyanListNode* keyanNode = current->khead;
CourseListNode* tempCourseNode;
KeyanListNode* tempKeyanNode;
while (courseNode != NULL) {
tempCourseNode = courseNode->next;
free(courseNode);
courseNode = tempCourseNode;
}
while(keyanNode != NULL){
tempKeyanNode = keyanNode->next;
free(keyanNode);
keyanNode = tempKeyanNode;
}
free(current);
current = next;
}
head = NULL;
FILE* fp = fopen(filename, "w+");
if (fp != NULL) {
fclose(fp); // 关闭文件即可清空内容("w+" 模式下)
} else {
printf("无法打开文件进行清空!\n");
}
return (struct Lstudent *)head;
}
KeyanListNode* deleteKeyanofStudentByName(struct Lstudent* studentNode, char * targetName) {
if (studentNode == NULL || studentNode->khead == NULL) {
printf("该学生科研竞赛信息为空\n");
return NULL;
}
KeyanListNode* prev = NULL;
KeyanListNode* curr = studentNode->khead;
while (curr != NULL && strcmp(curr->data.name, targetName) != 0) {
prev = curr;
curr = curr->next;
}
if (curr != NULL) {
if (prev == NULL) {
studentNode->khead = curr->next;
} else {
prev->next = curr->next;
}
KeyanListNode* p = curr;
curr = curr->next;
free(p);
printf("已删除\n");
}
else{
printf("未找到\n");
}
return curr;
}
struct KeyanListNode* clearStudentKeyan(struct Lstudent* targetStudent) {
KeyanListNode* keyanNode = targetStudent->khead;
KeyanListNode* tempKeyanNode;
while (keyanNode != NULL) {
tempKeyanNode = keyanNode->next;
free(keyanNode);
keyanNode = tempKeyanNode;
}
targetStudent->khead = NULL;
return (struct KeyanListNode*) targetStudent->khead;
}
int main() {
// 初始化链表
struct Lstudent* head = NULL; // 初始化为空指针
load(&head,"信息.txt");
KGPA(head);
ZGPA(head);
if (head != NULL) {
// 打印链表信息
printStudentListAndCourses(head);
// 其他对链表的操作...
// 清理链表,释放内存
freeStudentList(head);
} else {
printf("没有读取到任何学生信息。\n");
}
/*int totalStudents = countStudents(head);
printf("\n系统中共有 %d 名学生。\n", totalStudents);
printStudentList(head);
int targetXuehao;
printf("请输入目标学号:");
scanf("%d", &targetXuehao);
struct Lstudent* targetStudent = findStudentByXuehao(head, targetXuehao);
if (targetStudent != NULL) {
printf("\n目标学生的课程信息如下:\n");
printStudentCourses(targetStudent->chead);
printStudentKeyan(targetStudent->khead);
int coursesNumber = countCoursesForStudent(targetStudent);
printf("\n目标学生已修的课程数目为:%d\n", coursesNumber);}
/*
initStudentList(head); // 假设initStudentList负责初始化链表并返回头指针
// 添加学生到链表
char continueInput = 'y';
char continueCourseInput='y';
while (continueInput == 'y' || continueInput == 'Y') {
head = addStudentToList(head); // 添加学生到链表
printf("是否继续输入学生信息?(y/n): ");
scanf(" %c", &continueInput); // 注意前面的空格用于跳过回车符
}
int targetXuehao;
printf("请输入目标学号:");
scanf("%d", &targetXuehao);
struct Lstudent* targetStudent = findStudentByXuehao(head, targetXuehao);
if (targetStudent == NULL) {
printf("未找到学号为%d的学生。\n", targetXuehao);
} else {
char continueCourseInput = 'y';
while (continueCourseInput == 'y' || continueCourseInput == 'Y') {
targetStudent->chead = addCourseToListForStudent(&targetStudent->chead);
printf("是否继续输入该学生的课程信息?(y/n): ");
scanf(" %c", &continueCourseInput);
}
}
//jidian(head);
//head = sort_student_list_by_ZGPA(head);
printf("\n已输入的学生信息如下:\n");
printStudentList(head);
if (targetStudent != NULL) {
printf("\n目标学生的课程信息如下:\n");
printStudentCourses(targetStudent->chead);
int coursesNumber = countCoursesForStudent(targetStudent);
printf("\n目标学生已修的课程数目为:%d\n", coursesNumber);
}
int totalStudents = countStudents(head);
printf("\n系统中共有 %d 名学生。\n", totalStudents);
save(head,"信息.txt");*/
return 0;
}