摘要:链表|、数组、指针
源代码展示:
#include <stdio.h>
// 动态申请内存
#include <stdlib.h>
// _getch:不需要回车,直接获取输入的字符,需要包含conio.h头文件
#include <conio.h>
//学生信息
typedef struct Student
{
int num;//学号
char name[20];//学生姓名
int score;//成绩
} Student; //类型变量名
//节点信息
typedef struct Node
{
Student student;//学生
struct Node* next;//指向下一个节点的指针
} Node;
void menu();
void input(Node* head);//输入
void print(Node* head);//打印
void count(Node* head);//统计
void find(Node* head);//查找
void save(Node* head);//保存
void load(Node* head);//加载
void modify(Node* head);//修改
void delete(Node* head);//删除
void sort(Node* head);//排序
int main()
{
//创建头结点
Node* head = malloc(sizeof(Node));
/*malloc时动态内存分配函数,用于申请一块连续的指定大小的内存块区域以void*类型返回分配的内存区域地址
头文件#include<malloc.h>,如果分配成功返回指向被分配内存的指针,否则返回空指针NULL*/
head->next = NULL;
load(head);
//创建一个死循环
while (1)
{
menu();
char c = _getch();
/*等待从键盘接收一个字符, 输入字符后,回车才能录入,注意:回车符号会被存储至缓存区,下次循环导致获取到回车
char c = getchar(); getchar(); 吸收回车getch:不需要回车,直接获取输入的字符,需要包含conio.h*/
switch (c)
{
case '1': //录入学生信息
input(head);
break;
case '2': //打印学生信息
print(head);
break;
case '3': //统计学生人数
count(head);
break;
case '4': //查找学生信息
find(head);
break;
case '5': //修改学生信息
modify(head);
break;
case '6': //删除学生信息
delete(head);
break;
case '7': //按成绩排序
sort(head);
break;
case '8': //退出系统
system("cls"); /*每次程序运行的时候都会将上一次运行输出的内容给清除掉,屏幕上只显示本次输出的结果
#include <windows.h>system("cls");这种办法的缺点是程序额外运行系统程序执行清屏操作,延长了程序执行时间。*/
printf("谢谢使用!\n");
exit(0); /*Exit() 是电脑函数。所在头文件:stdlib.h 功 能 : 关闭所有文件,终止正在执行的进程。
exit(1)表示异常退出.这个1是返回给操作系统的。 exit(x)(x不为0)都表示异常退出 exit(0)表示正常退出*/
break;
default:/*除上述以外其他情况*/
printf("请重新输入\n");
break;
}
}
return 0;
}
void menu() //主菜单
{
printf("*********************************\n");
printf("*\t学生成绩管理系统\t*\n");
printf("*********************************\n");
printf("\t1.录入学生信息\t\t\n");
printf("\t2.打印学生信息\t\t\n");
printf("\t3.统计学生人数\t\t\n");
printf("\t4.查找学生信息\t\t\n");
printf("\t5.修改学生信息\t\t\n");
printf("\t6.删除学生信息\t\t\n");
printf("\t7.按成绩排序\t\t\n");
printf("\t8.退出系统\t\t\n");
printf("*********************************\n");
}
void input(Node* head)
{
//录入学生信息
//创建结点
Node* New = malloc(sizeof(Node));
New->next = NULL;
//输入用户信息
printf("请输入学生的学号:\n ");
scanf("%d", &New->student.num);
printf("请输入学生的姓名:\n ");
scanf("%s", New->student.name);
printf("请输入学生的成绩:\n ");
scanf("%d", &New->student.score);
//定义指针指向头结点,用于遍历链表
Node* move = head;
while (move->next != NULL)
{
move = move->next;
}
//(尾插法)将学生插入到尾部 将新创建的结点,添加到链表的尾部
move->next = New;
printf("信息录入成功!\n");
save(head);
//暂停程序
system("pause");//按下任意键后,会继续执行程序
//清空控制台
system("cls");
}
void print(Node* head) //打印学生信息
{
//定义指针指向头结点,用于遍历链表
Node* move = head->next;
printf("*\t学号\t*\t姓名\t*\t成绩*\n");
while (move != NULL)
{
printf("*\t%d\t*\t%s\t*\t%d\t\n", move->student.num, move->student.name, move->student.score);
move = move->next;
}
//暂停程序
system("pause");
//清空控制台
system("cls");
}
void count(Node* head) //统计学生人数
{
int count = 0;
//定义指针指向头结点,用于遍历链表
Node* move = head->next;
while (move != NULL)
{
count++;
move = move->next;
}
printf("学生的总人数为:%d\n", count);
//暂停程序
system("pause");
//清空控制台
system("cls");
}
void find(Node* head) //查找学生信息
{
printf("请输入要查找的学生的学号: ");
int num;
scanf("%d", &num);
Node* move = head->next;
printf("*\t学号\t*\t姓名\t*\t成绩*\n");
while (move != NULL)
{
if (num == move->student.num)
{
printf("*\t%d\t*\t%s\t*\t%d\t\n", move->student.num, move->student.name, move->student.score);
//暂停程序
system("pause");
//清空控制台
system("cls");
return;
}
move = move->next;
}
printf("未找到学生信息\n");
//暂停程序
system("pause");
//清空控制台
system("cls");
}
void save(Node* head)
{
/*“r”以只读方式打开文件。 只允许读取,不允许写入
“w”以写入的方式打开文件。如果文件不存在,那么创建一个新文件,如果文件存在,那么清空原文件,再创建一个文件*/
FILE* fp = fopen("./stu.info", "w");/*FILE *fp 是声明,声明fp是指针,用来指向FILE类型的对象。 *fp是指向文件结构体的指针变量,通过fp可找到存放某个文件信息的结构变量,
根据这个结构变量的信息找到该文件,实施对文件的操作。 fp通常被成为一个指向文件的指针。*/
Node* move = head->next;//遍历链表
while (move != NULL)
{
if (fwrite(&move->student, sizeof(Student), 1, fp) != 1)
{
printf("写入失败\n");
return;
}
move = move->next;
}
fclose(fp);//关闭
}
/*fwrite(const void *ptr,size,nmemb,FILE *stream) const void *ptr:指针指向要写出数据的内存首地址;size:要写数据的基本单元的字节大小,
写出单位的大小;nmemb:要写出数据的基本单元的个数;FILE *stream:打开的文件指针 fread(void* buffer,size,count,FILE*stream)
buffer用于接收数据的内存地址;size要读的每个数据项的字节数;count:要读数据的个数;stream:输入流的指针返回值*/
void load(Node* head) //加载
{
FILE* fp = fopen("./stu.info", "r");
if (!fp)
{
printf("没有学生文件,跳过读取\n");
return;
}
Node* New = malloc(sizeof(Node));
New->next = NULL;
Node* move = head;
while (fread(&New->student, sizeof(Student), 1, fp) == 1)
{
move->next = New;
move = New;
New= malloc(sizeof(Student));
New->next = NULL;
}
free(New);
fclose(fp);
printf("读取成功\n");
}
void modify(Node* head)
{
//修改学生信息
printf("请输入要修改的学生的学号:\n");
int num;
scanf("%d", &num);
Node* move = head->next;
while (move != NULL)
{
if (move->student.num == num)
{
printf("请输入学生姓名:\n");
scanf("%s", move->student.name);
printf("请输入学生成绩:\n");
scanf("%s",&move->student.score);
save(head);
printf("修改成功\n");
//暂停程序
system("pause");
//清空控制台
system("cls");//清屏
return;
}
move = move->next;
}
//如果循环完毕,也没找到学生
if (move == NULL)
{
printf("未找到学生信息\n");
}
//暂停程序
system("pause");
//清空控制台
system("cls");
}
void delete(Node * head)
{
//删除学生信息
printf("请输入要删除的学生学号:\n ");
int Num = 0;
scanf("%d", &Num);
Node* move = head;
while (move->next != NULL)
{
if (move->next->student.num == Num)
{
Node* temp = move->next;
move->next = move->next->next;
//最后记得将删除的动态空间释放掉
free(temp);//free功 能: 释放temp指向的存储空间。
temp = NULL; //释放后随即指向NULL
save(head);//同步到文件
printf("删除成功\n");
break;
}
move = move->next;
}
if (move->next == NULL)
{
printf("未找到学生信息\n");
//暂停程序
system("pause");
//清空控制台
system("cls");
}
}
void sort(Node* head) //实现排序
{
Node* save = NULL;
Node* move = NULL;
//冒泡排序
for (Node* turn = head->next; turn->next != NULL; turn = turn->next)
{
for (move = head->next; move->next != save; move = move->next)
{
if (move->student.score <move->next->student.score)
{
Student temp = move->student;
move->student = move->next->student;
move->next->student = temp;
}
}
save = move;
}
print(head);
}
这是大一的时候写的成绩管理系统,运行结果,你们可以把代码复制到自己的电脑上进行运行。我就不进行展示了,其实就是懒。