#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define N 3
#define LEN (Student*) malloc(sizeof(Student))
/* 学生数据结构 */
typedef struct node
{
char num[];
char name[];
int score[N];
int sum;
double ave;
struct node *next;
} Student;
/* 头指针 */
Student *head = NULL;
/* 临时指针 */
Student *tmp = NULL;
/* 课程名称 */
char CLASSNAME[N][] = {"大物", "高数", "c语言"};
/* 命令开关 */
int SWITCH[] = {, , , , , , , , , , , , , , , };
/* 函数声明 */
int Menu();
Student* Init();
int CheckNUM(char*);
int CheckName(char*);
int CheakScore(int score);
int Same_NUM(char*);
void InputNodeInfo(Student*);
void OutputNodeInfo(Student*);
Student* SearchFrontNode(Student*);
void DeleteNode(Student*);
void InsertBefore();
void InputList();
Student* SearchID(char*);
Student* SearchName(char*);
void SearchDeleteNode();
void OutList();
void SearchPrintNode();
void Compute();
int CmpID(Student*, Student*, int);
int CmpSum(Student*, Student*, int);
int CmpScore(Student*, Student*, int);
Student* SearchMaxNode(int (*cmp)(Student*, Student*, int), int);
Student* Sort(int (*cmp)(Student*, Student*, int), int);
void OutputToFile(FILE*, Student*, int);
void InsertAfter(Student*);
void SaveToFile();
void LoadFile();
void CopyFile();
void InsertToFile();
void FreeList(Student* p);
void Stat();
void Quit();
/* 主函数 */
int main()
{
int n;
while ()
{
n = Menu();
{
if (n == || n == || SWITCH[])
{
switch (n)
{
/* 执行初始化 */
case :
head = Init();
printf("LOOK...初始化成功\n");
break;
/* 创建链表 ,输入学生信息*/
case :
InputList();
break;
/* 查找学号或姓名删除信息 */
case :
SearchDeleteNode();
break;
/* 输出全部学生信息 */
case :
system("cls");
OutList();
break;
/* 按姓名查找学生信息*/
case :
SearchPrintNode();
break;
/* 保存到文件 */
case :
SaveToFile();
break;
/* 从文件中读取学生信息*/
case :
if (SWITCH[])
{
head = Init();
LoadFile();
}
else
{
printf("当前文件未保存\n");
}
break;
/* 计算所有学生的总分和平均分 */
case :
Compute();
SWITCH[] = ;
printf("计算完毕\n");
break;
/* 插入一个学生信息到链表 */
case :
InsertBefore();
SWITCH[] = ;
SWITCH[] = ;
break;
/* 复制文件 */
case :
CopyFile();
break;
/* 排序,按总分排序并打印学生信息 */
case :
if (SWITCH[])
{
head = Sort(CmpSum, );
system("cls");
OutList();
}
else
{
printf("请先计算总分!\n");
}
break;
/* 尾部添加一个学生信息到文件中 */
case :
InsertToFile();
SWITCH[] = ;
printf("尾部添加完毕!\n");
break;
/* 按学号搜索..学生信息*/
case :
if (SWITCH[])
{
head = Sort(CmpID, );
system("cls");
OutList();
}
else
{
printf("请先计算总分!\n");
}
break;
/* 分类汇总 */
case :
system("cls");
Stat();
break;
/* 结束 */
case :
Quit();
break;
default:
printf("无效命令!\n");
fflush(stdin);
}
system("pause");
}
else
{
printf("你必须首先初始化!\n");
system("pause");
}
}
}
system("pause");
return ;
}
/* 菜单 */
int Menu()
{
int n;
system("cls");
fflush(stdin);
printf("*********************************************************************\n");
printf("*********************************************************************\n");
printf("【01】 初始化........\n");
printf("【02】 输入学生信息\n");
printf("【03】 查找学号或姓名删除信息\n");
printf("【04】 输出全部学生信息\n");
printf("【05】 按姓名查找学生信息\n");
printf("【06】 保存到文件\n");
printf("【07】 从文件中读取学生信息\n");
printf("【08】 计算所有学生的总分和平均分\n");
printf("【09】 插入一个学生信息到链表中\n");
printf("【10】 复制文件\n");
printf("【11】 按总分排序并打印学生信息\n");
printf("【12】 尾部添加一个学生信息到文件中\n");
printf("【13】 按学号搜索..学生信息\n");
printf("【14】 分类汇总\n");
printf("【15】 退出\n");
printf("********************************************************************\n");
printf("请输入命令编号: ");
scanf("%d", &n);
return n;
}
/* 初始化 */
Student* Init()
{
int i;
Student *head;
head = LEN;
head->next = NULL;
/* 命令开关初始化 */
for (i = ; i < ; i++)
{
SWITCH[i] = ;
}
SWITCH[] = ;
SWITCH[] = ;
return head;
}
/* 检查学号 */
int CheckNUM(char* s)
{
int i;
if (strlen(s) == || strlen(s) > ) return ;
for (i = ; i < strlen(s); i++)
{
if (s[i] < '' || s[i] > '') return ;
}
return ;
}
/* 检查姓名 */
int CheckName(char* s)
{
int i;
if (strlen(s) == || strlen(s) > ) return ;
for (i = ; i < strlen(s); i++)
{
if (!(s[i] >= 'a' && s[i] <= 'z' || s[i] >= 'A' && s[i] <= 'Z')) return ;
}
return ;
}
/* 检查分数 */
int CheakScore(int score)
{
if (score > || score <= ) return ;
return ;
}
/* 检查相同学号 */
int Same_NUM(char* s)
{
Student *p = head->next;
while(p != NULL)
{
if (strcmp(s, p->num) == ) return ;
p = p->next;
}
return ;
}
/* 给p指向的节点输入信息 */
void InputNodeInfo(Student* p)
{
fflush(stdin);
/* 学号 */
printf("\n请输入学号: ");
do
{
gets(p->num);
if (!CheckNUM(p->num))
{
printf("数据不标准,请重新输入学号: ");
}
else if (Same_NUM(p->num))
{
printf("检测到此学号存在,请重新输入: ");
}
}while (!(CheckNUM(p->num) && !Same_NUM(p->num)));
/* 姓名 */
printf("请输入姓名: ");
do
{
gets(p->name);
if (!CheckName(p->name))
{
printf("数据不标准,请重新输入姓名: ");
}
}
while (!CheckName(p->name));
/* 成绩 */
int i;
for (i = ; i < N; i++)
{
printf("请输入 %s 成绩: ", CLASSNAME[i]);
do
{
fflush(stdin);
scanf("%d", &p->score[i]);
if (!CheakScore(p->score[i]))
{
printf("数据不标准,请重新输入 %s 成绩: ", CLASSNAME[i]);
}
}
while (!CheakScore(p->score[i]));
}
/* 总分及平均分 */
p->sum = -;
p->ave = -;
}
/* 输出p指向节点的信息 */
void OutputNodeInfo(Student* p)
{
int i;
printf("\n");
printf("姓名: %s\n", p->name);
printf("学号: %s\n", p->num);
for (i = ; i < N; i++)
{
printf("%s 成绩: %d\n", CLASSNAME[i], p->score[i]);
}
/* 计算过才输出 */
if (SWITCH[]) printf("总分: %d\n", p->sum);
if (SWITCH[]) printf("平均分: %.2lf\n", p->ave);
}
/* 返回r的前一个节点 */
Student* SearchFrontNode(Student* r)
{
Student *p = head;
while (p->next != r) p = p->next;
return p;
}
/* 删除r指向的节点 */
void DeleteNode(Student* r)
{
Student *p = SearchFrontNode(r);
p->next = r->next;
}
/* 头插法插入节点 */
void InsertBefore()
{
Student *s = LEN;
InputNodeInfo(s);
s->next = head->next;
head->next = s;
}
/* 输入链表 */
void InputList()
{
int n;
printf("有多少个学生信息要输入? ");
scanf("%d", &n);
while (n--)
{
InsertBefore();
}
}
/* 按学号查找 */
Student* SearchID(char* num)
{
Student *p = head->next;
while (p != NULL)
{
if (strcmp(p->num, num) == ) break;
p = p->next;
}
return p;
}
/* 按姓名查找 */
Student* SearchName(char* name)
{
Student *p = head->next;
while (p != NULL)
{
if (strcmp(p->name, name) == ) break;
p = p->next;
}
return p;
}
/* 按学号或姓名查找删除节点 */
void SearchDeleteNode()
{
Student *p;
fflush(stdin);
char str[];
char sure[];
/* 输入合法性判断 */
printf("请输入你要删除的学生的 姓名 或 学号: ");
do
{
gets(str);
if (!(CheckNUM(str) || CheckName(str)))
{
printf("数据不标准,请重新输入姓名或学号: ");
}
}
while (!(CheckNUM(str) || CheckName(str)));
/* 判断是姓名还是学号 */
if (str[] >= '' && str[] <= '')
{
p = SearchID(str);
if (p == NULL)
{
printf("对不起,找不到这个学号\n");
}
else
{
OutputNodeInfo(p);
printf("确认删除? (输入\"y\"确认,任意键取消): ");
if (strcmp(gets(sure), "y") == )
{
DeleteNode(p);
printf("删除成功\n");
SWITCH[] = ;
}
fflush(stdin);
}
}
else
{
p = SearchName(str);
if (p == NULL)
{
printf("对不起,找不到这个姓名\n");
}
else
{
OutputNodeInfo(p);
printf("确认删除? (输入\"y\"确认,任意键取消): ");
if (strcmp(gets(sure), "y") == )
{
DeleteNode(p);
printf("删除成功!\n");
SWITCH[] = ;
}
fflush(stdin);
}
}
}
/* 输出链表 */
void OutList()
{
Student *p = head->next;
/* 空表处理 */
if (p == NULL)
{
printf("暂无学生信息!\n");
}
while (p != NULL)
{
OutputNodeInfo(p);
p = p->next;
}
}
/* 按姓名查找记录并打印 */
void SearchPrintNode()
{
Student *p = head->next;
int ok = ;
char name[];
fflush(stdin);
/* 姓名合法性判断 */
printf("请输入你要查找的学生姓名: ");
do
{
gets(name);
if (!CheckName(name))
{
printf("数据不标准,请重新输入姓名: ");
}
}
while (!CheckName(name));
/* 按姓名查找节点 */
while (p != NULL)
{
if (strcmp(p->name, name) == )
{
ok = ;
OutputNodeInfo(p);
}
p = p->next;
}
if (ok)
{
printf("对不起,找不到这个姓名\n");
}
}
/* 计算总分和均分 */
void Compute()
{
int i;
Student *p = head->next;
while (p != NULL)
{
int sum = ;
for (i = ; i < N; i++)
{
sum += p->score[i];
}
p->sum = sum;
p->ave = sum * 1.0 /N;
p = p->next;
}
}
/* 比较学号 */
int CmpID(Student* a, Student* b, int k)
{
return strcmp(a->num, b->num);
}
/* 比较总分 */
int CmpSum(Student* a, Student* b, int k)
{
return b->sum - a->sum;
}
/* 比较各科分数 */
int CmpScore(Student* a, Student* b, int k)
{
return b->score[k] - a->score[k];
}
/* 选择最大元素 */
Student* SearchMaxNode(int (*cmp)(Student* a, Student* b, int k), int k)
{
Student *p = head->next;
Student *max = p;
while (p != NULL)
{
if (cmp(p, max, k) < )
{
max = p;
}
p = p->next;
}
return max;
}
/* 排序 */
Student* Sort(int (*cmp)(Student* a, Student* b, int k), int k)
{
Student *newhead = LEN;
Student *p = newhead;
Student *max;
while (head->next != NULL)
{
max = SearchMaxNode(cmp, k);
p->next = max;
DeleteNode(max);
p = p->next;
}
/* 表尾处理 */
p->next = NULL;
return newhead;
}
/* 将s插入链表尾部 */
void InsertAfter(Student* s)
{
Student *p = head;
while (p->next != NULL) p = p->next;
s->next = NULL;
p->next = s;
}
/* 保存到文件 */
void SaveToFile()
{
/* 处理尾部添加表尾情况 */
if (SWITCH[])
{
InsertAfter(tmp);
}
FILE *fp;
int i;
Student *p;
char file[];
fflush(stdin);
printf("请输入要保存的文件名: ");
gets(file);
if ((fp = fopen(file, "wt")) == NULL)
{
printf("写文件错误.......!\n");
return;
}
for(p = head->next;p!=NULL;p=p->next)
fprintf(fp,"%s %s \n",p->name,p->num);
for(i=;i<;i++)
{
fprintf(fp,"%d\n",p->score[i]);
}
printf("文件保存成功!\n");
fclose(fp);
SWITCH[] = ;
/* 处理尾部添加情况 */
if (SWITCH[])
{
DeleteNode(tmp);
SWITCH[] = ;
}
}
/* 从文件中读入记录 */
void LoadFile()
{
int i;
FILE *fp;
char file[];
fflush(stdin);
printf("请输入文件名: ");
gets(file);
if ((fp = fopen(file, "rt")) == NULL)
{
printf("对不起,无法打开文件!\n");
return;
}
/* 文件未结束时读入数据 */
while (!feof(fp))
{
Student *s = LEN;
fscanf(fp, "%s", s->name);
fscanf(fp, "%s", s->num);
for (i = ; i < N; i++)
{
fscanf(fp, "%d", &s->score[i]);
}
s->next = head->next;
head->next = s;
}
printf("文件读取成功!\n");
fclose(fp);
}
/* 复制文件 */
void CopyFile()
{
FILE *fp1, *fp2;
char ch, file1[], file2[];
fflush(stdin);
/* 读入源文件 */
printf("请输入源文件名: ");
gets(file1);
if ((fp1 = fopen(file1, "rb")) == NULL)
{
printf("对不起,无法打开文件!\n");
return;
}
/* 读入目标文件 */
printf("请输入目标文件名: ");
gets(file2);
if ((strcmp(file1, file2) == ) || ((fp2 = fopen(file2, "wb")) == NULL))
{
printf("对不起,无法创建文件!\n");
return;
}
/* 逐个字符拷贝 */
while (!feof(fp1))
{
ch = fgetc(fp1);
if (ch != EOF)
fputc(ch, fp2);
}
fclose(fp1);
fclose(fp2);
printf("文件拷贝成功!\n");
}
/* 尾部添加记录到文件中 */
void InsertToFile()
{
tmp = LEN;
InputNodeInfo(tmp);
SWITCH[] = ;
}
/* 分类统计 */
void Stat()
{
int i, j, n = ;
int sum[N] = {};
Student *p = head->next;
if (p == NULL)
{
printf("暂无学生信息,无法统计\n");
return;
}
/* 统计各科总分 */
while (p != NULL)
{
/* 记录学生总数 */
n++;
for (i = ; i < N; i++)
{
sum[i] += p->score[i];
}
p = p->next;
}
/* 各科分别输出 */
for (i = ; i < N; i++)
{
printf("%s 总均分: %.2lf\n", CLASSNAME[i], sum[i] * 1.0 / n);
head = Sort(CmpScore, i);
j = ;
p = head->next;
while (p != NULL)
{
j++;
printf("第%d名 %s %d\n", j, p->name, p->score[i]);
p = p->next;
}
printf("\n");
}
}
/* 释放链表 */
void FreeList(Student* p)
{
if (p->next != NULL)
{
FreeList(p->next);
}
free(p);
}
/* 退出 */
void Quit()
{
if (!SWITCH[])
{
printf("请先保存文件!\n");
return;
}
if (head != NULL)
{
FreeList(head);
}
exit();
}