#include<stdio.h>
#include<stdlib.h>
#include <windows.h>
#include<conio.h>
//#definefun_name(x) printf("%s ", #x) //定义把变量名转换成字符串 ???如何获取结构体中变量名等信息
//********定义数据结构********
typedef struct student {
int rec_id=NULL;//设置默认值??对否
char name[20]="";
float fs=0;
struct student * p_next=NULL;
} STD;
//*******声明子函数******
STD * record_create(); //1、生成链表
void record_add(STD * p_head); //2、添加数据
void record_insert(STD * p_head); //3、插入数据
void record_sort(STD * p_head); //4、链表排序
void record_list(STD * p_head); //5、显示数据
void record_input(STD * p_head); //6、导入数据
void record_output(STD *p_head); //7、导出数据
bool rls(STD * p_head ) ; //释放链表的函数
void paint_head(); //8、绘制介面
bool isempty(STD * p); //判定链表是否为空
// 0、**********主函数开始**********
int main(void){
STD* p_head=NULL; //定义STD型指针变量,标识链表头地址,并初始化
while(1){ //****主循环,保持所有操作都在主界面控制下****
system("cls"); //清屏并
paint_head(); //调用绘制主界面函数
inti=0;
charselect=NULL; //初始化选项标识变量
scanf("%c",&select); //接受选择项 //select=getchar();
if(select=='\n') //当直接回车时,返回、重载主界面
continue; //????必须放到前 while(getchar()!='\n') _下一句增加闪烁光标
while(getchar()!='\n') //判断输入字符的个数
i++;
if(i>0) //当输入多个字符时,无效、返回
continue;
switch(select){ //**********以下是主菜单选择部分************
//新建链表
case'1':
case'n':
case'N'://分析是否已存存链表
if(p_head!= NULL){
printf("\n\n链表已经存在按任意键,继续!");
system("pause>nul");
break;
} else
p_head=record_create();
break;
//添加节点
case'2':
case'a':
case'A':
record_add(p_head);
break;
//插入节点
case'3':
case'i':
case'I':
record_insert(p_head);
break;
//排序数据
case'4':
case'Y':
case'y':
record_sort(p_head);
break;
//显示数据
case'5':
case'v':
case'V':
record_list(p_head);
break;
//导入数据
case'6':
case'r':
case'R':
record_input(p_head);
break;
//导出数据
case'7':
case's':
case'S':
record_output(p_head);
break;
//退出系统
case'8':
case'q':
case'Q':{
printf("\n\n按任意建,退出程序!");
rls(p_head);
exit(0);
break;
}
default:
continue;
}
//********以上是:主菜单选择部分********
}
return0;
}
//*********主函数main()结束********
//0、判定链表是否为空
bool isempty(STD * p_head){
if(p_head==NULL){
printf("\n\n ");
system("echo 请先创建链表,按任意键返回主菜单!");
system(" pause>nul");
system("cls");
returntrue;
} else {
system("cls");
returnfalse;
}
}
//1、********建立链表********
STD * record_create(){
system("cls"); //清屏
printf("现在创建新链表!\n\n");
STD*p_head=NULL;
STD*p_old=NULL;
STD*p_new=NULL;
inti=0;
intlen;
printf("请输入要存储记录的条数 N:");
while (scanf("%d",&len)<1){
system("\n echo 非法输入,请按重新输入数字!");
while(getchar()!='\n');
}
p_new=(STD *)malloc(sizeof(STD));
if(p_new==NULL){ //检测内存空间申请是否成功
printf("\n链表生成失败!");
returnNULL;
}
p_new->p_next=NULL; //这里是p_new所指向在STD型变量的成员p_next的值为NULL,而不是p_new所存储的地址信息变了.变的是其指向的STD型 结构体中用以存储下一地址的成员变量值
p_old=p_new;
p_head=p_new;
for(i=0; i<len; i++){
p_new=(STD *)malloc(sizeof(STD));
if(p_new==NULL){
printf("\n链表生成中断!");
break;
}
p_new->p_next=NULL;
p_old->p_next=p_new;
p_old=p_new;
printf("\n输入第%d个结点的信息:\n",(i+1));
printf(" 学号:");
scanf("%d",&p_new->rec_id);
printf(" 姓名:");
scanf("%s",&p_new->name);
printf(" 成绩:");
scanf("%f",&p_new->fs);
if(i<len-1){ //根据需要选择是否,中断输入!
printf("\n按ESC键,返回主介面,任意键继续!\n");
if(getch()==27) break;
}
}
//system("\n\necho 新建链表成功,按任意键退出!");
printf("\n新建链表成功,按任意键退出!\n");
system("pause>nul");
returnp_head;
}
//2、*******添加数据********
void record_add(STD * p_head){
if(isempty(p_head)) //无链表结构时,即出!
return;
STD*p_cur;
STD*p_new;
p_cur=p_head; //以p_add表示当前结点,首先把头结点做为当前结点
while(NULL!=p_cur->p_next) //判断下当前结点的地址域是否为空,即是否链表尾,不为空看下一结点
p_cur=p_cur->p_next; //把下结点的地址传给p_add,直到 p_add指向尾结点,此时 p_add地址域为NULL!!
inti,len=0;
printf("\n请输入要添加记录的条数 N:");
if(scanf("%d",&len)<1){ //保证输入数字
system("\n echo 非法输入,请按任意键退出!");
system("pause>nul");
return;
}
for(i=0; i<len; i++){
p_new=(STD *)malloc(sizeof(STD)); //申请内容空间,并把地址放到原链表尾地址变量中
p_new->p_next=NULL;
p_cur->p_next=p_new;
p_cur=p_new;
printf("\n输入添加的第%d个结点的信息:\n",(i+1));
printf(" 学号:");
scanf("%d",&p_new->rec_id); //等同于 scanf("%d",&((*p_new).rec_id));
printf(" 姓名:");
scanf("%s",&p_new->name);
printf(" 成绩:");
scanf("%f",&p_new->fs);
printf("\n");
if(i<len-1){ //根据需要选择是否,中断输入!
printf("\n按ESC键,返回主介面,任意键继续!\n");
if(getch()==27) break;
}
}
printf("\n数据添加成功,按任意键退出!\n");
system("pause>nul");
return;
}
//3、*******插入数据********
void record_insert(STD * p_head){
if(isempty(p_head)) //无链表结构时,即出!
return;
STD* p_cur; //定义结构体变量
STD* p_previous;
STD* p_new;
intvalue=0; //统计总结点数
intposition=0; //设置插入点位置
p_cur=p_head->p_next; //设置头结点的地址域指向的结点(即第一个存储有效值的结点,也即首结点)为当前结点
while(NULL!=p_cur){ //统计总结点数,不包括点结点。比实际结点少一个!!!!!!!!!
value++;
p_cur=p_cur->p_next;
}
printf("当前链表有效结点总数为: %d\n",value);
printf("请输入数据插入第几个结点前面:");
while((scanf("%d",&position)<1)||(position>value)){ //保证输入数字,并不超限
if (position>value)
system("\n echo 输入超限,请重新输入数字或选择添加!");
else
system("\n echo 输入错误,请重新输入数字!");
while(getchar()!='\n'); //清除缓冲区残留的字符,分号是空语句,while不包括continue
continue;
}
//下面和插入节点 “当插入点为1时,插入到头结点与首结点之间”,在头结点前不插入任何结点
value=0; //计数置零
p_previous=p_head; //把头结点 设置为上一结点
p_cur=p_head->p_next; //把首结点 设置为当前结点
while(NULL!=p_cur){ //遍历结点,直到插入点。
value++; //当前结点,即检测指针指向结点不为空时,计数加1
if(value==position){
p_new=(STD *)malloc(sizeof(STD));
if(p_new!=NULL){
p_new->p_next=p_previous->p_next;
p_previous->p_next=p_new;
printf("\n输入插入结点的信息:\n");
printf(" 学号:");
scanf("%d",&p_new->rec_id); //等同于 scanf("%d",&((*p_new).rec_id));
printf(" 姓名:");
scanf("%s",&p_new->name);
printf(" 成绩:");
scanf("%f",&p_new->fs);
printf("\n");
break;
}
}
p_previous=p_cur;
p_cur=p_cur->p_next;
}
system("\n echo 数据插入成功,按任意键退出!");
system("pause>nul");
}
//4、*******数据排序****采用冒泡排序法****//数据对应错误!!!!!!
void record_sort(STD *p_head){
if(isempty(p_head)) //无链表结构时,即出!
return;
STD*p_curr=NULL;
STD*p_next=NULL;
float val;
inti,j;
p_curr=p_head;
p_next=p_head; //指针变量初始化
for( p_curr=p_head; p_curr!=NULL && p_curr->p_next!=NULL; p_curr=p_curr->p_next) //从表头循环到表尾
for(p_next=p_curr->p_next; p_next!=NULL&&p_next->p_next!=NULL;p_next=p_next->p_next){//对于外循环的每一个节点,取其后的最小值到当前节点
if(p_curr->p_next->fs > p_next->p_next->fs){//对内循环的每两个相邻节点,取其小的放前,大的后放后
val= p_curr->p_next->fs;
p_curr->p_next->fs=p_next->p_next->fs;
p_next->p_next->fs=val;
}
}
return;
}
//5、*******显示数据********
void record_list(STD * p_head){
if(isempty(p_head)) //无链表结构时,即出!
return;
//*************************************************以下定义表头**************
inti;
STD* p_list;
p_list=p_head->p_next;
printf("\n当前输入数据有:\n\n");
for(i=0; i<20; i++)
printf("* ");
printf("\n%s\n"," rec_id | name |fs");
printf("%s\n" ,"--------+----------------------+----- ");
//*****************************************以上定义表头,以下输入数据********
while(p_list){// while(NULL!=p_list->p_next)//不能输出最后一相结点的数据,因 p_list->p_next为空时,循环就结束了
printf(" %-7d | %-20s |%-10f\n",(*p_list).rec_id,p_list->name,p_list->fs);//(*p_list).rec_id等同于p_list->rec_id;
p_list=p_list->p_next;
}
printf("\n\n");
system("\n echo 显示结束,请按任意键退出!");
system("pause>nul");
return;
}
//6、*******导入数据********
void record_input(STD * p_head){
system("cls");
FILE*fp;
intc;
if((fp = fopen("d:\\jhm.txt","r"))!=NULL){
while(1){
c= fgetc(fp);
if( feof(fp)){
break;
}
printf("%c", c);
}
} else
printf("文件打开失败\n");
printf("\n\n");
system("\n echo 显示结束,请按任意键退出!");
system("pause>nul");
fclose(fp);
return;
}
//7、*******导出数据********
void record_output(STD * p_head){
if(isempty(p_head)) //无链表结构时,即出!
return;
STD* p_write,* p_term;
FILE* fp;
if((fp=fopen("d:\\jhm.txt","wt+"))==NULL){
printf("\n打开文件失败!返回! ");
getchar();
return;
}
p_write=p_head->p_next;
while(NULL!=p_write){
fprintf(fp,"%-6d",p_write->rec_id ); //-左对齐,+右对齐
// fprintf(fp,"%s",",");
fprintf(fp,"%-20s",p_write->name);
// fputs(",",fp);
fprintf(fp,"%-10f",p_write->fs );
fputs("\n",fp);
p_write=p_write->p_next;
}
system("\n echo 已经成功执行,请按任意键退出!");
system("pause>nul");
fclose(fp);
return;
}
//释放链表的函数---未验证
bool rls(STD * p_head){
STD* p_cur,*p_del;
p_cur=p_head;
p_del=p_head;
while(NULL!=p_cur){
p_cur=p_cur->p_next;
free(p_del);
//p_del=NULL;
p_del=p_cur;
}
}
//*******画主菜单*********//
void paint_head(){
// 设置字体颜色(高亮)
SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE),14);
inti;
constint num_top_btn=30,num_mid=57,num_lr=5; //定义常量,存储间隔的空格数,便于修改
// ******打出第一行星号 ******
for(i=0; i<num_top_btn; i++)
printf("* ");
// * * * * 打出第二行 * * * *
printf("\n*"); //行首*
for(i=0; i<num_mid; i++) //行空格
printf(" ");
printf("*"); //行尾*
// * * * * 打出第三行 * * * *
printf("\n*"); //行首*
for(i=0; i<num_lr; i++)
printf(" ");
printf("1、新建链表<\"n\"或\"N\">");
for(i=0; i<num_lr; i++)
printf(" ");
printf("2、添加数据<\"a\"或\"A\">");
for(i=0; i<num_lr; i++)
printf(" ");
printf("*"); // 行尾*
// * * * *打出第四行 * * * *
printf("\n*"); //行首*
for(i=0; i<num_mid; i++) //行空格
printf(" ");
printf("*"); //行尾*
// * * * * 打出第五行 * * * *
printf("\n*"); //行首*
for(i=0; i<num_lr; i++)
printf(" ");
printf("3、插入数据<\"I\"或\"i\">");
for(i=0; i<num_lr; i++)
printf(" ");
printf("4、数据排序<\"P\"或\"p\">");
for(i=0; i<num_lr; i++)
printf(" ");
printf("*"); // 行尾*
// * * * * 打出第六行 * * * *
printf("\n*"); //行首*
for(i=0; i<num_mid; i++) //行空格
printf(" ");
printf("*"); //行尾*
// * * * *打出第七行 * * * *
printf("\n*"); //行首*
for(i=0; i<num_lr; i++)
printf(" ");
printf("5、显示数据<\"S\"或\"s\">");
for(i=0; i<num_lr; i++)
printf(" ");
printf("6、打开文件<\"Q\"或\"q\">");
for(i=0; i<num_lr; i++)
printf(" ");
printf("*"); // 行尾*
// * * * * 打出第八行 * * * *
printf("\n*"); //行首*
for(i=0; i<num_mid; i++) //行空格
printf(" ");
printf("*"); //行尾*
// * * * *打出第九行 * * * *
printf("\n*"); //行首*
for(i=0; i<num_lr; i++)
printf(" ");
printf("7、保存文件<\"S\"或\"s\">");
for(i=0; i<num_lr; i++)
printf(" ");
printf("8、退出系统<\"Q\"或\"q\">");
for(i=0; i<num_lr; i++)
printf(" ");
printf("*"); // 行尾*
// *****打出最后一行星号 ******
printf("\n*"); // 行首*
for(i=0; i<num_mid; i++) //中间空格
printf(" ");
printf("*\n"); //行尾*
for(i=0; i<num_top_btn; i++) //最后一行的*号
printf("* ");
// ****设置字体颜色(还原)****
printf("\n\n\n 请按相应数字或字符,选择所要进行的操作:");
SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE),15);
}