(考完再来更新。。。)o(╥ - ╥)o
文件介绍
mymac.h文件:
main.c文件:
只有一个入口函数 main(),实现两个功能:
- ① 初始化:
初始化3个全局变量;初始化用户信息(一定要有管理员)和列车信息,即在数据库中增加几条Person表和Train表的记录- ② 进入系统的交互界面并控制页面跳转:
从3个界面中的主界面进入,由此开始在3个界面中切换database.c文件:
mainWindow.c文件:
manager.c文件:
user.c文件:
代码
仅展示框架图中的代码结构,完整代码访问 github (还没传完。。。)
main.c(全)
#include "mymac.h"
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <windows.h>
int user_num; // 当前用户登录状态
int manager_num; // 当前管理员登录状态
int seed_adj; // 随机种子调节因子
int main()
{
/** 1.初始化 **/
printf("初始化中,请稍后...\n");
user_num = 0;
manager_num = 0;
seed_adj = 0;
initialTrain(); // 火车x4
initialPerson(); // 乘客x3 管理员x1
system("cls");
// 避免多次跳转页面程序嵌套,由主程序控制页面跳转
/** 2.从主界面开始进入交互界面 控制页面跳转**/
int forw = -1; // 是否发生页面跳转
forw = mainMenu();
while(1){
if(forw == 0){
forw = mainMenu(); //跳转到主界面
}if(forw == 1){
forw = userMenu(); //跳转到用户界面
}else if(forw == 2){
forw = managerMenu(); //跳转到管理员界面
}else{
break;
}
}
return 0;
}
mymac.h(全)
/************************** 常用数值 *************************/
#ifndef PERSON_MAX
#define PERSON_MAX 100 //数据库中乘客记录不超过100
#endif
#ifndef TRAIN_MAX
#define TRAIN_MAX 20 //数据库中火车记录不超过20
#endif
#ifndef TICKIT_MAX
#define TICKIT_MAX 100 //数据库中购票记录不超过100
#endif
#ifndef STATION_LENGTH_MAX
#define STATION_LENGTH_MAX 40 //一辆火车总站点数不大于40字节
#endif
#ifndef NAME_LENGTH_MAX
#define NAME_LENGTH_MAX 30 //名字(站点名或人名)不大于30字节
#endif
#ifndef ID_LENGTH_MAX
#define ID_LENGTH_MAX 19 //身份证不大于18字节
#endif
#ifndef GENDER_LENGTH_MAX
#define GENDER_LENGTH_MAX 4 //性别 不大于4字节
#endif
#ifndef TEL_LENGTH_MAX
#define TEL_LENGTH_MAX 12 //电话不大于11字节
#endif
#ifndef CODE_LENGTH_MAX
#define CODE_LENGTH_MAX 7 //密码 不大于6字节
#endif
#ifndef SET_SEED
#define SET_SEED srand(time(NULL)+seed_adj++) //密码 不大于6字节
#endif
/************************** 带参数宏 *************************/
// 命令提示语句
#ifndef COMMAND
#define COMMAND(s) color(2); printf(s); printf(">> "); color(15);
#endif
// 标题
#ifndef TITLE
#define TITLE(s) color(6); printf(s); color(15);
#endif
// 提示信息
#ifndef HINT
#define HINT(s) color(3); printf(s); color(15);
#endif
/************************** Person, Tickit, Train 3种结构体 *************************/
typedef struct _Person
{
int person_num; //乘客编号-主键
char person_name[NAME_LENGTH_MAX]; //乘客姓名
char id[ID_LENGTH_MAX]; //18位身份证号
char gender[GENDER_LENGTH_MAX]; //性别
char tel[TEL_LENGTH_MAX]; //号码,最多11位
char code[CODE_LENGTH_MAX]; //密码,最多6位
struct _Person* next; //便于链表操作
}Person;
typedef struct _Tickit
{
int tickit_num; //票号-主键
int person_num; //用户编号
int train_num; //火车编号
// int seat_num; //座位号
int start; //起点站号
int end; //终点站号
double price; //票价
struct _Tickit* next; //便于链表操作
}Tickit;
typedef struct _Train
{
int train_num; //火车编号
int sta_count; //总站点数,不大于30
char train_name[NAME_LENGTH_MAX]; //火车名
char sta_name[STATION_LENGTH_MAX][NAME_LENGTH_MAX]; //站点名称
double adj_sta_price[STATION_LENGTH_MAX]; //相邻2站之间的票价
int adj_tic_num[STATION_LENGTH_MAX]; //相邻2站之间的余票,初始值200
struct _Train* next; //便于链表操作
}Train;
database.c(不全)
太长不贴了,仅展示person表增删改查部分,大同小异
#include "mymac.h"
#include <stdio.h>
#include <time.h>
#include <stdlib.h>
#include <string.h>
#include <windows.h>
extern int manager_num;
extern int user_num;
extern int seed_adj;
/************************** 对Person表的增删改查 *************************/
/*
新增乘客信息
遍历文件查看 身份证号 是否已经存在
不存在则在文件末尾插入新乘客信息,在文件尾操作因此不需要存入链表
存在则返回新增失败
*/
int addPerson(char * person_name, char* id, char* gender, char* tel, char* code)
{
//打开person文件; 任何地方判断出错则返回false
FILE* fp = fopen("person.txt", "ab+"); // a+可读可写
if (fp == NULL) {
return 0; //非0即true
}
Person person; // 缓冲区
// 乘客信息不能相同 检查是否已经存在-> 存在则不用增加
while (!feof(fp)) {
if (fread(&person, sizeof(Person), 1, fp) != 0) {
if (strcmp(person.id, id) == 0) { //身份证号相同
printf("乘客信息已存在\n");
fclose(fp);
return 0; // 乘客信息已存在
}
}
else {
// printf("fread读取为0\n");
}
}
//乘客不存在,新增乘客信息
//新增Person
SET_SEED;
person.person_num = rand();
strcpy(person.person_name, person_name);
strcpy(person.id, id);
strcpy(person.gender, gender);
strcpy(person.tel, tel);
strcpy(person.code, code);
//在文件末尾写入Person节点
fseek(fp, 0, SEEK_END);
fwrite(&person, sizeof(Person), 1, fp);
fclose(fp);
return 1;
}
/*
删除一个乘客信息
同时对tickit表进行对应更改
输入:乘客编号 或者 乘客id
遍历文件,查看乘客是否存在
在文件中间进行操作,因此将所有数据存入动态链表
存在,则删除节点 tag = 1
不存在,则无操作 tag =0
*/
int delPerson(int person_num)
{
//打开person文件; 覆盖式写入; 任何地方判断出错则返回false
FILE* fp = fopen("person.txt", "rb");
if (fp == NULL) {
return 0; //非0即true
}
Person person_buff;
Person* L, * p;
int tag = 0; // 找到目标节点tag为1
L = (Person*)malloc(sizeof(Person));
L->next = NULL;
while (!feof(fp)) {
if(fread(&person_buff, sizeof(Person), 1, fp) > 0){
// printf("\n 本次比对 buff_num=%d, person_num=%d\n\n", person_buff.person_num, person_num);
if (person_buff.person_num == person_num) {
tag = 1; //目标节点不读出
}
else {
// 新增结点
p = (Person*)malloc(sizeof(Person));
p->person_num = person_buff.person_num;
strcpy(p->id, person_buff.id);
strcpy(p->person_name, person_buff.person_name);
strcpy(p->gender, person_buff.gender);
strcpy(p->tel, person_buff.tel);
strcpy(p->code, person_buff.code);
// 插入链表;减少一个指针,使用头插法
p->next = L->next;
L->next = p;
}
}else{
break;
}
}
fclose(fp);
if (tag == 1) { //删除目标节点
// if (delTickit(2, person_num)) { //更新Tickit表成功的前提下,更新Person表
delTickit(2, person_num);
//覆盖式打开文件
FILE* fp = fopen("person.txt", "wb");
if (fp == NULL) {
return 0; //非0即true
}
// 文件头
fseek(fp, 0, SEEK_SET);
p = L->next;
while (p) {
fwrite(p, sizeof(Person), 1, fp);
p = p->next;
}
// 关闭文件
fclose(fp);
return 1;
}
free(p);
return 0;
}
/*
更新一个乘客信息
只能更新 号码 密码 2项
char tel[12]; //号码,最多11位
char code[7]; //密码,最多6位
*/
int updPerson(int person_num, int op)
{
//打开person文件; 覆盖式写入; 任何地方判断出错则返回false
FILE* fp = fopen("person.txt", "rb");
if (fp == NULL) {
printf("file open failure\n");
return 0; //非0即true
}
char* parastr;
Person person_buff;
Person* L, * p;
int tag = 0; // 更新成功tag为1
L = (Person*)malloc(sizeof(Person));
L->next = NULL;
while (!feof(fp)) {
// printf("finish2\n");
if(fread(&person_buff, sizeof(Person), 1, fp) > 0){
p = (Person*)malloc(sizeof(Person));
if (person_buff.person_num == person_num) {
if (tag == 0 && op == 1) { // 更改电话
COMMAND("请输入新11位电话号码:");
parastr = (char*)malloc(sizeof(char) * 12);
scanf("%s", parastr);
if(strlen(parastr) != 11){
printf("格式错误\n");
break;
}
strcpy(p->tel, parastr);
strcpy(p->code, person_buff.code);
tag = 1;
}
else if (tag == 0 && op == 2) { //更改密码
COMMAND("请输入新6位密码:");
parastr = (char*)malloc(sizeof(char) * 7);
scanf("%s", parastr);
if(strlen(parastr) != 6){
printf("格式错误\n");
break;
}
strcpy(p->tel, person_buff.tel);
strcpy(p->code, parastr);
tag = 1;
}
}
else {
strcpy(p->tel, person_buff.tel);
strcpy(p->code, person_buff.code);
}
// 另4项不可改变
p->person_num = person_buff.person_num;
strcpy(p->person_name, person_buff.person_name);
strcpy(p->id, person_buff.id);
strcpy(p->gender, person_buff.gender);
p->next = L->next;
L->next = p;
}else{
break;
}
}
fclose(fp);
if (tag == 1) { //更新成功,将新的链表覆盖式写入文件
// 打开文件
fp = fopen("person.txt", "wb");
if (fp == NULL) {
return 0; //非0即true
}
// 写入文件
fseek(fp, 0, SEEK_SET);
p = L->next;
while (p) {
fwrite(p, sizeof(Person), 1, fp);
p = p->next;
}
// 关闭文件
fclose(fp);
return 1;
}
else {// 更新失败,不写回文件
return 0;
}
}
/*
* 仅管理员有此权限
* 4种查询方式
int person_num; //乘客编号-主键
char person_name[20]; //乘客姓名
char id[19]; //18位身份证号
char tel[12]; //号码,最多11位
*/
int* qurPerson(int op)
{
//打开person文件; 覆盖式写入; 任何地方判断出错则返回false
FILE* fp = fopen("person.txt", "rb");
if (fp == NULL) {
return NULL; //非0即true
}
int tag = 0; // 查询成功tag=1
int* person_nums = (int*)calloc(PERSON_MAX, sizeof(int)); //初始化为0
int cur = 0;
// 4种查询方式需键入的值
int person_num = 0; //乘客编号-主键
char person_name[NAME_LENGTH_MAX]; //乘客姓名
char id[ID_LENGTH_MAX]; //18位身份证号
char tel[TEL_LENGTH_MAX]; //号码,最多11位
Person* p = (Person*)malloc(sizeof(Person));
// 根据不同方式定位结点
switch (op) {
case 1: /*根据乘客编号查询*/
COMMAND("请输入待查询的乘客编号")
scanf("%d", &person_num);
while (!feof(fp)) {
if(fread(p, sizeof(Person), 1, fp) > 0){
if (p->person_num == person_num) {
person_nums[cur++] = p->person_num;
tag = 1;
break;
}
}else{
break;
}
}
break;
case 2: /*根据姓名查询*/
COMMAND("请输入待查询的乘客姓名")
scanf("%s", person_name);
while (!feof(fp)) {
if(fread(p, sizeof(Person), 1, fp) > 0){
if(strcmp(p->person_name, person_name) ==0){
person_nums[cur++] = p->person_num;
tag = 1;
}
}else{
break;
}
}
break;
case 3: /*根据身份证查询*/
COMMAND("请输入待查询的乘客身份证件号码");
scanf("%s", id);
while (!feof(fp)) {
if(fread(p, sizeof(Person), 1, fp) > 0){
if (strcmp(p->id, id) == 0) {
person_nums[cur++] = p->person_num;
tag = 1;
break;
}
}else{
break;
}
}
break;
case 4: /*根据手机号码查询*/
COMMAND("请输入11位手机号");
scanf("%s", tel);
while (!feof(fp)) {
if(fread(p, sizeof(Person), 1, fp) > 0){
if (strcmp(p->tel, tel) == 0) {
person_nums[cur++] = p->person_num;
tag = 1;
break;
}
}else{
break;
}
}
break;
default:
break;
}
fclose(fp);
if (tag == 1) {
return person_nums;
}
return NULL;
}
mainWindow.c (全)
#include "mymac.h"
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <windows.h>
extern int user_num;
extern int manager_num;
extern int seed_adj; // 随机种子调节因子
void color(short x) //自定义函根据参数改变颜色
{
if (x >= 0 && x <= 15)//参数在0-15的范围颜色
SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), x); //只有一个参数,改变字体颜色
else//默认的颜色白色
SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), 7);
}
void exitInter()
{
HINT("\n\n已退出,感谢使用!\n\n");
system("pause");
exit(-1);
}
/*
主界面
*/
int mainMenu()
{
system("cls");
HINT("\n欢迎使用火车预定系统!\n");
// printf("this is the function of making mainmenu\n");
printf("****************************************************\n");
printf("*** ");TITLE("系统主页");printf(" ***\n");
printf("****************************************************\n");
printf("\n》主界面》\n");
printf("****************************************************\n");
printf("* 0.退出 *\n");
printf("* 1.用户模式 *\n");
printf("* 2.管理员模式 *\n");
printf("****************************************************\n\n");
int forw = -1;
while(1){
COMMAND("请输入数字选择【模式操作】");
scanf("%d", &forw);
if(forw == 0){
exitInter();
break;
}else if(forw == 1 || forw == 2){
break;
}else{
printf("无相应操作数字,请重试\n\n");
}
}
return forw;
}
user.c (不全)
仅展示主要函数 ==int userMenu() ==
#include "mymac.h"
#include <stdio.h>
#include <time.h>
#include <stdlib.h>
#include <string.h>
#include <windows.h>
extern int manager_num;
extern int user_num;
extern int seed_adj;
/*
用户界面
*/
int userMenu()
{
system("cls");
int forw = -1;
if(user_num == 0){ //无登录状态,需要先登录
printf("****************************************************\n");
printf("*** ");TITLE("用户模式");printf(" ***\n");
printf("****************************************************\n");
int opr;
// 合法登录才能使用功能
HINT("您需要登录账号来使用系统(无账号请先注册)\n\n")
while(1){
printf("\n》主界面》用户模式》用户登录\n");
printf("****************************************************\n");
printf("* 0.返回主界面 *\n");
printf("* 1.登录 *\n");
printf("* 2.注册 *\n");
printf("****************************************************\n\n");
COMMAND("请输入数字选择【登录操作】");
scanf("%d", &opr);
if(opr == 0){
return 0; //跳转主界面
}else if(opr == 1){
signIn();
break;
}else if(opr == 2){
signUp();
break;
}else{
printf("无相应操作数字,请重试\n\n");
}
}
}
// 进行操作
system("cls");
Person *p = getPerson(user_num);
HINT("\n欢迎用户");TITLE(p->person_name);
HINT("! 您的系统编号是");printf("%d\n", p->person_num);
printf("******************************************************************************************\n");
printf("*** ");TITLE("用户模式");printf(" ***\n");
printf("******************************************************************************************\n");
int opr;
while(1){
printf("\n》主界面》用户模式》用户操作》\n");
printf("******************************************************************************************\n");
printf("* 0.返回主界面 1.账号设置 2.车次信息查询 3.购票和退改 4.我的主页 *\n");
printf("* >注销账号 >根据车次编号查询 >购票 >我的资料 *\n");
printf("* >更改密码 >根据车次名查询 >退票 >我的订单 *\n");
printf("* >更改电话号码 >根据途径站点查询 >改签 *\n");
printf("* >根据起点&终点查询 *\n");
printf("* >查看所有车次信息 *\n");
printf("******************************************************************************************\n\n");
COMMAND("请输入数字选择【用户操作】");
scanf("%d", &opr);
if(opr == 0){
forw = 0;
break;
}else if(opr == 1){
if(userAccount() == 1){
forw = 0;
break;
}
}else if(opr == 2){
userQur();
}else if(opr == 3){
userTikOP();
}else if(opr == 4){
userPage();
}else{
printf("无相应操作数字,请重试\n\n");
}
}
return forw;
}
manager.c(不全)
仅展示主要函数 managerMenu()
#include "mymac.h"
#include <stdio.h>
#include <time.h>
#include <stdlib.h>
#include <string.h>
#include <windows.h>
extern int manager_num;
extern int user_num;
extern int seed_adj;
/*
管理员界面
*/
int managerMenu()
{
system("cls");
int forw = -1;
if(manager_num == 0){ //无登录状态,需要先登录
printf("****************************************************\n");
printf("*** ");TITLE("管理员模式");printf(" ***\n");
printf("****************************************************\n");
int opr;
// 合法登录才能使用功能
HINT("您需要登录账号来使用系统\n\n");
while(1){
printf("\n》主界面》管理员模式》管理员登录\n");
printf("****************************************************\n");
printf("* 0.返回主界面 *\n");
printf("* 1.登录 *\n");
printf("****************************************************\n\n");
COMMAND("请输入数字选择【登录操作】");
scanf("%d", &opr);
if(opr == 0){
return 0; //跳转主界面
}else if(opr == 1){
signInMana();
break;
}else{
printf("无相应操作数字,请重试\n\n");
}
}
}
// 登录成功,操作
system("cls");
Person *p = getPerson(manager_num);
HINT("\n欢迎管理员");TITLE(p->person_name);
HINT("! 您的系统编号是");printf("%d\n", p->person_num);
printf("*************************************************************************************************************\n");
printf("*** ");TITLE("管理员模式");printf(" ***\n");
printf("*************************************************************************************************************\n");
int opr;
while(1){
printf("\n》主界面》管理员模式》管理员操作》\n");
printf("*************************************************************************************************************\n");
printf("* 0.返回主界面 1.账号设置 2.车次管理 3.用户管理 4.票务管理 5.我的主页 *\n");
printf("* >更改密码 >根据火车编号查看 >根据用户编号查看 >根据车票编号查看 >我的资料*\n");
printf("* >更改电话号码 >根据车次名查看 >根据用户名查看 >根据用户编号查看 *\n");
printf("* >根据途径站点查看 >查看所有用户信息 >根据火车编号查看 *\n");
printf("* >根据起点&终点查看 >查看所有车票信息 *\n");
printf("* >查看所有车次信息 *\n");
printf("* >增设车次 *\n");
printf("* >删除车次 *\n");
printf("*************************************************************************************************************\n\n");
COMMAND("请输入数字选择【管理员操作】");
scanf("%d", &opr);
if(opr == 0){
forw = 0;
break;
}else if(opr == 1){
manaAccount();
}else if(opr == 2){
manaTrainOP();
}else if(opr == 3){
manaUserOP();
}else if(opr == 4){
manaTickitOP();
}else if(opr == 5){
manaPage();
}else{
printf("无相应操作数字,请重试\n\n");
}
}
return forw;
}