如圖,資訊保存到檔案后,想要再將檔案提取出來,結果不行。


uj5u.com熱心網友回復:
看提示是對空指標進行操作了,這個例外是定位到哪個陳述句上面了?你的mess都資料結構是什么? 貼出來看看
此外,呼叫這個函式之前,head初始化了沒有呢
uj5u.com熱心網友回復:
#include<stdio.h>
#include<windows.h>
#include<stdlib.h>
#include<string.h>
#include<conio.h>
typedef struct message
{
long number;
char name[10];
char sex[5];
int year;
int month;
char add[20];
char phone[12];
char mail[20];
struct message *next;
}mess;
mess *head=NULL;
int n; //儲存人數
FILE *fp=NULL; //檔案指標
//函式
void welcome(); //歡迎界面函式
void input(); //輸入資訊函式
void output(); //輸出資訊函式
void num_search(); //按學號查詢函式
void name_search(); //按姓名查詢函式
void del(); //洗掉資訊函式
void update(); //更新資訊函式
void save(); //保存到檔案函式
void draw(); //提取檔案資訊函式
//主函式
int main()
{
char ch;
system("color F2");
welcome();
while(1)
{
printf("\n\n\n\n\n\n");
printf("\t\t\t\t\t————————————\n");
printf("\t\t\t\t\t| 1、錄入資訊 |\n");
printf("\t\t\t\t\t| 2、查看資訊 |\n");
printf("\t\t\t\t\t| 3、按學號排序并查詢 |\n");
printf("\t\t\t\t\t| 4、按姓名查詢 |\n");
printf("\t\t\t\t\t| 5、洗掉資訊 |\n");
printf("\t\t\t\t\t| 6、資訊修改 |\n");
printf("\t\t\t\t\t| 7、保存資訊 |\n");
printf("\t\t\t\t\t| 8、提取資訊 |\n");
printf("\t\t\t\t\t| 9、退出系統 |\n");
printf("\t\t\t\t\t————————————\n");
scanf("%d",&ch);
switch(ch)
{
case 1:input();break;
case 2:output();break;
case 3:num_search();break;
case 4:name_search();break;
case 5:del();break;
case 6:update();break;
case 7:save();break;
case 8:draw();break;
case 9:exit(1);break;
default:
printf("\n請輸入有效數字\n");
system("pause");
system("cls");
}
}
return 0;
}
//歡迎界面函式
void welcome()
{
printf("\n\n\n\n");
printf("\t\t\t\t\t*************************\n");
printf("\t\t\t\t\t*歡迎進入學生資訊管理系統*\n");
printf("\t\t\t\t\t*************************\n");
system("pause");
system("cls");
}
//輸入資訊函式
void input()
{
int i;
mess *p=NULL,*p1=NULL;
system("cls");
i=1;
printf("請輸入要錄入的學生個數:");
scanf("%d",&n);
system("pause");
system("cls");
head=(mess*)malloc(sizeof(mess)); //創建頭結點
p1=head;
do //頭插法創建鏈表
{
p=(mess*)malloc(sizeof(mess));
p1->next=p;
p1=p;
printf("請輸入第%d個學生的學號:",i);
scanf("%ld",&p->number);
printf("\n請輸入第%d個學生的姓名:",i);
scanf("%s",&p->name);
printf("\n請輸入第%d個學生的性別:",i);
scanf("%s",&p->sex);
printf("\n請輸入第%d個學生的出生年:",i);
scanf("%d",&p->year);
printf("\n請輸入第%d個學生的出生月:",i);
scanf("%d",&p->month);
printf("\n請輸入第%d個學生的地址:",i);
scanf("%s",&p->add);
printf("\n請輸入第%d個學生的電話:",i);
scanf("%s",&p->phone);
printf("\n請輸入第%d個學生的E-mail:",i);
scanf("%s",&p->mail);
printf("");
printf("");
system("pause");
system("cls");
i++;
}
while(i<=n);
p1->next=NULL;
head=head->next;
}
//輸出資訊函式
void output()
{
mess *p;
p=head;
system("cls");
printf("學號\t");
printf("姓名\t");
printf("性別\t");
printf("出生年月\t");
printf("地址\t\t");
printf("\t電話\t\t");
printf("E-mail\t\t\n");
while(p!=NULL)
{
printf("%ld\t",p->number);
printf("%s\t",p->name);
printf("%s\t",p->sex);
printf("%d%d\t",p->year,p->month);
printf(" %s\t",p->add);
printf("%s\t",p->phone);
printf("%s\t\n",p->mail);
p=p->next;
}
system("pause");
system("cls");
}
//按學號查詢函式
void num_search()
{
mess*p,*p1;
int _year,_month,k=0,i=1;
long _number;
char _phone[12];
char _name[10],_sex[5],_add[20],_mail[20];
p=head;
p1=p;
if(p!=NULL&&p->next!=NULL)
{
while(i!=0)
{
while(p1->next!=NULL)
{
if(p1->number>p1->next->number) //冒泡排序法
{
_number=p1->number;
p1->number=p1->next->number;
p1->next->number=_number;
strcpy(_name,p1->name);
strcpy(p1->name,p1->next->name);
strcpy(p1->next->name,_name);
strcpy(_sex,p1->sex);
strcpy(p1->sex,p1->next->sex);
strcpy(p1->next->sex,_sex);
_year=p1->year;
p1->year=p1->next->year;
p1->next->year=_year;
_month=p1->month;
p1->month=p1->next->month;
p1->next->month=_month;
strcpy(_add,p1->add);
strcpy(p1->add,p1->next->add);
strcpy(p1->next->add,_add);
strcpy(_phone,p1->phone);
strcpy(p1->phone,p1->next->phone);
strcpy(p1->next->phone,_phone);
strcpy(_mail,p1->mail);
strcpy(p1->mail,p1->next->mail);
strcpy(p1->next->mail,_mail);
k++;
}
p1=p1->next;
}
p1=p;
if(k>0)
k=0;
else
i=0;
}
printf("排序成功。\n");
system("cls");
system("pause");
}
else
{
printf("資料只有一個或者為空,排序失敗\n");
system("pause");
system("cls");
}
}
//按姓名查詢函式
void name_search()
{
char name1[10];
mess*p;
p=head;
system("cls");
printf("請輸入你想查詢的學生姓名:");
scanf("%s",&name1);
printf("\n");
printf("學號\t");
printf("姓名\t");
printf("性別\t");
printf("出生年月\t");
printf("地址\t\t");
printf("電話\t\t");
printf("E-mail\t\t\t\n");
while(p!=NULL)
{
if(strcmp(p->name,name1)==0)
{
printf("%ld\t",p->number);
printf("%s\t",p->name);
printf("%s\t",p->sex);
printf("%d%d\t",p->year,p->month);
printf("%s\t",p->add);
printf("%s\t",p->phone);
printf("%s\t\n",p->mail);
p=p->next;
}
else
p=p->next;
}
system("pause");
system("cls");
}
//洗掉資訊函式
void del()
{
mess*p,*p1;
char name1[10];
system("cls");
printf("請輸入學生姓名:");
scanf("%s",&name1);
p=head;
p1=head;
if(p==NULL)
{
printf("沒有資料,洗掉失敗。\n");
system("pause");
return;
}
while(p!=NULL)
{
if(strcmp(p->name,name1)==0)
{
break;
}
p1=p;
p=p->next;
}
if(p==head)
{
head=p->next;
free(p);
printf("洗掉成功。\n");
system("pause");
system("cls");
return;
}
if(p==NULL)
{
printf("查無此人。\n");
system("pause");
system("cls");
return;
}
else
{
p1->next=p->next;
free(p);
}
system("pause");
system("cls");
return;
}
void update()
{
char name1[12];
char ch1;
mess *p=head;
system("cls");
printf("輸入所需修改資訊學生的姓名:");
scanf("%s",&name1);
getchar();
if(p==NULL)
{
printf("修改失敗,沒有資料。\n");
system("pause");
system("cls");
return;
}
while(p!=NULL)
{
if(strcmp(name1,p->name)==0)
{
printf("學號\t");
printf("姓名\t");
printf("性別\t");
printf("出生年月\t");
printf("地址\t\t");
printf("\t電話\t\t");
printf("E-mail\t\t\n");
printf("%ld\t",p->number);
printf("%s\t",p->name);
printf("%s\t",p->sex);
printf("%d%d\t",p->year,p->month);
printf(" %s\t",p->add);
printf("%s\t",p->phone);
printf("%s\t\n",p->mail);
break;
}
p=p->next;
}
if(p==NULL)
{
printf("沒有找到該資料,修改失敗。\n");
system("pause");
system("cls");
return;
}
else
{
do
{
printf("\n\n1、修改學號。\n");
printf("2、修改性別。\n");
printf("3、修改出生年份。\n");
printf("4、修改出生月份。\n");
printf("5、修改地址。\n");
printf("6、修改電話。\n");
printf("7、修改E-mail。\n");
printf("8、修改完成。\n請輸入:");
ch1=getch();
switch(ch1)
{
case 1:
printf("請輸入學號:");
scanf("%ld",&p->number);
system("pause");
system("cls");
break;
case 2:
printf("請輸入性別:");
scanf("%s",&p->sex);
system("pause");
system("cls");
break;
case 3:
printf("請輸入出生年份:");
scanf("%d",&p->year);
system("pause");
system("cls");
break;
case 4:
printf("請輸入出生月份:");
scanf("%d",&p->month);
system("pause");
system("cls");
break;
case 5:
printf("請輸入地址:");
scanf("%s",&p->add);
system("pause");
system("cls");
break;
case 6:
printf("請輸入電話:");
scanf("%s",&p->phone);
system("pause");
system("cls");
break;
case 7:
printf("請輸入E-mail:");
scanf("%s",&p->mail);
system("pause");
system("cls");
break;
case 8:
system("cls");
printf("修改完成。\n");
system("pause");
system("cls");
return;
default:
printf("請輸入有效數字。\n");
system("pause");
system("cls");
}
}while(ch1!=8);
}
}
//保存到檔案函式
void save()
{
mess *p=head;
fp=fopen("d:\\stu.txt","ab+"); //<<--
system("cls");
if(head==NULL) //<<--
{
printf("保存失敗,資訊為空。");
system("pause");
system("cls");
return;
}
while(p!=NULL)
{
fprintf(fp,"%ld\t%s\t%s\t%d%d\t %s\t%s\t%s\t\r\n",
p->number,p->name,p->sex,p->year,p->month,p->add,
p->phone,p->mail);
p=p->next;
}
fclose(fp);
printf("保存成功。\n");
system("pause");
system("cls");
return;
}
//提取檔案資訊函式
void draw()
{
mess *p;
system("cls");
fp=fopen("d:\\stu.txt","rb+"); //<<--
if(fp==NULL)
{
printf("打開失敗,檔案不存在。\n");
fclose(fp);
system("pause");
system("cls");
return;
}
fseek(fp,0,SEEK_SET);
while(!feof(fp))
{
p=(mess*)malloc(sizeof(mess));
fscanf(fp,"%ld %s %s %d %d %s %s %s\r\n",
&p->number,p->name,p->sex,&p->year,&p->month,p->add,
p->phone,p->mail);
p->next=head;
head=p;
}
fclose(fp);
system("pause");
system("cls");
return;
}
uj5u.com熱心網友回復:
這個我是用vs編譯的,看不出定位到哪里,源代碼如下
uj5u.com熱心網友回復:
fp=fopen("d:\\stu.txt","rb+"); //<<--這個是二進制打開
fscanf(fp,"%ld %s %s %d %d %s %s %s\r\n",
這個是文本讀
uj5u.com熱心網友回復:
那fprintf呢? 能不能幫我解釋一下這幾個,我有點懵
uj5u.com熱心網友回復:
fp=fopen("d:\\stu.txt","r+");//把比去掉就可以。兩種方式各有優缺點,以二進制保存結構,浪費空間。
以 文本方式保存結構,效率低。
uj5u.com熱心網友回復:
沒有windows環境,沒法測驗下面這個寫法有問題
while(!feof(fp))
{
p=(mess*)malloc(sizeof(mess));
fscanf(fp,"%ld %s %s %d %d %s %s %s\r\n",
&p->number,p->name,p->sex,&p->year,&p->month,p->add,
p->phone,p->mail);
p->next=head;
head=p;
}
feof要完成一次讀不出來資料的fscanf之后, 才會得到這個狀態
所以,你會在最后弄出個無效的p節點,并且成了了head
如果你的鏈表是有空頭的,這么做剛好是對的,但是你的鏈表是沒有空頭的
draw應該是從磁盤讀取鏈表, 那么head應該在讀取之前設定為NULL然后再執行讀取操作
否則,原來的鏈表掛在了這個新讀入的鏈表都后面了
上述兩個問題都不是空指標造成的原因。
最好還是能定位報錯的位置再來看--沒windows環境,要除錯還得改代碼去
uj5u.com熱心網友回復:
不對啊你這個input函式里面就一堆問題, scanf獲取名字,性別,地址,電話等字串的時候,引數怎么還再取地址呢
printf("\n請輸入第%d個學生的姓名:",i);
scanf("%s",&p->name);
應該是
scanf("%s",p->name);
namesearch
del
差不多每個函式都有類似的問題, 這個前面的步驟你是怎么執行過去的呢???
uj5u.com熱心網友回復:
運行的起來,就沒發現這個
uj5u.com熱心網友回復:
head全域變數一開始就是NULL呀,那個feof一次讀不出來資料的fscanf是什么意思uj5u.com熱心網友回復:
把b去掉還是不行
uj5u.com熱心網友回復:
head一開始是NULL,但是你的錄入操作等,折騰后就不是NULL了還有那個n,表示有多少個, 這個要和head一樣初始化為0
draw讀取到時候,也要對n進行同步,才能計數
你的這個資料檔案,你打開看了沒有,里面都是什么樣子的資料,確定正確嗎?
很是懷疑呢, 前面的input都是錯的, 后面的save怎么可能正確執行下來的
如果save執行的不對, 比如,寫入的name的長度超長,超過了陣列的大小, 讀取進來必然會把mess變數撐死
現在是嚴重的懷疑你的資料檔案就不對
還有就是你怎么確定的問題是出在draw函式里面的呢?
你可以在draw函式上做一點改造:
printf("\nStart reading data from file ......\n")
while(!feof(fp))
{
p=(mess*)malloc(sizeof(mess));
fscanf(fp,"%ld %s %s %d %d %s %s %s\r\n",
&p->number,p->name,p->sex,&p->year,&p->month,p->add,
p->phone,p->mail);
printf("%d %s\n", p->num, p->name);
p->next=head;
head=p;
}
printf("\n------Finish--------\n");
看看螢屏輸出了什么
uj5u.com熱心網友回復:
那你把這個檔案打開,看看里面有內容嗎。fscanf(fp,"%ld %s %s %d %d %s %s %s\n"
去掉\r
uj5u.com熱心網友回復:
void save(){
mess *p=head;
fp=fopen("d:\\stu.txt","ab+");
前面保存的就不對。
難道用二進制打開,可以用文本方式讀寫嗎?
uj5u.com熱心網友回復:
哦哦,我想起來了,這個問題我曾經問過。在linux下只有一種檔案格式。at等同于ab,這個原始碼應該是linux上的所以沒問題。
uj5u.com熱心網友回復:
檔案里是我輸入的內容
uj5u.com熱心網友回復:
輸出了列印的那兩句英文
uj5u.com熱心網友回復:
fprintf(fp, "%ld\t%s\t%s\t%d\t%d\t%s\t%s\t%s\t\r\n",這里錯了。
uj5u.com熱心網友回復:
void save(){
mess* p = head;
fp = fopen("d:\\stu.txt", "ab+"); //<<--
system("cls");
if (head == NULL) //<<--
{
printf("保存失敗,資訊為空。");
system("pause");
system("cls");
return;
}
while (p != NULL)
{
fprintf(fp, "%ld\t%s\t%s\t%d\t%d\t%s\t%s\t%s\t\r\n",
p->number, p->name, p->sex, p->year, p->month, p->add,
p->phone, p->mail);
p = p->next;
}
fclose(fp);
printf("保存成功。\n");
system("pause");
system("cls");
return;
}
你資料沒有保存對
uj5u.com熱心網友回復:
資料錯了
uj5u.com熱心網友回復:
draw函式啟動的時候,螢屏輸出什么了?Start reading data from file ......
1 陳
------Finish--------
還是什么也木有
uj5u.com熱心網友回復:
while中間, 在scanf之后,還有一個printf呢,那個有沒有輸出內容?如果這里都可以正常輸出,那么錯誤也沒有發生在draw函式里面啊
你的那個例外,是執行到哪兒出現的
uj5u.com熱心網友回復:
螢屏輸出的就是你說的這個
uj5u.com熱心網友回復:
我有點暈了。現在是資料儲存位置錯了,提取沒有問題uj5u.com熱心網友回復:
這里修改了哪里
uj5u.com熱心網友回復:
用二進制讀寫uj5u.com熱心網友回復:
用二進制讀寫,調整一下輸出的指標的起始位置uj5u.com熱心網友回復:
看了好幾遍也沒發現無誤
uj5u.com熱心網友回復:
厲害啊 我的哥00
uj5u.com熱心網友回復:
是不是突破了64k檔案長度限制?有多少資料項?通常c語言檔案長度不大于64k,否則會出錯。需要使用長檔案時,需要使用專用的頭檔案。uj5u.com熱心網友回復:
fprintf(fp,"%ld\t%s\t%s\t%d%d\t %s\t%s\t%s\t\r\n",p->number,p->name,p->sex,p->year,p->month,p->add,
p->phone,p->mail);
p=p->next;
愁死個人, 這樣寫,兩個數字都挨在一起了。 一個2一個3, 你這樣寫輸出的是23, 回頭fscanf能分出來才見鬼了呢
就一個輸出整那么多沒有的干嘛呢
這種資料檔案你還講究個什么排版啊, 老老實實的去寫:
fprintf(fp,"%ld %s %s %d %d %s %s %s\n", \
p->number, \
p->name, p->sex, \
p->year, p->month, \
p->add, p->phone, p->mail);
uj5u.com熱心網友回復:
和我一樣 都在寫成績管理系統 我在檔案的時候困了老半天uj5u.com熱心網友回復:
你結構體下面 mess *head 要用malloc 生成 不能直接這樣轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/124467.html
標籤:C語言
