彩票管理項目

花了幾天時間寫了一個比較簡單的項目,也算是自己做的第一個小項目。想的很簡單,寫的時候有些地方寫的還是很費勁,寫的時候沒有辦法聯網,現在把它放在Github中,電腦裏也不用留備份了,順便熟悉一下Git的用法,作爲菜鳥,深知路漫漫其修遠兮。

Github項目地址https://github.com/guangxyou/Simple.Lottery.Ticket.System

寫了個項目總結,放在這裏吧。

				
								彩票管理系統項目
項目需求
	詳見docx文檔			

整體框架
	詳見pdf文檔

文件結構
	1.兩個子目錄
		a)數據文件(隱藏admin文件)
		b)界面文件
	2.源程序文件(6個C文件,7個頭文件)
		a)mainsys.c
		b)user_list.c .h
		c)lott_list.c .h
		d)admin_operate.c .h
		e)user_list.c .h
		f)main_menu.c .h
		g)common.h		
		
代碼結構  接近2000行代碼
	1.兩條單鏈表
		a)用戶鏈 user_list.c
		b)彩票鏈 lott_list.c
	2.兩種用戶
		a)admin
		b)users
	3.一個C文件對應一個H文件
		common.h通用函數,頭文件都包含這個頭文件
	4. 5個結構體
	
typedef struct global	//全局變量
{
	int g_issue;		//期號
	float g_jackpot;	//獎池餘額
}GLO;

typedef struct user		//用戶鏈表
{
	int uid;
	char name[NAME_LEN];
	char passwd[PASS_LEN];
	float balance;
	struct user *next;
}USER, *pUser;		

typedef struct lott		//彩票鏈表
{
	bool sweep_flag;		//0沒有開獎,1已開獎
	bool win_flag;			//0沒有中獎,1中獎
	char name[NAME_LEN];	//購買彩票用戶的姓名
	int issue;				//彩票期號
	int uid;				//購買彩票用戶的UID
	int lott_num;			//彩票號碼
	int multiple;			//注數
	int book_amount;		//購買彩票的金額=multiple*BASE1
	
	struct lott *next;
}LOTT, *pLott;	

typedef struct w_histoty	//歷史中獎信息
{
	char name[NAME_LEN];
	int issue;
	int lott_num;
	int uid;
	int win_amount;
}WINHIS;	

typedef struct input		//登錄時結構體
{
	char name[NAME_LEN];
	char passwd[PASS_LEN];
}INPUT;		


函數:
	1.開獎(兩條鏈表,一個開獎函數完成一個鏈表的功能,將中獎信息全部寫進文件,查詢時直接讀取文件)
		void cash_award(int win_num, GLO *pglo, pUser puHead, pLott plHead);	//admin_operate.c
	2.餘額排序
		void sort_balance(pUser puHead);	//admin_operate.c
	3.模糊查找
		void fuzzy_lookup(int magic_num, char *magic_str, bool search_flag, 
		pUser puHead, pLott plHead);	//admin_operate.c
	4.搜索顯示函數(動態顯示)
		void searching(void);	//mainsys.c
	5.查找UID返回結點指針(代碼重用)
		pUser getuP_byuid(pUser puHead, int uid, pUser pMod);	//admin_operate.c
	6.重置所有信息
		void sys_reset(void);	//mainsys.c
	7.輸入判斷函數
		void operate_choice(int *num);	//mainsys.c

Bug:
	保存每期開獎信息有時不正確;		
	//admin_operate.c --> void	write_winner_file(pLott plHead, int win_num);
		
項目總結
	1.自上而下的設計模式,搭建整體框架,不必要想太細,不要過早優化;
	2.寫代碼想清楚再動手,code review之後再進行編譯;
	3.適度代碼重構(代碼複用度高),注意項目進度;
	4.加深對一些知識的理解(List/IO/動態內存分配);
	5.一個好的編輯器;
	
	6.單鏈表的結點數據域/指針域要獨立,數據域作爲一個單獨的結構體嵌入到結點;
	7.鏈表的插入操作視情況選擇插入到尾部還是頭結點之後,可以保留尾指針,一定要注意效率;
	8.定義了一個指針pa,想在堆中爲pa分配內存,無需將pa傳入被調函數中,在被調函數中聲明
	  一個同類型的指針pb, malloc分配內存之後返回pb,用pa接收.
	  錯誤1.傳入pa再返回pb,pa的確指向了堆中分配的空間,但理解錯誤;
	  原因:編譯器爲pa創建副本_pa(棧中),表面上對pa進行操作其實是對_pa的操作,而這些
	  隨着被調函數結束,_pa消亡,pa沒有任何更改;關鍵是返回值pb在起作用.
	  
	  錯誤2.傳入pa沒有返回值,pa並沒有指向分配的內存,後面調用pa可能會出錯;
	  原因:編譯器爲函數的每個參數創建副本,pa的副本爲_pa,_pa和pa指向同樣的地址,
	  如果函數體修改_pa指向的地址中的內容,pa指向的內容自然會相應的作出修改,但如果
	  在函數體內部爲參數指針動態分配內存,結果只是_pa指向的地址發生了變化,而pa指向的地址
	  中的內容沒有發生變化,沒有達到相應的目的.
	
	9.如果指針pa指向一塊堆內存,如果要對指針pa進行下移(不是偏移)時,最好創建一個臨時指針
	  ptmp = pa;否則free時可能會出錯;
	10.入參檢測(特別是指針),另外函數的返回值也要檢測,否則會有無法預知的錯誤;
	11.函數封裝,人機交互放到函數體外部,傳入參數即可;
	12.善於利用函數返回值;
	
By guangxyou 2013-8-8
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章