目录
题目及要求:
现有学生成绩信息文件 1(1.txt),内容如下(同学自己补充,共 30 名学生,数据文件格式与解析程序自己设定):
姓名 | 学号 | 语文 | 数学 | 英语 |
张明明 | 01 | 67 | 78 | 82 |
李成友 | 02 | 78 | 91 | 88 |
张辉灿 | 03 | 68 | 82 | 56 |
王露 | 04 | 56 | 45 | 77 |
陈东明 | 05 | 67 | 38 | 47 |
... | ... | ... | ... | ... |
学生成绩信息文件 2(2.txt),内容如下(同上):
姓名 | 学号 | 语文 | 数学 | 英语 |
陈果 | 31 | 57 | 68 | 82 |
李华明 | 32 | 88 | 90 | 68 |
张明东 | 33 | 48 | 42 | 56 |
李明国 | 34 | 50 | 45 | 87 |
陈道亮 | 35 | 47 | 58 | 77 |
... | ... | ... | ... | ... |
【实现要求】
试编写一管理系统,要求如下:
(1)实现对两个文件数据进行合并,生成新文件 3.txt
(2)抽取出三科成绩中有补考的学生(小于 60 分)并保存在一个新文件 4.txt
(3)对合并后的文件 3.txt 中的数据按总分降序排序(至少采用两种排序方法实现)
(4)输入一个学生姓名后,能查找到此学生的信息并输出结果(至少采用两种查找方法实现)
(5)要求使用结构体,链或数组等实现上述要求合并文件
录入学生成绩信息到链表中
List inputfile() {
char stu[50];
FILE *fp;
List s,head,p;
p=initlist();
head=initlist();
if((fp=fopen("E:\\3.txt","r"))==NULL) {
printf("Could not open the file!");
return 0;
}
fgets(stu,50,fp);
head=p;
while(!feof(fp)) { //尾插法
s=initlist(); //文件刚开始不能读入第一行元素,原因是文件空行的问题
fscanf(fp,"%s%d%d%d%d\n",s->std.name,&s->std.stdID,&s->std.Chinese,&s->std.Math,&s->std.Engish);
s->std.total=s->std.Chinese+s->std.Engish+s->std.Math;
p->next=s;
p=s;
}
p->next=NULL;
fclose(fp);
return head;
}
合并文件
int combination() {
FILE *fp1=fopen("E:\\1.txt","rb+"); //读入文件1.txt
FILE *fp2=fopen("E:\\2.txt","rb+"); //读入文件2.txt
FILE *fp3=fopen("E:\\3.txt","wb+"); //写入文件3.txt
char c;
if(fp1==NULL||fp2==NULL||fp3==NULL) {
puts("Could not open the files\n");
return 0;
}
while((c=fgetc(fp1))!=EOF) //读到文件末尾返回EOF(-1)
fputc(c,fp3); //逐个字符写入文件3.txt
while((c=fgetc(fp2))!=EOF)
fputc(c,fp3);
printf("Merged 1.txt and 2.txt into 3.txt\n");
fclose(fp1);
fclose(fp2);
fclose(fp3);
return 1;
}
直接插入排序(总分降序)
List sortscore1() {
List p,q,head,r;
head=inputfile();
p=head->next; //带头结点和第一个元素的链表
q=p->next; //第一个元素后面的链表
p->next=NULL; //链表一后面为空
while(q!=NULL) { //连表二不为空执行
p=head; //头结点,p表示头结点,在下面一定不要搞混
r=q->next; //链表二第一个元素的下一个
while(p->next!=NULL) { //头结点下一个不为空时执行
if(p->next->std.total>q->std.total) { //p->next表示头结点的下一个元素对应的总分,大于不需要调整,继续比下一个
p=p->next;
} else {
break;
}
}
q->next=p->next; //当链表一p的第一个小于链表二q的第一个元素,将q的第一个元素头插到p中
p->next=q; //插入q的第一个元素在p头结点后
q=r; //移动q到r
}
return head;
}
冒泡排序(总分降序)
List sortscore2() {
List p,q,head,tail;
tail=NULL;
head=inputfile();
while((head->next->next!=tail)) {
p=head;
q=head->next;
while(q->next!=tail) {
if((q->std.total)<(q->next->std.total)) { //小于调换
p->next=q->next;
q->next=q->next->next;
p->next->next=q;
q=p->next;
}
q=q->next;
p=p->next;
}
tail=q;
}
return head;
}
顺序查找(名字查找)
void search_Name1() {
List p=sortscore1(); //循环使用函数,要在前面声明函数,否则出现conflicting types for"XXX"
char a[10];
printf("请输入查找的名字:");
scanf("%s",a);
while(p) {
if(0==strcmp(a,p->std.name)) { //字符串匹配strcmp()
printf("姓名\t学号\t语文\t数学\t英语\t总分\n");
printf("%s\t%.2d\t%d\t%d\t%d\t%d\n",p->std.name,p->std.stdID,p->std.Chinese,p->std.Math,p->std.Engish,p->std.total);
break;
}
p=p->next;
if(p==NULL)
printf("Could not find!\n"); //找不到返回
}
}
二分查找(名字查找)
这里是先按字母首字母排序再查找
void search_Name2() {
FILE *fp;
Studentdata temp;
Studentdata stu[60]; //要加static,否则后面会出现报错,改变了局部变量
memset(stu,0,sizeof(stu)); //初始化数组
int i=0,n,m;
char std[50];
if((fp=fopen("E:\\3.txt","rb+"))==NULL) {
printf("Could not open the file!");
exit(0);
}
fgets(std,50,fp);
while(!feof(fp)) {
fscanf(fp,"%s%d%d%d%d",stu[i].name,&stu[i].stdID,&stu[i].Chinese,&stu[i].Math,&stu[i].Engish); //数组存数据
stu[i].total=stu[i].Chinese+stu[i].Math+stu[i].Engish;
i++;
}
fclose(fp);
for(n=0; n<i-1; n++) {
for(m=0; m<i-n; m++) {
if(strcmp(stu[m].name,stu[m+1].name)>0) { //按姓名字母排序
temp=stu[m];
stu[m]=stu[m+1];
stu[m+1]=temp;
}
}
}
printf("%d",i);
for(n=0; n<i; n++) {
printf("%s %.2d %d %d %d %d\n",stu[n].name,stu[n].stdID,stu[n].Chinese,stu[n].Math,stu[n].Engish,stu[n].total);
}
char a[10];
printf("请输入查找的名字:");
scanf("%s",a);
int low=1,high=i,mid;
while(low<high) {
mid=(low+high)/2;
if(strcmp(a,stu[mid].name)==0) {
printf("姓名\t学号\t语文\t数学\t英语\t总分\n");
printf("%s\t%.2d\t%d\t%d\t%d\t%d\n",stu[mid].name,stu[mid].stdID,stu[mid].Chinese,stu[mid].Math,stu[mid].Engish,stu[mid].total);
break;
} else if(strcmp(stu[mid].name,a)<0)
low=mid+1;
else high=mid-1;
if(low==high)
printf("Could not find!\n"); //找不到返回
}
}
保存不及格学生到文件中
int bujige() {
int key=60;
List p=inputfile()->next;
FILE *fp1=fopen("E:\\3.txt","rb+");
FILE *fp2=fopen("E:\\4.txt","wb+");
if((fp1==NULL)||(fp2==NULL)) {
printf("Could not open the file!");
return 0;
}
while(p) {
if((p->std.Chinese<key)||(p->std.Engish<key)||(p->std.Math<key)) {
fprintf(fp2,"%s %.2d %d %d %d\n",p->std.name,p->std.stdID,p->std.Chinese,p->std.Math,p->std.Engish);
}
p=p->next;
}
printf("4.txt successfully saved!\n");
fclose(fp1);
fclose(fp2);
}
完整代码
#include<stdio.h>
#include<locale.h>
#include<stddef.h>
#include<stdlib.h>
#include<string.h>
typedef struct {
int stdID;
int Chinese;
int Math;
int Engish;
int total;
char name[10];
} Studentdata,*ST;
typedef struct student {
Studentdata std;
struct student *next;
} student,*List;
List initlist() { //初始化头结点
List head;
head=(List)malloc(sizeof(student));
head->next=NULL;
return head;
}
//函数声明,不声明,下面调用函数会出现错误
int combination(); //合并函数 ,合并1.txt和2.txt到3.txt中
List inputfile(); //录入成绩
int bujige(); //补考学生保存4.txt
List sortscore1(); //排序
List sortscore2(); //排序
void search_Name1(); //查找
void search_Name2(); //名字排序并查找
//读入学生的信息
List inputfile() {
char stu[50];
FILE *fp;
List s,head,p;
p=initlist();
head=initlist();
if((fp=fopen("E:\\3.txt","r"))==NULL) {
printf("Could not open the file!");
return 0;
}
fgets(stu,50,fp);
head=p;
while(!feof(fp)) { //尾插法
s=initlist(); //文件刚开始不能读入第一行元素,原因是文件空行的问题
fscanf(fp,"%s%d%d%d%d\n",s->std.name,&s->std.stdID,&s->std.Chinese,&s->std.Math,&s->std.Engish);
s->std.total=s->std.Chinese+s->std.Engish+s->std.Math;
p->next=s;
p=s;
}
p->next=NULL;
fclose(fp);
return head;
}
//查找不及格的保存文件4.txt中
int bujige() {
int key=60;
List p=inputfile()->next;
FILE *fp1=fopen("E:\\3.txt","rb+");
FILE *fp2=fopen("E:\\4.txt","wb+");
if((fp1==NULL)||(fp2==NULL)) {
printf("Could not open the file!");
return 0;
}
while(p) {
if((p->std.Chinese<key)||(p->std.Engish<key)||(p->std.Math<key)) {
fprintf(fp2,"%s %.2d %d %d %d\n",p->std.name,p->std.stdID,p->std.Chinese,p->std.Math,p->std.Engish);
}
p=p->next;
}
printf("4.txt successfully saved!\n");
fclose(fp1);
fclose(fp2);
}
//合并后的学生成绩按总分降序排序,两种排序方法实现
//直接插入排序,拆分链表
List sortscore1() {
List p,q,head,r;
head=inputfile();
p=head->next; //带头结点和第一个元素的链表
q=p->next; //第一个元素后面的链表
p->next=NULL; //链表一后面为空
while(q!=NULL) { //连表二不为空执行
p=head; //头结点,p表示头结点,在下面一定不要搞混
r=q->next; //链表二第一个元素的下一个
while(p->next!=NULL) { //头结点下一个不为空时执行
if(p->next->std.total>q->std.total) { //p->next表示头结点的下一个元素对应的总分,大于不需要调整,继续比下一个
p=p->next;
} else {
break;
}
}
q->next=p->next; //当链表一p的第一个小于链表二q的第一个元素,将q的第一个元素头插到p中
p->next=q; //插入q的第一个元素在p头结点后
q=r; //移动q到r
}
return head;
}
//冒泡排序
List sortscore2() {
List p,q,head,tail;
tail=NULL;
head=inputfile();
while((head->next->next!=tail)) {
p=head;
q=head->next;
while(q->next!=tail) {
if((q->std.total)<(q->next->std.total)) { //小于调换
p->next=q->next;
q->next=q->next->next;
p->next->next=q;
q=p->next;
}
q=q->next;
p=p->next;
}
tail=q;
}
return head;
}
//查找学生的信息并输出结果
//顺序查找
void search_Name1() {
List p=sortscore1(); //循环使用函数,要在前面声明函数,否则出现conflicting types for"XXX"
char a[10];
printf("请输入查找的名字:");
scanf("%s",a);
while(p) {
if(0==strcmp(a,p->std.name)) { //字符串匹配strcmp()
printf("姓名\t学号\t语文\t数学\t英语\t总分\n");
printf("%s\t%.2d\t%d\t%d\t%d\t%d\n",p->std.name,p->std.stdID,p->std.Chinese,p->std.Math,p->std.Engish,p->std.total);
break;
}
p=p->next;
if(p==NULL)
printf("Could not find!\n"); //找不到返回
}
}
//按姓氏字母排序并查找,二分查找
void search_Name2() {
FILE *fp;
Studentdata temp;
Studentdata stu[60]; //要加static,否则后面会出现报错,改变了局部变量
memset(stu,0,sizeof(stu)); //初始化数组
int i=0,n,m;
char std[50];
if((fp=fopen("E:\\3.txt","rb+"))==NULL) {
printf("Could not open the file!");
exit(0);
}
fgets(std,50,fp);
while(!feof(fp)) {
fscanf(fp,"%s%d%d%d%d",stu[i].name,&stu[i].stdID,&stu[i].Chinese,&stu[i].Math,&stu[i].Engish); //数组存数据
stu[i].total=stu[i].Chinese+stu[i].Math+stu[i].Engish;
i++;
}
fclose(fp);
for(n=0; n<i-1; n++) {
for(m=0; m<i-n; m++) {
if(strcmp(stu[m].name,stu[m+1].name)>0) { //按姓名字母排序
temp=stu[m];
stu[m]=stu[m+1];
stu[m+1]=temp;
}
}
}
printf("%d",i);
for(n=0; n<i; n++) {
printf("%s %.2d %d %d %d %d\n",stu[n].name,stu[n].stdID,stu[n].Chinese,stu[n].Math,stu[n].Engish,stu[n].total);
}
char a[10];
printf("请输入查找的名字:");
scanf("%s",a);
int low=1,high=i,mid;
while(low<high) {
mid=(low+high)/2;
if(strcmp(a,stu[mid].name)==0) {
printf("姓名\t学号\t语文\t数学\t英语\t总分\n");
printf("%s\t%.2d\t%d\t%d\t%d\t%d\n",stu[mid].name,stu[mid].stdID,stu[mid].Chinese,stu[mid].Math,stu[mid].Engish,stu[mid].total);
break;
} else if(strcmp(stu[mid].name,a)<0)
low=mid+1;
else high=mid-1;
if(low==high)
printf("Could not find!\n"); //找不到返回
}
}
//打印函数
int PrintList_L(List p) {
while(p) {
printf("%s\t%.2d\t%d\t%d\t%d\t%d\n",p->std.name,p->std.stdID,p->std.Chinese,p->std.Math,p->std.Engish,p->std.total);
p = p->next;
}
printf("\n");
return 0;
}
//合并文件函数
int combination() {
FILE *fp1=fopen("E:\\1.txt","rb+"); //读入文件1.txt
FILE *fp2=fopen("E:\\2.txt","rb+"); //读入文件2.txt
FILE *fp3=fopen("E:\\3.txt","wb+"); //写入文件3.txt
char c;
if(fp1==NULL||fp2==NULL||fp3==NULL) {
puts("Could not open the files\n");
return 0;
}
while((c=fgetc(fp1))!=EOF) //读到文件末尾返回EOF(-1)
fputc(c,fp3); //逐个字符写入文件3.txt
while((c=fgetc(fp2))!=EOF)
fputc(c,fp3);
printf("Merged 1.txt and 2.txt into 3.txt\n");
fclose(fp1);
fclose(fp2);
fclose(fp3);
return 1;
}
void menu() {
system("cls"); //清屏信号
printf("\n\n\n\n");
printf("\t\t|------------------------STUDENT GRADE SYSTEM-------------------------------|\n");
printf("\t\t|\t 0.退出 |\n");
printf("\t\t|\t 1.合并1.txt和2.txt文件,生成3.txt文件 |\n");
printf("\t\t|\t 2.录入学生信息到链表 |\n");
printf("\t\t|\t 3.抽取三科成绩中补考的学生(<60)保存到4.txt文件 |\n");
printf("\t\t|\t 4.按总分降序排序(直接插入排序) |\n");
printf("\t\t|\t 5.按总分降序排序(冒泡排序) |\n");
printf("\t\t|\t 6.输入姓名,查找学生信息(直接查找) |\n");
printf("\t\t|\t 7.输入姓名,查找学生信息(按姓名首字母排序并查找,二分查找) |\n");
printf("\t\t|\t 8.输入姓名,查找学生信息(fibonacci查找) |\n");
printf("\t\t|---------------------------------------------------------------------------|\n");
printf("\t\t|======================请输入对应数字(0-7)==================================|\n");
}
int main() {
List p;
int n;
menu();
printf("请输入(0-7)>> ");
scanf("%d",&n);
while(1) {
switch(n) {
case 1: {
combination();
break;
}
case 2: {
printf("姓名\t学号\t语文\t数学\t英语\t总分\n");
p=inputfile();
PrintList_L(p->next);
break;
}
case 3: {
bujige();
break;
}
case 4: {
printf("姓名\t学号\t语文\t数学\t英语\t总分\n");
p=sortscore1();
PrintList_L(p->next);
break;
}
case 5: {
printf("姓名\t学号\t语文\t数学\t英语\t总分\n");
p=sortscore2();
PrintList_L(p->next);
break;
}
case 6:
search_Name1();
break;
case 7:
search_Name2();
break;
default:
break;
}
if(n==0) break;
getch(); //过滤回车键
menu();
printf("请输入(0-7)>> ");
scanf("%d",&n);
}
}
这是我的数据结构课设题目,想分享给大家参考,因为我觉得在这里分享会提高我对代码的兴趣,我也知道学习路上会有很多阻碍,非常感谢这个网站带来的帮助,我也希望帮助更多人,如有不足的地方,欢迎各位大神不吝赐教。