双向循环链表-航班订票系统

Makefile多文件统筹开发,标准io实现用户注册,登录,密码星号保密打印,管理员在注册登录界面直接输(1443003064):    实现对航班的增删改查;用户:实现对航班信息的总览,查询机票,订票,退票,    查看个人订单。

vscode下载https://vscode.cdn.azure.cn/stable/441438abd1ac652551dbe4d408dfcec8a499b8bf/VSCodeUserSetup-x64-1.75.1.exe

        可以直接cp用作数据结构课设还是可以的,如果文件操作没有学,可以自己把账号跟密码放入链表数据里。

.h文件

#ifndef __FLIGHT_H__
#define __FLIGHT_H__
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <strings.h>
#include <stdbool.h>
#include <termio.h>



typedef struct flight_data //航班信息数据结构
{
    int flightID;        //航班号(月日时分+当日起飞次序)
    char staaddress[20]; //起点站
    char arraddress[20]; //终点站
    char plane[20];      //机型
    char stime[20];      //起飞时间(月日时分)
    char atime[20];      //到达时间(月日时分)
    int value;           //票价
    int ticket;          //飞机票数
} flight, *pflight;

typedef struct node //双向链表结点
{
    flight data;
    struct node *next;
    struct node *prev;
} node, *pnode;

typedef struct JiaJieMi
{
    char id[11];  // id 即登录的账号
    char pwd[20]; //密码
} decrypt;        //用来账号和伪密码联系起来,存入另一个一个文件;

typedef struct Userinfo
{
    char userid[11];    // id 即登录的账号
    char pwd[20];       //密码
    char username[15];  //姓名
    char userphone[12]; //电话
} user, *puser;         //  用户信息


node *create_Init(); //创建头节点并初始化
void node_insert_end(node *head); //添加航班(管理员)
void delete_flight(node *head); //删除航班信息(adm)
void show_flight(node *head); //查看航班信息(adm,user)
void updata_time(node *head); //修改航班信息,晚点时使用(管理员)
bool find_flight(node *head); //搜索航班信息(管理员和用户通用)
int book_flight(node *head); //订票(用户)
void refund_ticket(node *head, int x); //退票(user)
void show_ticket(node *head, int x);//查看个人订票
void admmenu(node *head); //(管理员菜单界面)
void common_usermenu(node *head); //普通用户菜单界面
void main_UI();//初始化界面
int getch(void);//vim终端设置
void regis();//注册
void login(node *head); //登录


#endif




.c文件

#include "flight.h"

int RETU = 0; //定义全局变量为订票功能服务,返回值,注意此变量名不能与函数形参名相同,否则只会修改形参

node *create_Init() //创建头节点并初始化
{
    node *phead = (node *)malloc(sizeof(node));
    if (NULL == phead)
    {
        printf("头节点申请错误\n");
        return NULL;
    }
    phead->next = phead; //定义成双向循环链表
    phead->prev = phead;
    return phead;
}

void node_insert_end(node *head) //添加航班(管理员)
{
    node *pnew = (node *)malloc(sizeof(node)); //申请内存,创建新节点
    if (pnew == NULL)                          //容错处理
    {
        printf("申请失败!");
    }
    if (head != NULL)
    {
        head->prev->next = pnew; //链接新节点
        pnew->prev = head->prev;
        head->prev = pnew;
        pnew->next = head;
        printf("\n航班号:");
        scanf("%d", &pnew->data.flightID);
        printf("\n起点站:");
        scanf("%s", pnew->data.staaddress);
        printf("\n终点站:");
        scanf("%s", pnew->data.arraddress);
        printf("\n机型:");
        scanf("%s", pnew->data.plane);
        printf("\n起飞时间:");
        scanf("%s", pnew->data.stime);
        printf("\n到达时间:");
        scanf("%s", pnew->data.atime);
        printf("\n票价:");
        scanf("%d", &pnew->data.value);
        printf("\n票数:");
        scanf("%d", &pnew->data.ticket);
        printf("\n添加完成\n");
        printf("\t\t\t\t\t****************************************************************^-^\n\n\n\n\n\n");
    }
}

