来吧,接下来是各个功能的函数的实现代码。
首先,程序运行时加载读入账户信息和航班信息。接下来就该读取文件了。
我把账户资料和航班信息储存在了.txt文件里
那么问题就来了,挖掘机...额,不对,应该怎么读入账户资料和航班信息?
每一行是结构体的一个成员,我读入的方式是一行一行读入。
两个读入函数代码如下:
1 //读入账户信息 2 BOOL ReadAccountData(HWND hwndDlg){ 3 4 FILE *fp; 5 6 passenger = (Passenger *)malloc(sizeof(Passenger)); //为登录账户分配内存 7 if (!passenger){ 8 MessageBox(hwndDlg, TEXT("内存申请错误!"), TEXT("错误"), MB_OK | MB_ICONERROR); 9 EndDialog(hwndDlg, 0); 10 return FALSE; 11 }//if 12 13 psglink.head = NULL; 14 psglink.tail = NULL; 15 psglink.PsgNum = 0; 16 17 if ((fp = fopen(".\AccountData.txt", "r+")) == NULL){ //打开文件 18 MessageBox(hwndDlg, TEXT("账户文件读入错误!"), TEXT("错误"), MB_OK | MB_ICONERROR); 19 EndDialog(hwndDlg, 0); 20 }//if 21 22 while (!feof(fp)){ 23 Passenger *p = (Passenger *)malloc(sizeof(Passenger)); 24 if (!p){ 25 MessageBox(hwndDlg, TEXT("内存申请错误!"), TEXT("错误"), MB_OK | MB_ICONERROR); 26 EndDialog(hwndDlg, 0); 27 return FALSE; 28 }//if 29 30 //读入账户姓名、身份证号、密码 31 if (fscanf(fp, "%s%s%s", p->Name, p->IdNum, p->PassWord) == EOF){ 32 free(p); break; 33 } 34 35 p->Next = NULL; 36 if (psglink.head == NULL) //读入第一个账户信息时,头、尾结点均指向p 37 psglink.head = p; 38 else 39 psglink.tail->Next = p; //否则,尾结点Next指向p 40 psglink.tail = p; //尾结点指向p 41 psglink.PsgNum++; //已注册账户个数 42 43 }//while 44 fclose(fp); //关闭文件 45 return TRUE; 46 }//ReadAccountData(HWND) 47 48 49 //读入航班信息 50 BOOL ReadFlightData(HWND hwndDlg){ 51 52 int flag = 0; 53 FILE *fp; 54 55 flightlink.Flight_Number = 0; 56 flightlink.head = NULL; 57 flightlink.tail = NULL; 58 59 if ((fp = fopen(".\FlightData.txt", "r")) == NULL){ //打开文件 60 MessageBox(hwndDlg, TEXT("账户文件读入错误!"), TEXT("错误"), MB_OK | MB_ICONERROR); 61 EndDialog(hwndDlg, 0); 62 }//if 63 64 while (!feof(fp)){ 65 Flight *p = (Flight *)malloc(sizeof(Flight)); 66 if (!p){ 67 MessageBox(hwndDlg, TEXT("内存申请错误!"), TEXT("错误"), MB_OK | MB_ICONERROR); 68 EndDialog(hwndDlg, 0); 69 return FALSE; 70 }//if 71 //读入航班信息 72 if (fscanf(fp, "%s%lf%s%d%d%s%s%s%s%s", 73 p->Flight_Number, 74 &p->Fare, 75 p->Discount, 76 &p->Seat_Number, 77 &p->Vacant_Seat, 78 p->Departure, 79 p->Destination, 80 p->Date, 81 p->TakeOff_Time, 82 p->Landing_Time) == EOF) 83 { 84 free(p); 85 break; 86 } 87 p->Next = NULL; 88 if (flightlink.head == NULL) //添加至链表 89 flightlink.head = p; 90 else 91 flightlink.tail->Next = p; 92 flightlink.tail = p; 93 flightlink.Flight_Number++; 94 95 }//while 96 fclose(fp); //关闭文件 97 return TRUE; 98 }//ReadFlightData()
因为开发环境是vs2013,所以编译时会报错,报错信息是大体是说fopen()函数不安全,根据提示信息,解决办法是在文件头部做如下定义:
1 #define _CRT_SECURE_NO_WARNINGS
或者是在项目->属性->c/c++->预处理器->预处理器定义,后面加上_CRT_SECURE_NO_WARNINGS就行了。
结下来又遇到问题了:程序退出把数据写入txt文件时每行末尾都会有一个 ,读入数据的时候用的是feof()函数,而feof()返回的其实是"最后一次读操作的内容",与数据库中的eof()不同,eof()读取的是当前指针位置。因此在读到文件末尾的时候,程序会多执行一次循环,为了防止这种情况,我采取的是检查fscanf()返回值的方法,在此以读入账户资料时为例:
1 //读入账户姓名、身份证号、密码 2 if (fscanf(fp, "%s%s%s", p->Name, p->IdNum, p->PassWord) == EOF){ 3 free(p); break; 4 }
然后是用户登录或注册时所用到的函数:
1 //登陆用户验证 2 BOOL AccountLogIn(HWND hwndDlg){ 3 4 int flag = 0; //flag!=0则该用户已注册,flag==0则该用户尚未注册 5 Passenger *p; 6 7 GetDlgItemText(hwndDlg, IDC_IDEDIT, passenger->IdNum, 256); //获取用户输入ID 8 GetDlgItemText(hwndDlg, IDC_PSWEDIT, passenger->PassWord, 256); //获取用户输入密码 9 10 p = psglink.head; 11 while (p){ //在用户链表查找登陆用户ID 12 if (!lstrcmp(passenger->IdNum, p->IdNum)){ 13 flag++; //该用户已注册 14 if (!lstrcmp(passenger->PassWord, p->PassWord)){ //密码匹配,登陆成功 15 lstrcpy(passenger->Name, p->Name); 16 MessageBox(hwndDlg, TEXT("登陆成功,单击确定进入程序主界面"), TEXT("登陆成功"), MB_OK | MB_ICONINFORMATION); 17 break; 18 }//if 19 else{ //密码错误,退出循环 20 MessageBox(hwndDlg, TEXT("密码错误,请重新输入"), TEXT("密码错误"), MB_OK | MB_ICONERROR); 21 return FALSE; 22 }//else 23 }//if 24 p = p->Next; 25 }//while 26 if (!flag){ //用户尚未注册 27 if (lstrlen(passenger->PassWord)==0) 28 MessageBox(hwndDlg, TEXT("请输入密码!"), TEXT("信息"), MB_OK | MB_ICONINFORMATION); 29 else 30 MessageBox(hwndDlg, TEXT("该账户尚未注册,请先注册"), TEXT("信息"), MB_OK | MB_ICONINFORMATION); 31 }//if 32 else{ //关闭登陆界面,弹出主界面 33 EndDialog(hwndDlg, TRUE); 34 if (ReadAccountOrder(hwndDlg, passenger)) //读取用户订单 35 DialogBox(hInst, MAKEINTRESOURCE(IDD_MAINDLG), NULL, (DLGPROC)MainDlgProc); 36 }//else 37 38 return TRUE; 39 }//AccountLogIn(HWND)
1 //用户注册 2 BOOL AccountRegister(HWND hwndDlg){ 3 4 GetDlgItemText(hwndDlg, IDC_IDEDIT, passenger->IdNum, 256); //获取用户输入ID 5 GetDlgItemText(hwndDlg, IDC_PSWEDIT, passenger->PassWord, 256); //获取用户输入密码 6 7 if (lstrlen(passenger->PassWord) == 0){ 8 MessageBox(hwndDlg, TEXT("请输入注册用户密码!"), TEXT("信息"), MB_OK | MB_ICONINFORMATION); 9 return FALSE; 10 } 11 12 DialogBox(hInst, MAKEINTRESOURCE(IDD_NAMEDLG), NULL, (DLGPROC)NameDlgProc); //获取新注册用户姓名 13 14 if (lstrlen(passenger->Name) == 0) 15 return FALSE; 16 17 passenger->Next = NULL; 18 19 if (psglink.head == NULL) //该注册账户为第一个账户时,头、尾结点均指向passenger 20 psglink.head = passenger; 21 else 22 psglink.tail->Next = passenger; //将新注册账户资料添加至账户链表 23 psglink.tail = passenger; //链表尾指针指向链表尾 24 psglink.PsgNum++; //注册用户数目加1 25 passenger->TicketNum = 0; 26 passenger->OrderLink.head = NULL; //乘客订单链表初始化 27 passenger->OrderLink.tail = NULL; 28 passenger->OrderLink.OrderNum = 0; 29 30 MessageBox(hwndDlg, TEXT("注册成功!请单击确定进入主界面"), TEXT("注册成功"), MB_OK | MB_ICONINFORMATION); 31 32 EndDialog(hwndDlg, TRUE); //关闭登陆界面 33 34 DialogBox(hInst, MAKEINTRESOURCE(IDD_MAINDLG), NULL, (DLGPROC)MainDlgProc); //弹出主界面 35 36 return TRUE; 37 }//AccountRegister(HWND)
点击查找、订票、退票、航班录入、修改航班信息按钮都会调用相应的函数。下面来看实现各个功能的代码:
1 //查找航班 2 BOOL SearchFlight(HWND hMainDlg){ 3 int flag1 = 0; //if(flag1==0) 出发地、目的地查询航班,else:航班号查航班 4 int flag2 = 0; 5 Flight *p; 6 TCHAR szBuffer[256] = {TEXT("