《資料結構課程設計》——活期儲蓄賬目管理系統
《資料結構課程設計》
課程題目 |
活期儲蓄賬目管理系統 |
課程編號 |
j1620102 |
學生姓名 |
張瑞祺 |
所在專業 |
資訊管理與資訊系統 |
所在班級 |
信管1132 |
學號 |
201311671231 |
任課老師 |
易學明 |
實習時間 |
2014/12/29—2015/01/11 |
設計成績 |
|
老師評語 |
完成時間: 2015 年 1 月 11 日
目錄
八、 心得體會……………………………………………………24
活期儲蓄賬目管理系統
一、 問題描述
小明是一個計算機專業top student,祝賀他畢業了。並準備到銀行參加工作。上班第一天,經理叫他編制一個實現一個活期儲蓄處理程式,算作考查。上班第一天,一定要給領導一個好印象,小明二話沒說,就答應了。如果你是小明,請完成如下題目功能:
儲戶開戶、銷戶、存入、支出活動頻繁,系統設計要求:
(1)能比較迅速地找到儲戶的帳戶,以實現存款、取款記賬;
(2)能比較簡單,迅速地實現插入和刪除,以實現開戶和銷戶的需要。
二、 問題分析
1. 建立檔案,用陣列形式儲存使用者資料,開戶時自定義使用者賬號、姓名、密碼、開戶金額。
2.使用者登入時,輸入正確的使用者賬號及密碼,完成登入後即可進行存款、取款、查詢等相關業務。
3.實現輸入使用者的賬戶名,將其全部資訊刪除,進行銷戶。
三、 資料結構設計
1. 資料結構設計
該管理系統的資料結構是線性的資料儲存結構,採用的是陣列型別的儲存結構。
2. 儲存結構設計
該儲存結構是鏈式儲存結構,本管理系統主要用線性表結構型別來儲存在“活期儲蓄賬目管理系統”中的資訊。其中,結構體由4個分量:使用者賬號名、使用者姓名、使用者密碼、開戶金額構成。
四、 演算法設計
1. 模組設計
2. 模組功能分析
開戶模組主要是輸入需要開戶的姓名,然後建立使用者賬號,輸入賬號密碼。同樣存款是根據提醒輸入需要登入的賬號,然後再輸入其密碼,之後就可以檢視其賬號上的相關資料。登入模組主要是輸入使用者賬號,
登入模組主要是輸入使用者賬號,然後對該賬號進行相關的存款、取款以及查詢餘額的操作。
銷戶模組則是輸入需要銷戶的賬號,然後從系統中銷去些賬號的相關記錄。
3. 詳細設計
(1) 資料型別定義
本系統採用鏈式結構儲存儲蓄賬目管理系統結構。結點定義如下:
struct user //使用者型別定義(賬號,姓名,密碼,餘額)
{
int id;
char name[20];
char person_password[7];
double money;
};
(2) 系統主要子程式詳細設計
1) 使用者開戶
使用者輸入需要開戶的賬戶姓名,賬戶密碼(6位數字)以及開戶金額,系統就會顯示開戶成功,並會有一個賬戶號產生(按開戶順序)。
賬戶開戶函式:add()
詳細設計:
void add()//新增使用者資料
{
printf("%30s\n","***新增使用者***");
printf("---------------------------------------------\n\n");
struct user getuser();
int count(); //函式目的:計算檔案中的記錄數目以生成自動賬號
FILE *fp;
int number;
struct user temp;
if((fp=fopen(file,"ab"))==NULL)
{
printf("cannot open file!\n");
exit(1);
}
temp=getuser(); //讀取使用者名稱
number=count();
temp.id=number+1; //生成自動賬號
fwrite(&temp,sizeof(struct user),1,fp);
printf("新增使用者成功!\n");
fclose(fp);
}
2) 使用者登入(查詢、存款、取款)
①使用者登入需要輸入賬號和密碼,系統將判斷賬戶名及密碼是否正確,若錯誤,則返回;若正確,即可進入管理系統。
使用者資訊輸入函式:getuser()
②使用者查詢餘額,需要使用者輸入賬號以及密碼,即可查詢使用者餘額。
查詢餘額函式(按照賬號查詢):void select_id()
詳細設計:
void select_id() //按照賬號查詢賬戶餘額
{
int count();
printf("%30s\n","***按照賬號查詢賬戶餘額***");
printf("%8s %15s %6s %10s\n","賬號","使用者姓名","密碼","存款餘額");
printf("---------------------------------------------\n\n");
FILE * fp;
struct user temp;
int i,maxnum;
char person_password[6];
if((fp=fopen(file,"rb"))==NULL)
{
printf("cannot open file!\n");
exit(1);
}
maxnum=count();
printf("輸入要查詢賬號:"); //判斷賬號是否在記錄中
scanf("%d",&i);
printf("輸入賬號密碼:");
scanf("%s",&person_password);
if(i<1||i>maxnum)
{
printf("你要查詢的賬號不存在!");
return;
}
while(fread(&temp,sizeof(struct user),1,fp))
if(temp.id==i&&strcmp(temp.person_password,person_password)==0)
{
printf("NO.%d %15s %6s %.2f\n",temp.id,temp.name,temp.person_password,temp.money);
}
fclose(fp);
}
③使用者存款
使用者存款,需要使用者輸入賬號以及密碼,然後輸入要存入該賬戶的金額。
存款函式:save_money()
詳細設計:
void save_money() //函式功能:按賬號存款
{
printf("%30s\n","***使用者存款業務***");
printf("---------------------------------------------\n\n");
int count();
void getperson_password(char *person_password);
FILE *fp;
int i,num,mark;
struct user *temp;
char person_password[6];
num=count(); //根據記錄數申請空間
temp=(struct user *)malloc(num*sizeof(struct user));
if((fp=fopen(file,"rb"))==NULL)
{
printf("cannot open file!\n");
exit(1);
}
for(i=0;i<num;i++) //將檔案內容存入陣列
fread(&temp[i],sizeof(struct user),1,fp);
fclose(fp);
printf("輸入要存款賬號:"); //讀取存款賬號
scanf("%d",&mark);
if(mark<1||mark>num)
{
printf("你要存款賬號不存在!");
return;
}
printf("輸入賬號密碼:");
scanf("%s",&person_password);
if((fp=fopen(file,"wb"))==NULL)
{
printf("cannot open file!\n");
exit(1);
}
for(i=0;i<num;i++)
{
if(temp[i].id==mark)
{
double money=0;
printf("輸入要存入的金額:");
scanf("%lf",&money);
if(money<=0)
{
printf("只能為正數!\n");
money=0;
}
temp[i].money +=money; //修改該使用者的資訊
}
fwrite(&temp[i],sizeof(struct user),1,fp);
}
fclose(fp);
free(temp);
printf("你存款業務已辦妥!\n");
}
④使用者取款
使用者存款,需要使用者輸入賬號以及密碼,然後輸入要取出的金額。系統將會判斷其金額是否小於賬戶上的金額,如果不小於,則提示使用者重新輸入相應的金額,或者退出。
取款函式:get_money()
詳細設計:
void get_money() //函式功能:使用者取款
{
printf("%30s\n","***使用者取款業務***");
printf("---------------------------------------------\n\n");
int count();
void getperson_password(char *person_password);
FILE *fp;
int i,num,mark;
struct user *temp;
char person_password[6];
num=count(); //根據記錄數申請空間
temp=(struct user *)malloc(num*sizeof(struct user));
if((fp=fopen(file,"rb"))==NULL)
{
printf("cannot open file!\n");
exit(1);
}
for(i=0;i<num;i++) //讀取檔案內容
fread(&temp[i],sizeof(struct user),1,fp);
fclose(fp);
printf("輸入要取款賬號:");
scanf("%d",&mark);
if(mark<1||mark>num)
{
printf("你要取款賬號不存在!");
return;
}
printf("輸入賬號密碼:");
scanf("%s",&person_password);
if((fp=fopen(file,"wb"))==NULL)
{
printf("cannot open file!\n");
exit(1);
}
for(i=0;i<num;i++) //寫方式開啟檔案,覆蓋原檔案中的內容
{
if(temp[i].id==mark)
{
double money=0;
printf("輸入要取出的金額:");
scanf("%lf",&money);
if(money<=0) //判斷使用者餘額是否足夠
{
printf("只能為正數!\n");
money=0;
}
else
if(money>temp[i].money)
{
printf("你的餘額不足!\n");
money=0;
}
temp[i].money -=money;
}
fwrite(&temp[i],sizeof(struct user),1,fp);
}
fclose(fp);
free(temp);
printf("你取款業務已辦妥!\n");
}
3)使用者顯示
直接在系統中選擇使用者顯示,即可顯示該系統的所有儲戶及其相關資訊。
系統顯示函式:display()
詳細設計:
void display() //顯示使用者資料
{
printf("%30s\n","***使用者資料顯示**");
printf("%8s %15s %6s %10s\n","賬號","使用者姓名","密碼","存款餘額");
printf("---------------------------------------------\n\n");
FILE * fp;
struct user temp;
if((fp=fopen(file,"rb"))==NULL)
{
printf("cannot open file!\n");
exit(1);
}
while(fread(&temp,sizeof(struct user),1,fp))
{
printf("NO.%d %15s %6s %.2f\n",temp.id,temp.name,temp.person_password,temp.money);
}
fclose(fp);
}
4)使用者銷戶
使用者輸入需要銷戶的賬號,系統自動判斷該賬號是否存在,然後輸入賬號密碼。若賬號與密碼相對應,且該賬戶內沒有存款,則刪除該賬號及其所有相關資訊。
銷戶函式:del()
詳細設計:
void del() //銷戶
{
int count();
printf("%30s\n","***登出賬戶***");
printf("%8s %15s %15s %10s\n","賬號","使用者姓名","密碼","存款餘額");
printf("---------------------------------------------\n\n");
FILE * fp;
struct user temp;
int i,maxnum;
if((fp=fopen(file,"rb"))==NULL)
{
printf("cannot open file!\n");
exit(1);
}
maxnum=count();
printf("輸入要銷戶賬號:"); //判斷編號是否在記錄中
scanf("%d",&i);
if(i<1||i>maxnum)
{
printf("你要查詢的賬號不存在!");
return;
}
while(fread(&temp,sizeof(struct user),1,fp)) //迴圈讀取每一條記錄
if(temp.id==i&&temp.money==0.00) //餘額為0
{temp.id=-1;//算無效帳戶
printf("NO.%d %15s %15s %.2f\n",temp.id,temp.name,temp.person_password,temp.money);
printf("%d\n",temp.id);
fwrite(&temp,sizeof(struct user),1,fp);//儲存修改
printf("賬戶銷戶成功\n");
}
fclose(fp);
}
五、 時間複雜度和空間複雜度分析
1. 時間複雜度
由於插入,刪除查詢的演算法的複雜度都是O(n),所以此演算法的複雜度O(n)。
2. 空間複雜度
是程式執行所以需要的額外消耗儲存空間,一般的遞迴演算法就要有o(n)的空間複雜度了,簡單說就是遞迴集算時通常是反覆呼叫同一個方法,遞迴n次,就需要n個空間。
六、 原始碼
#include<stdio.h>
#include<string.h>
#include<conio.h>
#include<stdlib.h>
#define file "temp.txt" //資料儲存的檔名
struct user //使用者型別定義(賬號,姓名,密碼,餘額)
{
int id;
char name[20];
char person_password[7];
double money;
};
void add()//新增使用者資料
{
printf("%30s\n","***新增使用者***");
printf("---------------------------------------------\n\n");
struct user getuser();
int count(); //函式目的:計算檔案中的記錄數目以生成自動賬號
FILE *fp;
int number;
struct user temp;
if((fp=fopen(file,"ab"))==NULL)
{
printf("cannot open file!\n");
exit(1);
}
temp=getuser(); //讀取使用者名稱
number=count();
temp.id=number+1; //生成自動賬號
fwrite(&temp,sizeof(struct user),1,fp);
printf("新增使用者成功!\n");
fclose(fp);
}
int count() //函式目的:計算檔案中的記錄總數
{
FILE *fp;
int num;
struct user temp;
num=0;
if((fp=fopen(file,"rb"))==NULL)
{
printf("cannot open file!\n");
exit(1);
}
while(fread(&temp,sizeof(struct user),1,fp))
{
num++;
}
fclose(fp);
return num;
}
struct user getuser()
void getname(char *name);
void getperson_password(char *person_password);
struct user temp;
printf("請輸入使用者姓名(字元數<20): "); //讀取相關開戶資訊
getname(temp.name);
printf("請輸入使用者密碼: ");
getperson_password(temp.person_password);
printf("輸入開戶金額:");
do{ //判斷開戶金額(>=100)
scanf("%lf",&temp.money);
fflush(stdin);
if((temp.money)<100.0)
printf("開戶金額不能小於100\n");
else
break;
printf("重新輸入開戶金額:");
}
while(1);
return temp;
}
void getname(char *name) //函式功能:讀取使用者姓名(字元數<20)
{
do{
scanf("%s",name);
fflush(stdin);
if(strlen(name)==0)
printf("姓名不能為空!\n");
else
if(strlen(name)>=20)
printf("姓名不能超過20個字元!\n");
else
break;
printf("重新輸入姓名: ");
}while(1); //迴圈以保證讀入資料有效
}
void getperson_password(char *person_password) //函式功能:讀取使用者密碼 )
{
do{
int i,mark;
char ch;
for(i=0,mark=0;;i++) //輸入有效性判斷(只能是數字)
if((ch=getchar())!='\n')
{
if(ch<='9'&&ch>='0')
person_password[i]=ch;
else
{
printf("密碼只能是數字!\n");
mark=1;
break;
}
}
else
break;
person_password[i]='\0';
if(mark==1)
continue;
if(strlen(person_password)!=6)
printf("密碼只能是6位!\n");
else
break;
printf("重新輸入密碼: ");
}while(1); //迴圈以保證讀入資料有效
}
void select_id() //按照賬號查詢賬戶餘額
{
int count();
void getperson_password(char*person_password);
printf("%30s\n","***按照賬號查詢賬戶餘額***");
printf("%8s %15s %6s %10s\n","賬號","使用者姓名","密碼","存款餘額");
printf("---------------------------------------------\n\n");
FILE * fp;
struct user temp;
int i,maxnum;
char person_password[6];
if((fp=fopen(file,"rb"))==NULL)
{
printf("cannot open file!\n");
exit(1);
}
maxnum=count();
printf("輸入要查詢賬號:"); //判斷賬號是否在記錄中
scanf("%d",&i);
printf("輸入賬號密碼:");
scanf("%s",&person_password);
if(i<1||i>maxnum)
{
printf("你要查詢的賬號不存在!");
return;
}
while(fread(&temp,sizeof(struct user),1,fp))//迴圈讀取每一條記錄判斷是否為要檢視的記錄
if(temp.id==i&&strcmp(temp.person_password,person_password)==0)
{
printf("NO.%d %15s %6s %.2f\n",temp.id,temp.name,temp.person_password,temp.money);
}
fclose(fp);
}
void display() //顯示使用者資料
{
printf("%30s\n","***使用者資料顯示**");
printf("%8s %15s %6s %10s\n","賬號","使用者姓名","密碼","存款餘額");
printf("---------------------------------------------\n\n");
FILE * fp;
struct user temp;
if((fp=fopen(file,"rb"))==NULL)
{
printf("cannot open file!\n");
exit(1);
}
while(fread(&temp,sizeof(struct user),1,fp))
{
printf("NO.%d %15s %6s %.2f\n",temp.id,temp.name,temp.person_password,temp.money);
}
fclose(fp);
}
void save_money() //函式功能:按賬號存款
{
printf("%30s\n","***使用者存款業務***");
printf("---------------------------------------------\n\n");
int count();
void getperson_password(char *person_password);
FILE *fp;
int i,num,mark;
struct user *temp;
char person_password[6];
num=count(); //根據記錄數申請空間
temp=(struct user *)malloc(num*sizeof(struct user));
if((fp=fopen(file,"rb"))==NULL)
{
printf("cannot open file!\n");
exit(1);
}
for(i=0;i<num;i++) //將檔案內容存入陣列
fread(&temp[i],sizeof(struct user),1,fp);
fclose(fp);
printf("輸入要存款賬號:"); //讀取存款賬號
scanf("%d",&mark);
if(mark<1||mark>num)
{
printf("你要存款賬號不存在!");
return;
}
printf("輸入賬號密碼:");
scanf("%s",&person_password);
if((fp=fopen(file,"wb"))==NULL) //寫方式開啟檔案,覆蓋原檔案中的內容
{
printf("cannot open file!\n");
exit(1);
}
for(i=0;i<num;i++)
{
if(temp[i].id==mark)
{
double money=0;
printf("輸入要存入的金額:");
scanf("%lf",&money);
if(money<=0)
{
printf("只能為正數!\n");
money=0;
}
temp[i].money +=money; //修改該使用者的資訊
}
fwrite(&temp[i],sizeof(struct user),1,fp);
}
fclose(fp);
free(temp);
printf("你存款業務已辦妥!\n");
}
void get_money() //函式功能:使用者取款
{
printf("%30s\n","***使用者取款業務***");
printf("---------------------------------------------\n\n");
int count();
void getperson_password(char *person_password);
FILE *fp;
int i,num,mark;
struct user *temp;
char person_password[6];
num=count(); //根據記錄數申請空間
temp=(struct user *)malloc(num*sizeof(struct user));
if((fp=fopen(file,"rb"))==NULL)
{
printf("cannot open file!\n");
exit(1);
}
for(i=0;i<num;i++) //讀取檔案內容
fread(&temp[i],sizeof(struct user),1,fp);
fclose(fp);
printf("輸入要取款賬號:");
scanf("%d",&mark);
if(mark<1||mark>num)
{
printf("你要取款賬號不存在!");
return;
}
printf("輸入賬號密碼:");
scanf("%s",&person_password);
if((fp=fopen(file,"wb"))==NULL)
{
printf("cannot open file!\n");
exit(1);
}
for(i=0;i<num;i++) //寫方式開啟檔案,覆蓋原檔案中的內容
{
if(temp[i].id==mark)
{
double money=0;
printf("輸入要取出的金額:");
scanf("%lf",&money);
if(money<=0) //判斷使用者餘額是否足夠
{
printf("只能為正數!\n");
money=0;
}
else
if(money>temp[i].money)
{
printf("你的餘額不足!\n");
money=0;
}
temp[i].money -=money;
}
fwrite(&temp[i],sizeof(struct user),1,fp);
}
fclose(fp);
free(temp);
printf("你取款業務已辦妥!\n"); }
void del() //銷戶
{
int count();
printf("%30s\n","***登出賬戶***");
printf("%8s %15s %15s %10s\n","賬號","使用者姓名","密碼","存款餘額");
printf("---------------------------------------------\n\n");
FILE * fp;
struct user temp;
int i,maxnum;
if((fp=fopen(file,"rb"))==NULL)
{
printf("cannot open file!\n");
exit(1);
}
maxnum=count();
printf("輸入要銷戶賬號:"); //判斷編號是否在記錄中
scanf("%d",&i);
if(i<1||i>maxnum)
{
printf("你要登出的賬號不存在!");
return;
}
while(fread(&temp,sizeof(struct user),1,fp)) //迴圈讀取每一條記錄,
if(temp.id==i&&temp.money==0.00) //餘額為0
{temp.id=-1;//算無效帳戶
printf("NO.%d %15s %15s %.2f\n",temp.id,temp.name,temp.person_password,temp.money);
printf("%d\n",temp.id);
fwrite(&temp,sizeof(struct user),1,fp);//儲存修改
printf("賬戶銷戶成功!\n");
}
fclose(fp);
}
void print() //函式功能:輸出介面
{
printf("%30s\n","***活期儲蓄帳目管理系統***");
printf("---------------------------------------------\n\n");
printf("%8s,%-20s\n","1","儲戶開戶");
printf("%8s,%-20s\n","2","按照賬號查詢賬戶餘額");
printf("%8s,%-20s\n","3","顯示使用者資訊");
printf("%8s,%-20s\n","4","存款");
printf("%8s,%-20s\n","5","取款");
printf("%8s,%-20s\n","6","儲戶銷戶");
printf("%8s,%-20s\n","7","退出");
printf("\n請選擇功能(1~7):");
}
void main()
{
char choose;
do{
print();
scanf(" %c",&choose); //讀取功能標號,根據標號選擇不同的函式
fflush(stdin);
system("cls");
switch(choose)
{
case '1':
add();
break;
case '2':
select_id();
break;
case '3':
display();
break;
case '4':
save_money();
break;
case '5':
get_money();
break;
case '6':
del();
break;
case '7':
exit(1);
default:
printf("對不起,你所選擇的功能不存在!\n");
}
getch(); //暫停功能(讀取任意鍵繼續)(conio.h)
system("cls"); //清除螢幕顯示(stdlib.h)
}while(1);
}<strong>
</strong>
七、 執行結果
(1) 主介面截圖
(2) 儲戶開戶
(3) 按照賬號查詢賬戶餘額
(4)顯示儲戶資訊
(5) 存款
1)存款成功
2)存款失敗
(6) 取款
1)取款成功
2)取款失敗
(7) 儲戶銷戶
1)銷戶成功
2)銷戶失敗
八、 心得體會
剛拿到這個課程設計的題目時,其實是很忐忑的,因為我的功底不好,對C++,資料結構等課程的學習比較吃力,因此上課很難跟上老師的節奏,以至於對本課程的學習一直處於迷惑的狀態,學習到的知識只能勉強應付考試。所以這次的課程設計,我也參考了網上的一些程式,但也通過自己的思考,分析,整合,理解,發現了網上現有程式的一些不足,我也對此作出了修改,加入了自己的想法。
首先要做的就是理解題目要求,分析活期儲蓄賬目管理系統的功能模組後,開始編寫程式碼。剛編寫完,在除錯過程中出現了很多錯誤,這讓我有點著急。後來我靜下心來,慢慢的分析每一個錯誤的問題所在,我發現,有些錯誤是由於我粗心大意導致的,而有些錯誤則讓我很頭疼,百思不得其解。於是我便重新翻閱書本,上網查詢資料,詢問舍友,一個一個錯誤消失,一個一個問題解決,經過好多輪的刪刪改改,終於除錯成功了!當然,這隻能說明這個程式基本滿足了題目的要求,還有很多可以改進提升的地方,但是,這對於我這個連菜鳥都算不上的初學者來說,還是很高興的!
通過這次活期儲蓄賬戶管理系統的編寫和除錯,我鞏固了有關結構體的知識及其操作,鍛鍊了實際應用能力。
演算法是程式的靈魂,在今後的學習上,我必須要將理論聯絡實際,多多上機實驗,將思路整理清晰,程式也應儘量簡潔,我一定會加油的!