void delete_flight(node *head) //删除航班信息(adm)
{
    if (head == NULL) //容错处理
    {
        printf("传入失败!");
    }
    node *ptemp = head; //定义临时节点
    int id;
    printf("请输入要删除的航班ID^-^:");
    scanf("%d", &id);
    do
    {
        ptemp = ptemp->next;
        if (id == ptemp->data.flightID)
        {
            ptemp->prev->next = ptemp->next; //链接与断开
            ptemp->next->prev = ptemp->prev;
            printf("\n\n删除成功!");

            free(ptemp); //释放内存并置空
            ptemp = NULL;
            return;
        }
    } while (ptemp != head); //遍历寻找id

    printf("未找到此ID,请检查是否输入错误!^-^\n"); //在循环内未找到,输出这句话
}

void show_flight(node *head) //查看航班信息(adm,user)
{
    if (head == NULL) //容错处理
    {
        printf("传入失败!");
    }
    node *ptemp = head; //临时节点遍历
    printf("\n\n\n\n\n\n\t\t\t\t\t航班号  起点站  终点站 机型    起飞时间 到达时间 票价  票数^-^\n\n");
    do
    {
        ptemp = ptemp->next;
        printf("\t\t\t\t\t%d  %s   %s   %s   %s   %s   %d   %d\n", ptemp->data.flightID, ptemp->data.staaddress,
               ptemp->data.arraddress, ptemp->data.plane, ptemp->data.stime, ptemp->data.atime, ptemp->data.value, ptemp->data.ticket);
    } while (ptemp != head);
    printf("\n\t\t\t\t\t**********************************^-^******************************\n\n\n\n\n\n\n\n\n\n");
}

void updata_time(node *head) //修改航班信息,晚点时使用(管理员)
{
    if (head == NULL) //容错处理
    {
        printf("传入失败!");
    }
    node *ptemp = head; //定义临时节点,遍历

    int id;
    char time[20]; //延误后的时间
    printf("\n请输入要修改的航班ID^-^:");
    scanf("%d", &id);
    do
    {
        ptemp = ptemp->next;
        if (id == ptemp->data.flightID)
        {
            printf("\n请输入延误后时间^-^\n");
            scanf("%s", time);
            strcpy(ptemp->data.atime, time);
            printf("\n修改成功!^-^\n\n\n\n\n");
            return;
        }
    } while (ptemp != head);

    printf("\n\n未找到此ID,请检查是否输入错误!^-^\n\n\n\n\n");
}

bool find_flight(node *head) //搜索航班信息(管理员和用户通用)运用起点站和目的地查询
{
    if (head == NULL) //容错处理
    {
        printf("传入失败!");
    }
    int t; //方便呈现比对结果
    char arrive[20];
    char start[20];
    printf("\n请输入您当前的位置^-^\n");
    scanf("%s", start);
    printf("\n请输入您的目的地^-^\n");
    scanf("%s", arrive);
    printf("正在查询!\n正在显示!\n");
    node *ptemp = head->next;
    printf("\n\n\n\n\n\n\t\t\t\t\t航班号  起点站  终点站 机型     起飞时间 到达时间 票价  票数^-^\n\n");
    while (ptemp != head)
    { //两次比对结果(位或),strcmp(a,b)a,b相同则为0;
        t = !(strcmp(ptemp->data.staaddress, start) | strcmp(ptemp->data.arraddress, arrive));
        if (t == 1)
        {
            printf("\t\t\t\t\t%d  %s   %s   %s    %s  %s   %d   %d\n", ptemp->data.flightID, ptemp->data.staaddress,
                   ptemp->data.arraddress, ptemp->data.plane, ptemp->data.stime, ptemp->data.atime,
                   ptemp->data.value, ptemp->data.ticket);
        }
        ptemp = ptemp->next; //两次比对结果(位或),strcmp(a,b)a,b相同则为0;
    }
    printf("\n\n查询完成!^-^\n\n\n");
}

