核心知识
单向链表基本操作+对文件的基本操作
使用说明
- 请先建好一个
.txt
文件并记下路径名,文件可以为空,也可以预先存好数据 - 建议创建一个空文件,通过程序来向文件中存数据。
- 手动去文件中存数据需要严格按照格式。
如果想预先手动存一些数据,需要按照以下格式:
在某些编译器上,姓名可能不支持中文
姓名1 语文 数学 英语 计算机 C语言 平均分 总分1
…
姓名n 语文 数学 英语 计算机 C语言 平均分 总分n
文件结尾,也就是最后一行的
总分n
后面不要有任何字符
。
代码附上
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <malloc.h>
#define MAXNAME 30
#define MAXSUBJECT 5
#define SPACE ' '
typedef struct student
{
char name[MAXNAME];
int score[MAXSUBJECT];
double aver;
int sum;
} STUDENT;
typedef struct node
{
STUDENT data;
struct node *next;
} NODE, *LIST;
int i, choice;
char ch, c, c2;
char s1[10] = "name";
char s2[10] = "average";
char s3[10] = "sum";
char s4[10] = "chinese";
char s5[10] = "math";
char s6[10] = "english";
char s7[10] = "computer";
char s8[10] = "c";
char FileName[100];
LIST headp = NULL;
// 读入文件时,添加链表成员
void AddFscanf(NODE);
// 使用说明
void Instructions();
// 进行完一次操作后,询问是否继续
void Ask();
// 打印分割线
void SplitLine();
// 操作1,用户输入时,添加链表成员,
void AddUserInput();
// 操作2,删除节点
void Delete();
// 操作3,查询某个节点信息
void Inquire();
// 操作4,更新某个节点信息
void Update();
// 操作5,排序学生信息
void Sort();
// 操作6,保存信息到文件中
void Save();
// 操作7,打印链表
void Print();
// 释放链表
void Free();
int main(void)
{
FILE *fp = NULL;
NODE head;
NODE temp;
headp = &head;
head.next = NULL;
temp.next = NULL;
printf("请输入文件的绝对路径+文件名(仅限 .txt 文件)\n\n");
printf("例如,若您要打开D盘根目录下的 info.txt 文件\n");
printf("则应输入\"D:/info.txt\"(您输入的字符均应为英文字符)\n");
scanf("%s", FileName);
getchar();
if ((fp = fopen(FileName, "r")) == NULL)
{
printf("\n\"%s\" 打开失败\n\n", FileName);
exit(EXIT_FAILURE);
}
printf("\n\"%s\" 打开成功!\n", FileName);
printf("\n正在鉴定文件是否为空...\n");
c2 = getc(fp);
fclose(fp);
if (c2 == EOF)
printf("打开的文件为空文件,仅可进行写入操作!\n");
else
{
printf("文件非空,可进行任意操作\n\n");
printf("正在重新打开该文件...\n");
if ((fp = fopen(FileName, "r")) == NULL)
{
printf("can't open \"%s\" \n", FileName);
exit(EXIT_FAILURE);
}
printf("正在读取该文件中的数据...\n");
while (1)
{
fscanf(fp, "%s", temp.data.name);
for (i = 0; i < MAXSUBJECT; i++)
fscanf(fp, "%d", &temp.data.score[i]);
fscanf(fp, "%lf", &temp.data.aver);
fscanf(fp, "%d", &temp.data.sum);
ch = getc(fp);
AddFscanf(temp);
if (ch == EOF)
break;
}
printf("文件数据读取成功!\n");
fclose(fp);
}
while (1)
{
Instructions();
switch (choice)
{
case 1:
AddUserInput();
break;
case 2:
Delete();
break;
case 3:
Inquire();
break;
case 4:
Update();
break;
case 5:
Sort();
break;
case 6:
Save();
break;
case 7:
Print();
break;
case 0:
printf("Bye~ Have a good day! \n\n");
exit(EXIT_FAILURE);
default:
break;
}
Ask();
}
Free();
return 0;
}
void Free()
{
LIST temp = headp->next;
LIST deletep = NULL;
while (temp != NULL)
{
deletep = temp;
temp = temp->next;
free(deletep);
}
}
void Save()
{
FILE *fp = NULL;
int flag = 0;
LIST temp = headp->next;
if ((fp = fopen(FileName, "w")) == NULL)
{
printf("can't open \" %s \" \n", FileName);
exit(EXIT_FAILURE);
}
while (temp != NULL)
{
if (flag)
fprintf(fp, "\n");
fprintf(fp, "%s ", temp->data.name);
for (i = 0; i < MAXSUBJECT; i++)
fprintf(fp, "%d ", temp->data.score[0]);
fprintf(fp, "%.2f ", temp->data.aver);
fprintf(fp, "%d", temp->data.sum);
flag = 1;
temp = temp->next;
}
printf("\n保存成功!");
fclose(fp);
}
void Sort()
{
LIST temp = NULL;
STUDENT t;
int lenth = 0, j;
if (headp->next == NULL)
{
printf("数据为空!仅可进行写入操作!\n");
return;
}
temp = headp->next;
while (temp != NULL)
{
lenth++;
temp = temp->next;
}
for (i = lenth - 1; i > 0; i--)
{
temp = headp->next;
for (j = 0; j < i; j++)
{
if (temp->data.sum < temp->next->data.sum)
{
t = temp->data;
temp->data = temp->next->data;
temp->next->data = t;
}
else if (temp->data.sum == temp->next->data.sum)
{
if (strcmp(temp->data.name, temp->next->data.name) > 0)
{
t = temp->data;
temp->data = temp->next->data;
temp->next->data = t;
}
}
temp = temp->next;
}
}
printf("\n排序成功!");
}
void Update()
{
LIST temp = NULL;
int flag;
char NAME[MAXNAME];
if (headp->next == NULL)
{
printf("数据为空!\n");
return;
}
temp = headp;
printf("请输入要更新的学生姓名:\n");
while (1)
{
temp = headp;
fflush(stdin);
scanf("%s", NAME);
getchar();
while (temp != NULL)
{
if (strcmp(temp->data.name, NAME) == 0)
break;
temp = temp->next;
}
if (temp == NULL)
{
printf("错误!库中没有该学生的信息\n");
printf("键入'n'退出该功能,或键入'y'重新输入\n");
while (1)
{
flag = 0;
scanf("%c", &c);
getchar();
if (c == 'y' || c == 'Y')
{
printf("请重新输入要更新学生的姓名\n");
break;
}
else if (c == 'n' || c == 'N')
{
flag = 1;
break;
}
else
printf("输入非法!请输入'y'或'n',不要输入其它字符\n");
}
if (flag)
break;
}
else
{
temp->data.sum = 0;
temp->data.aver = 0.0;
printf("请依次输入该学生语文、数学、英语、计算机、C语言,五门课的成绩\n");
for (i = 0; i < MAXSUBJECT; i++)
{
scanf("%d", &temp->data.score[i]);
temp->data.sum += temp->data.score[i];
}
temp->data.aver = temp->data.sum * 1.0 / MAXSUBJECT;
printf("\n更新成功!");
break;
}
}
}
void Inquire()
{
LIST temp = NULL;
int flag;
char NAME[MAXNAME];
if (headp->next == NULL)
{
printf("数据为空!\n");
return;
}
temp = headp;
printf("请输入要查询的学生姓名:\n");
while (1)
{
temp = headp;
fflush(stdin);
scanf("%s", NAME);
getchar();
while (temp != NULL)
{
if (strcmp(temp->data.name, NAME) == 0)
break;
temp = temp->next;
}
if (temp == NULL)
{
printf("错误!库中没有该学生的信息\n");
printf("键入'y'重新输入或'n'退出该功能\n");
while (1)
{
flag = 0;
scanf("%c", &c);
getchar();
if (c == 'y' || c == 'Y')
{
printf("请重新输入要查询学生的姓名\n");
break;
}
else if (c == 'n' || c == 'N')
{
flag = 1;
break;
}
else
printf("输入非法!请输入'y'或'n',不要输入其它字符\n");
}
if (flag)
break;
}
else
{
printf("\n\n%s的信息如下:\n\n", NAME);
printf("%-10s %-8s %-10s %-10s %-10s %-10s %6s\n",
s2, s3, s4, s5, s6, s7, s8);
printf("%-10.2f %-10d",
temp->data.aver, temp->data.sum);
for (i = 0; i < MAXSUBJECT; i++)
printf("%-12d", temp->data.score[i]);
printf("\n");
break;
}
}
}
void Delete()
{
LIST temp = NULL, deletp = NULL;
int flag;
char NAME[MAXNAME];
if (headp->next == NULL)
{
printf("数据为空!\n");
return;
}
temp = headp;
printf("请输入要删除的学生的姓名:\n");
// 现在这个情况,链表一定不为空
while (1)
{
temp = headp;
fflush(stdin);
scanf("%s", NAME);
getchar();
// 搜索要删除的学生姓名所在结点的上一个
while (temp->next != NULL)
{
if (strcmp(temp->next->data.name, NAME) == 0)
break;
temp = temp->next;
}
if (temp->next == NULL)
{
flag = 0;
printf("您要删除的学生不存在,键入'y'重新输入或'n'退出该功能\n");
while (1)
{
c = getchar();
getchar();
if (c == 'y' || c == 'Y')
{
printf("请重新输入学生姓名:\n");
break;
}
else if (c == 'n' || c == 'N')
{
flag = 1;
break;
}
else
printf("输入非法!请重新输入'y' or 'n'\n");
}
if (flag)
break;
}
else
{
// 要删除的结点是最后一个结点
if (temp->next->next == NULL)
{
free(temp->next);
temp->next = NULL;
}
else
{
deletp = temp->next;
temp->next = temp->next->next;
free(deletp);
}
printf("\n删除成功!");
break;
}
}
}
void Ask()
{
fflush(stdin);
printf("\n\n输入'n'结束该信息管理系统,或输入其它任意字符回到菜单\n");
scanf("%c", &c);
getchar();
if (c == 'n')
{
printf("\nBye~ Have a good day! \n\n");
exit(EXIT_FAILURE);
}
}
void AddUserInput()
{
int flag = 0, flag2 = 0;
LIST newp = NULL;
LIST temp = headp->next;
printf("请输入学生姓名:\n");
while (1)
{
newp = (LIST)malloc(sizeof(NODE));
flag = 0;
temp = headp->next;
fflush(stdin);
scanf("%s", newp->data.name);
getchar();
while (temp != NULL)
{
if (strcmp(newp->data.name, temp->data.name) == 0)
{
flag = 1;
break;
}
temp = temp->next;
}
if (flag)
{
printf("\n库中已有该名字,请退回到菜单选择\"更新信息\"或选择重新输入名字\n");
printf("是否重新输入?(y/n)\n");
while (1)
{
flag2 = 0;
c = getchar();
getchar();
if (c == 'y')
{
printf("\n您选择了'y',请重新输入名字\n");
break;
}
else if (c == 'n')
{
flag2 = 1;
break;
}
else
{
printf("\n请输入'y'或'n',不要输入其它字符!\n");
printf("请重新输入'y'或'n' \n");
}
}
if (flag2)
break;
}
else
{
temp = headp;
while (temp->next != NULL)
temp = temp->next;
temp->next = newp;
newp->next = NULL;
newp->data.sum = 0;
newp->data.aver = 0.0;
printf("请依次输入该学生语文、数学、英语、计算机、C语言,五门课的成绩\n");
for (i = 0; i < MAXSUBJECT; i++)
{
scanf("%d", &newp->data.score[i]);
newp->data.sum += newp->data.score[i];
}
newp->data.aver = newp->data.sum * 1.0 / MAXSUBJECT;
printf("\n添加成功!\n");
printf("是否继续添加?(输入'n'结束该功能,输入其它任意字符继续添加)\n");
fflush(stdin);
c = getchar();
getchar();
if (c == 'n')
break;
else
printf("\n请继续输入要添加的学生的姓名\n");
}
}
}
void AddFscanf(NODE newNode)
{
LIST newp = (LIST)malloc(sizeof(NODE));
LIST temp = headp;
while (temp->next != NULL)
temp = temp->next;
temp->next = newp;
newp->next = NULL;
newp->data.sum = 0;
newp->data.aver = 0.0;
strcpy(newp->data.name, newNode.data.name);
for (i = 0; i < MAXSUBJECT; i++)
newp->data.score[i] = newNode.data.score[i];
newp->data.sum = newNode.data.sum;
newp->data.aver = newNode.data.aver;
}
void Print()
{
LIST temp = NULL;
if (headp->next == NULL)
{
printf("数据为空!\n");
return;
}
temp = headp;
printf("已存储的数据为:\n");
SplitLine();
printf("%-15s %-10s %-8s %-10s %-10s %-10s %-10s %6s\n",
s1, s2, s3, s4, s5, s6, s7, s8);
while (temp->next != NULL)
{
printf("%-15s %-10.2f %-10d",
temp->next->data.name, temp->next->data.aver,
temp->next->data.sum);
for (i = 0; i < MAXSUBJECT; i++)
printf("%-12d", temp->next->data.score[i]);
printf("\n");
temp = temp->next;
}
SplitLine();
}
void SplitLine()
{
printf("\n========================================================================================\n\n");
}
void Instructions()
{
printf("\n\n\t The Student's Grade Management System\n\n");
printf("---------------------Student Menu------------------------\n");
if (headp->next == NULL)
{
printf("* 1 输入学生信息\t\t\t * 0 退出学生系统\n");
printf("----------------------------------------------------------\n");
printf("此时数据为空!仅支持输入学生信息!\n");
printf("Enter your choice 0 or 1: ");
}
else
{
printf("* 1 输入学生信息\t\t\t * 2 删除学生信息\n");
printf("* 3 查询学生信息\t\t\t * 4 更新学生信息\n");
printf("* 5 排序学生信息\t\t\t * 6 保存学生信息\n");
printf("* 7 显示学生信息\t\t\t * 0 退出学生系统\n");
printf("----------------------------------------------------------\n");
printf("Enter your choice [0 - 9]: ");
}
scanf("%d", &choice);
printf("\n\n");
}