C語言檔案讀取和單鏈表的新增、刪除和排序等操作例項
/*
1、從文字檔案中匯入班級學生資訊:學號、姓名、性別、籍貫
2、將學號重複的刪除
3、顯示匯入的學生資訊
4、按學號、姓名、性別、籍貫相等和不相等查詢
5、多次查詢
6、查詢結果寫入檔案
7、VC++6.0編譯通過
//以下程式碼存為main.cpp
*/
#include <stdio.h>
#include <malloc.h>
#include <conio.h>
#include <stdlib.h>
#include <string.h>
#include <math.h>
#define CLRSCR system("cls")
#define PRINT_TITLE "\n序號\t學號\t\t姓名\t性別 \t籍貫\n"
#define PRINT_FORMAT "%d\t%s\t%s\t%s\t%s\n",i,p->stu.num,p->stu.name,p->stu.sex,p->stu.hometown
#define WRITE_FORMAT "%s\t%s\t%s\t%s\n",p->stu.num,p->stu.name,p->stu.sex,p->stu.hometown
#define READ_FORMAT "%s %s %s %s",&p->stu.num,&p->stu.name,&p->stu.sex,&p->stu.hometown
//定義學生結構體
struct student
{
char num[9];
char name[7];//三個漢字長度為6個位元組,如果不多定義一個位元組來存放字串結束符'\0',當輸出name時會把sex和hometown也輸出
char sex[3];
char hometown[7];
};
//定義單鏈表結點
typedef struct listnode
{
struct student stu;
struct listnode *next;
}node;
int MySelect(node * head,node *temp) //返回查詢到符合條件的專案數
{
int equal,N;
char CHAR[10];
printf("----------------------------------------------\n\n");
printf("查詢模式:1是相等查詢,0是不相等查詢\n");
printf("列名編號:1是學號,2是姓名,3是性別,4是籍貫\n");
printf("\n--------------------------------------------\n");
do
{
printf("\n選擇查詢模式:");//用scanf時輸入字母會錯誤 改用getche,不用scanf
equal=getche();
if((equal!='1')&&(equal!='0'))
printf("\n\t輸入錯誤\n");
}
while((equal!='1')&&(equal!='0'));
equal=equal-48;
do
{
printf("\n輸入列名編號:");
N=getche();
if(N!='1'&&N!='2'&&N!='3'&&N!='4')
printf("\n\t輸入錯誤\n");
}
while(N!='1'&&N!='2'&&N!='3'&&N!='4');
switch(N)
{
case '1': N=0;break;
case '2': N=9;break;
case '3': N=16;break;
case '4': N=19;break;
}
printf("\n輸入關鍵字:");
scanf("%s",CHAR);
int i=0,flag;
node *p,*tp=temp;
p=head->next;
while (NULL!=p)
{
flag=strcmp((char *)p+N,CHAR);
if((abs(flag)+equal)==1)//當equal為1時是相等查詢,為0時是不相等查詢
{
node *end;
end = (node *)malloc(sizeof(node));
tp->next=end;
tp=end;
tp->next=NULL;
tp->stu=p->stu;
if(i==0)
printf (PRINT_TITLE);
i++;
printf(PRINT_FORMAT);
}
p=p->next;
}
if(i==0)
printf("\n\t沒有查詢到符合條件的資訊\n");
return i;
}
void InsertSort(node *head)//學號從小到大排序
{
node *p,*q,*r,*u;
p=head->next;
head->next=NULL;
while(p!=NULL)
{
r=head;
q=head->next;
while(q!=NULL&& strcmp(q->stu.num,p->stu.num)<0) //成立則基點向後移
{
r=q;
q=q->next;
}
u=p->next;
p->next=r->next; //p->stu.num比q->stu.num小,放到q->stu.num前面
r->next=p;
p=u;//下一上節點與基點進行比較
}
}
void CheckNum(node *head)
{
/*刪除學號重複的條目*/
node *release,*p;
p=head->next;
int m=0;
while(NULL!=p->next)
{
node *p2=p;
while(NULL!=p2->next)
{
if(0==strcmp(p->stu.num,p2->next->stu.num))
{ m++;
if(m==1)
printf("\t\t以下條目因學號與前面的資訊衝突而沒有匯入\n");
printf ("%d\t%s\t%s\t%s\t%s\n",m,p2->next->stu.num,p2->next->stu.name,\
p2->next->stu.sex,p2->next->stu.hometown);
release=p2->next;
p2->next=p2->next->next;
free(release);
}
p2=p2->next;
}
p=p->next;
}
}
void FscanfFromFile(node *head)
{
char file[15];
printf("輸入待匯入的檔名:");
scanf("%s",file);
FILE *fp;
if((fp=fopen(file,"r"))==NULL)
{
printf("\n\t檔案開啟失敗,按任意鍵退出\n");
getch();
exit(0);
}
node *p=head;
while(!feof(fp))
{
node *end;
end = (node *)malloc(sizeof(node));
p->next=end;
p=end;
p->next=NULL;
fscanf(fp,READ_FORMAT);
}
printf("\n\t資訊匯入成功\n");
fclose(fp);
void CheckNum(node *head);
void InsertSort(node *head);
CheckNum(head);
InsertSort(head);
}
void ShowList(node *head)//帶頭結點的連結串列
{
node *p=head->next;
int i=0;
printf (PRINT_TITLE);
while(NULL!=p )//*****************NULL!=p 不是NULL!=p->next
{ i++;
printf (PRINT_FORMAT);
p=p->next;
}
}
void FprintfToFile(node *head)
{
char file[15];
printf("\n輸入要寫入的檔名:");
scanf("%s",file);
FILE *fp;
if((fp=fopen(file,"w+"))==NULL)
{
printf("\n\t檔案建立失敗\n");
exit(0);
}
node *p=head->next;
while(NULL!=p)
{
if(p->next==NULL)//不要最後一行的回車,這樣的話匯入該檔案時就不會有末尾的亂碼
fprintf(fp,"%s\t%s\t%s\t%s",p->stu.num,p->stu.name,p->stu.sex,p->stu.hometown);
else
fprintf(fp,WRITE_FORMAT);
p=p->next;
}
fclose(fp);
printf("\n\t資料寫入成功\n",file);//printf輸出雙引號要用轉義字\"
}
node *ClearList(node *head)
{
node *p=head->next;
while(NULL!=p)
{
node *tp=p->next;
free(p);
p=tp;
}
return head->next=NULL;
}
int AddStu(node *head)
{
node *p,*p2=head,*p3;
p=(node *)malloc(sizeof(node));
printf("依次輸入學生的學號、姓名、性別和籍貫(用空格隔開):\n");
scanf("%s %s %s %s",p->stu.num,p->stu.name,p->stu.sex,p->stu.hometown);
int flag=0;
while(NULL!=p2->next)
{ /*找出第一個比新學生的學號大的位置,將新資訊放在它前面*/
if((flag=strcmp(p->stu.num,p2->next->stu.num))<0)
{
p3=p2->next;
p2->next=p;
p->next=p3;
break;//*******
}
p2=p2->next;
}
/*如果新新增學生的學號比已有的都大,放置最末尾*/
if(flag>0)
{
p2->next=p;
p->next=NULL;
}
void CheckNum(node *head);
CheckNum(head);
printf("資訊新增成功\n");
printf("\t按任意鍵返回\n");
getche();
return 1;
}
int DeleteByNum(node *head)
{ char num[9];
int flag=1;
node *p=head,*p2;
printf("輸入要刪除資訊的學號:");
scanf("%s",num);
while(NULL!=p->next)
{
if((flag=strcmp(p->next->stu.num,num))==0)
{
p2=p->next;
p->next=p->next->next;
free(p2);
printf("刪除成功\n");
break;//***************
}
p=p->next;
}
if(flag!=0)
printf("你輸入的學號不存在\n");
printf("\t按任意鍵返回\n");
getche();
return 1;
}
int main()
{
node *head;
int i=0;
head = (node *)malloc(sizeof(node));
strcpy(head->stu.num," ");
strcpy(head->stu.hometown," ");
strcpy(head->stu.name," ");
strcpy(head->stu.sex," ");
node *temp= (node *)malloc(sizeof(node));//儲存查詢結果的頭結點
printf("歡迎使用\n");
printf("\n----------------------------------------------\n");
FscanfFromFile(head);
char charget;
do
{
printf("\n----------------------------------------------\n");
printf("\n[1]資訊顯示\n");
printf("[2]資訊查詢\n");
printf("[3]新增資訊\n");
printf("[4]刪除資訊\n");
printf("[5]退出程式\n");
do
{
charget=getch();
}
while((charget!='1')&&(charget!='2')&&(charget!='3')&&(charget!='4')&&(charget!='5'));
switch(charget)
{
case '1': ShowList(head);
printf("\n按任意鍵顯示上層操作選單\n");
getch();
break;
case '2': if(0!=MySelect(head,temp))//查詢結束不為空則進行下面的操作,為空則返回上層選單
{
char charget2;
do
{
printf("\n[1]在此基礎上繼續查詢\n");
printf("[2]將查詢結果寫入檔案\n");
printf("[3]退出本次查詢\n");
do
{
charget2=getch();
}
while((charget2!='1')&&(charget2!='2')&&(charget2!='3'));
switch(charget2)
{
case '1': if(0==MySelect(temp,temp))
{
printf("\n按任意鍵結束本次查詢\n");
getch();
charget2='3';
}
break;
case '2': FprintfToFile(temp);
charget2='3';//資料寫入後,自動結束本次查詢
break;
case '3': ClearList(temp);//結束查詢,釋放暫存查詢結果的連結串列
break;
}//end switch,結束本次查詢
}
while(charget2!='3');//如果charget2也用charget的話,在查詢中按鍵3會直接退出程式
}//end if
break;
case '3': AddStu(head);break;
case '4': DeleteByNum(head);break;
}//end switch,結束操作
}
while(charget!='5');
return 0;
}
//以下資料存為class.txt
20074879 耿同學 男 江西
20077502 王同學 男 四川
20077508 肖同學 男 四川
20077524 王同學 男 四川
20077554 謝同學 男 四川
20067049 李同學 女 四川
20067054 王同學 男 四川
20067055 張同學 男 四川
20067061 劉同學 男 四川
20067049 楊同學 女 四川
20071020 趙同學 男 四川
20071080 周同學 女 四川
20071262 吳同學 女 四川
20072672 徐同學 女 四川
20072993 孫同學 女 黑龍江
20073728 朱同學 男 四川
20074864 馬同學 女 北京
20074865 衚衕學 女 甘肅
20074866 郭同學 女 廣東
20074867 林同學 女 廣西
20074868 何同學 女 陝西
20074869 高同學 女 四川
20074870 樑同學 女 四川
20074871 鄭同學 女 四川
20074872 羅同學 女 四川
20074873 宋同學 女 四川
20074874 謝同學 男 福建
20074876 唐同學 男 黑龍江
20074877 韓同學 男 湖北
20074878 曹同學 男 湖南
20074879 許同學 男 江西
20074880 鄧同學 男 遼寧
20074881 傅同學 男 寧夏
20074882 馮同學 男 山東
20074883 曾同學 男 四川
20074884 程同學 男 四川
20074885 蔡同學 男 四川
20074886 彭同學 男 四川
20074887 藩同學 男 四川
20074888 袁同學 男 四川
20074889 於同學 男 四川
20074890 董同學 男 四川
20074891 餘同學 男 四川
20074892 蘇同學 男 四川
20074893 葉同學 男 四川
20074894 呂同學 男 四川
20074895 魏同學 男 四川
20074896 蔣同學 男 四川
20074897 田同學 男 四川
20074898 杜同學 男 四川
20074899 丁同學 男 天津
20074900 沈同學 男 浙江
20075235 姜同學 男 四川
20075658 唐同學 男 四川
20076057 王同學 女 四川
20076060 穆同學 男 四川
20076098 陳同學 女 四川
20076101 王同學 女 四川
20076120 黃同學 女 四川
20077391 魏同學 男 四川
20077499 丁同學 男 四川