int book_flight(node *head) //订票(用户)
{
    if (head == NULL) //容错处理
    {
        printf("\n传入失败!\n");
    }
    if (find_flight(head))
    {
        int t;
        node *ptemp = head;
        printf("请选择您想要乘坐的航班号^-^");
        scanf("%d", &t);
        do
        {
            ptemp = ptemp->next;
            if (t == ptemp->data.flightID)
            {
                ptemp->data.ticket = ptemp->data.ticket - 1;
                printf("\n\n\n\n\n\n\t\t\t\t\t航班号  起点站  终点站 机型     起飞时间 到达时间 票价  票数^-^\n\n");
                printf("\t\t\t\t\t%d  %s   %s   %s    %s  %s   %d   %d\n", ptemp->data.flightID, ptemp->data.staaddress,
                       ptemp->data.arraddress, ptemp->data.plane, ptemp->data.stime, ptemp->data.atime,
                       ptemp->data.value, ptemp->data.ticket);
                printf("订购成功!^-^\n\n\n\n\n\n\n\n");
                printf("\n\t\t\t\t\t*********************************^-^*********************************\n");

                return ptemp->data.flightID;
            }

        } while (ptemp != head);
        printf("\n\n输入错误的航班ID^-^\n\n\n\n\n\n\n");
    }
}

void refund_ticket(node *head, int x) //退票(user)
{
    if (head == NULL) //容错处理
    {
        printf("传入失败!");
    }
    if (head != NULL)
    {
        int r;
        node *ptemp = head;
        printf("\t请选择您想要退订的航班号^-^\n");
        scanf("%d", &r);
        do
        {
            ptemp = ptemp->next;
            if (r == ptemp->data.flightID) //输入要退订航班号与订购的航班id比对
            {
                ptemp->data.ticket = ptemp->data.ticket + 1; //找到就加一,退回一张票
                RETU = -1;                                   // RETU 置为-1,在个人订单使用,用作比对
                printf("退订成功!^-^\n\n\n\n");
                return;
            }
        } while (ptemp != head);
        printf("\t未订购此航班机票!^-^\n\n\n\n");
    }
}

void show_ticket(node *head, int x) //查看个人订单
{
    if (head == NULL) //容错处理
    {
        printf("传入失败!");
    }
    if (head != NULL)
    {
        node *ptemp = head;
        do
        {
            ptemp = ptemp->next;
            if (RETU == ptemp->data.flightID)
            {
                printf("\t\t\t\t\t************************  个人 订单  *************************^-^\n");
                printf("\n\t\t\t\t\t航班号  起点站  终点站 机型     起飞时间 到达时间 票价  票数^-^\n\n");
                printf("\t\t\t\t\t%d  %s   %s   %s    %s  %s   %d   %d\n", ptemp->data.flightID, ptemp->data.staaddress,
                       ptemp->data.arraddress, ptemp->data.plane, ptemp->data.stime, ptemp->data.atime,
                       ptemp->data.value, ptemp->data.ticket);
                printf("\n\n\n\n\n");
                return;
            }
        } while (ptemp != head);

        printf("\n您还没有订单!\n\n\n\n\n");
    }
}

void admmenu(node *head) //(管理员菜单界面)
{
    if (head == NULL) //容错处理
    {
        printf("传入失败!");
    }
    printf("\033c");
    char choose[20];
    int flag = 1, ch;

    while (flag)
    {
        printf("\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************************0.退出管理员操作  **********************^-^\n");
        scanf("%s", choose);
        ch = atoi(choose); //防止输入字母时系统崩溃,用atoi转成整型

        switch (ch)
        {
        case 1:
            node_insert_end(head); //尾插法,增加航班
            break;
        case 2:
            delete_flight(head); //删除航班
            break;
        case 3:
            show_flight(head); //查看所有航班
            break;
        case 4:
            find_flight(head); //查找航班根据起点与终点
            break;
        case 5:
            updata_time(head); //修改时间
            break;
        case 0:
            flag = 0; // 退出
            break;
        default:
            printf("请输入正确的序号!\n");
            break;
        }
    }
}

void common_usermenu(node *head) //普通用户菜单界面
{
    if (head == NULL) //容错处理
    {
        printf("传入失败!");
    }
    int flag = 1, choo;
    printf("\033c");

    while (flag)
    {
        printf("\t\t\t\t\t\t     ^-^ 欢迎使用航空订票系统  ^-^                    \n");
        printf("\t\t\t\t\t****xx航空公司将竭心为您服务,请选择您的需求选择服务,祝您使用愉快!*****^-^\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*********************** 0.退出系统     *************************^-^\n");
        printf("\n\t请输入你要进行的操作:^-^\n\n");
        char choose[20];
        scanf("%s", choose);
        choo = atoi(choose);

        switch (choo)
        {
        case 1:
            show_flight(head);
            break;
        case 2:
            find_flight(head);
            break;
        case 3:
            RETU = book_flight(head);
            break;
        case 4:
            refund_ticket(head, RETU);
            break;
        case 5:
            show_ticket(head, RETU);
            break;
        case 0:
            flag = 0;
            printf("感谢您的使用!\n\n\n\n\n");
            break;
        default:
            printf("请输入正确的序号!\n\n");
            break;
        }
    }
}

void main_UI()
{
    printf("\033c"); //清屏
    printf("\n\n\n\n\n\n\n\n\n");
    printf("\t\t\t\t\t                  ^-^  欢迎使用xx航空订票系统  ^-^                   \n");
    printf("\t\t\t\t\t****xx航空公司将竭心为您服务,请选择您的需求选择服务,祝您使用愉快!*****^-^\n\n");
    printf("\t\t\t\t\t************************* 1.注册     ***************************^-^\n");
    printf("\t\t\t\t\t************************* 2.登录     ***************************^-^\n");
    printf("\t\t\t\t\t*********************** 0.退出系统    ***************************^-^\n");
    printf("\n\t\t请输入你要进行的操作:^-^\n\n");
}

int getch(void) // vim终端设置
{
    struct termios tm, tm_old;
    int fd = 0, ch;

    if (tcgetattr(fd, &tm) < 0) //保存现在的终端设置
    {
        return -1;
    }

    tm_old = tm; //更改终端设置为原始模式,该模式下所有的输入数据以字节为单位被处理
    cfmakeraw(&tm);
    if (tcsetattr(fd, TCSANOW, &tm) < 0) //设置上更改之后的设置
    {
        return -1;
    }

    ch = getchar();
    if (tcsetattr(fd, TCSANOW, &tm_old) < 0) //更改设置为最初的样子
    {
        return -1;
    }
    return ch;
}
void regis()
{
    user a;
    decrypt b;
    char arr[20]; //输入的密码
    char bb[20];  //加密处理后的密码
    char c;       //消除回车
    printf("\033c");
    printf("欢迎来到注册界面!\n");
    FILE *pf = fopen("users.txt", "a");
    if (pf == NULL)
    {
        perror("open失败");
        return;
    }
    printf("请输入您的姓名>>");
    scanf("%s", a.username);
    printf("请输入您的电话号码>>");
    scanf("%s", a.userphone);
    printf("请输入您的帐号>>");
    scanf("%s", a.userid);
    printf("请输入您的密码(不超过20位)>>");
    strcpy(a.pwd, "******");
    fprintf(pf, "%s %s %s %s\n", a.userid, a.pwd, a.username, a.userphone);
    fclose(pf);
    pf == NULL;
    c = getchar();
    int i = 0;
    int j = 0;
    while (i < 20)
    {
        arr[i] = getch();            // getch()从控制台输入一各字符但是不显示
        if (arr[i] == '\b' && i > 0) //遇到空格不管
        {
            continue;
        }
        if (arr[i] == '\b' && i == 0) //如果在最开始就按退格键(backspace),就让i=-1
        {
            i = 0;
            continue;
        }
        if (arr[i] == '\r') //如果输入的是回车,就退出输入循环
        {
            break;
        }
        i++;
        putchar('*');
    }
    arr[i] = '\0';
    printf("\n");
    for (int j = 0; j < strlen(arr); ++j)
    {
        bb[j] = arr[j] + j; //加密方法:用户密码+j后保存到文本;
    }
    bb[strlen(arr)] = '\0';
    strcpy(b.id, a.userid);
    strcpy(b.pwd, bb);
    FILE *q = fopen("decrypt.txt", "a");
    if (q == NULL)
    {
        perror("open<decrypt>失败");
        return;
    }
    fprintf(q, "\n%s %s", b.id, b.pwd);
    fclose(q);
    q == NULL;
    printf("\t注册成功!");
}

void login(node *head) //登录
{
    if (head == NULL) //容错处理
    {
        printf("传入失败!");
    }
    char rr[20]; //输入的密码
    decrypt a, b;
    char c;
    FILE *pf = fopen("decrypt.txt", "r");
    if (pf == NULL)
    {
        perror("open<decrypt>失败");
        return;
    }
    printf("\033c");
    printf("\n\t\t欢迎来到登录界面!\n");
    fscanf(pf, "%s %s", a.id, a.pwd);
    printf("\t\t请输入账号>>");
    scanf("%s", b.id);
    c = getchar();

    while (1)
    {
        if (!strcmp(a.id, b.id)) //在文件中找到了与用户输入相同的id
        {
            break;
        }
        else
        {
            if (!feof(pf)) //没读到文件末尾,继续读取文件中的id到a中
            {
                fscanf(pf, "%s %s", a.id, a.pwd); //继续从文件中读取用户信息进a,直到在文件中找到一个和a的信息相同的
            }
            else //读到文件末尾了,没有找到与用户输入相同的账号
            {
                printf("\n\t此账号不存在!请注册!\n");
                fclose(pf);
                pf = NULL;
                regis();
                return;
            }
        }
    }
    char d;
    char mima[20];    //解密后的密码
    char weimima[30]; //保存的伪密码
    do
    {
        printf("请输入密码>>");
        int i = 0;
        int j = 0;
        while (i < 20)
        {
            rr[i] = getch();            // getch()从控制台输入一各字符但是不显示
            if (rr[i] == '\b' && i > 0) //遇到空格不管
            {
                continue;
            }
            if (rr[i] == '\b' && i == 0) //如果在最开始就按退格键,就让i=-1
            {
                i = 0;
                continue;
            }
            if (rr[i] == '\r') //如果输入的是回车,就退出输入循环
            {
                break;
            }
            i++;
            putchar('*');
        }
        rr[i] = '\0';
        strcpy(weimima, a.pwd);
        for (int i = 0; i < strlen(rr); ++i)
        {
            mima[i] = weimima[i] - i;
        }
        mima[strlen(rr)] = '\0';
        if (!strcmp(mima, rr)) //输入的密码与文件中的相同
        {
            printf("\n\t登录成功!欢迎使用!\n");
            fclose(pf);
            pf = NULL; //置空,避免野指针
            common_usermenu(head);
            return;
        }
        else
        {
            printf("\n\t密码输入错误,请重新输入\n");
        }
    } while (strcmp(mima, rr));
}

main.c文件

#include "flight.h"


int main(int argc, char *argv[])
{
    node *head = create_Init();//头节点
    int flag = 1, choose1;
    while (flag)
    {
        main_UI();
        char choose[20];
        scanf("%s", choose);
        choose1 = atoi(choose);//转成整型容错,防止系统崩溃
        switch (choose1)
        {
        case 1:
            regis();//注册
            break;
        case 2:
            login(head);//登录
            break;
        case 3:
            flag = 0;//退出
            break;
        case 1443003064:  //管理员入口:不显示此功能,管理员自知,在显示功能外(隐藏入口)
            admmenu(head);
            break;
        default:
            printf("\n请输入正确的序号!\n");
            break;
        }
    }
    return 0;
}

  

makefile文件

FLIGHT : main.o flight.o
	gcc -g main.o flight.o -o FLIGHT
main.o : main.c
	gcc -g -c main.c -o main.o
flight.o: flight.c
	gcc -g -c flight.c -o flight.o
clean:
	rm *.txt main.o flight.o

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值