用链表做一个火车票订票系统

1.有一些问题实现不了,需要根据管理员模块Tick.cpp和头文件,用户模块man.cpp和头文件,改写代码实现以下两个问题。(list.h和list.cpp创建链表,插尾节点后),list模块的代码也可以更改,只要实现功能就可以
(1)目前管理员模块代码实现不了显示全部的车次信息,需要实现可以显示全部的火车票信息,并且再做一个可以实现根据车次查询火车票信息的功能。
(2)用户功能中订票目标城市只能查询到一条数据,需要可以显示当订票时查询目标城市后,显示所有到目标城市的车次信息。并改为根据ID删除用户信息而不是姓名。
(可以自己增加查询函数)
以下是代码:
Tick.h


#ifndef __TICKET_H__
#define __TICKET_H__

//定义火车票信息结构体
typedef struct _ticket
{
    char number[10]; //火车票的车次
    char startCity[10]; //火车票的出发城市
    char reachCity[10]; //火车票的到达城市
    char takeoffTime[10]; //火车票的出发时间
    char reachTime[10]; //火车票的到达时间
    float price; //火车票的票价
    int ticketNum; //火车票的剩余票数
}ticket;
/************************************* 预 编 译 模 块***************************************************/
#define HEADER1 "|------------------------------book ticket sys--------------------------------| \n"
#define HEADER2 "| number | start city | reach city|takeoffTime| reach time|  price| ticketNum | \n"
#define HEADER3 "|-----------------------------------------------------------------------------| \n"
#define FORMAT  "|%-10s|%-10s|%-10s|%-11s|%-10s|%-10.2f|%-10d|\n" // 除 了takeoffTime 这一项,为保持上下对齐的美观,其它项数据都固定只占 10 位的长度
extern node * g_ticketList;
//分配内存空间函数
extern void* mallocMemory(int size);
//保存链表中的数据到文件中
extern int saveData(node* head, int size);
//读取文本中的数据到链表中
extern int readData(node* head, int size);
//添加火车票,并保存在火车票信息链表中
extern int addTicket_toList(node* head);
//根据车次,修改火车票,并马上保存在火车票信息链表中
extern int modifyTicket_byNumber(node* head);
//根据车次,删除火车票,并实时更新
extern int deleteTicket_byNumber(node* head);
//显示火车票信息链表中的所有节点数据
extern int showTicketList_allData(node* head);
#endif

Tick.cpp

#define _CRT_SECURE_NO_WARNINGS

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "list.h"
#include "man.h"
#include "tick.h"

node* g_ticketList = NULL;
//分配内存空间函数
void* mallocMemory(int size)
{
    if (size == sizeof(ticket))
    {
        ticket* tmpTicket = (ticket*)malloc(size);
        return tmpTicket;
    }
    else if (size == sizeof(man))
    {
        man* tmpMan = (man*)malloc(size);
        return tmpMan;
    }
    else
    {
        printf("error!\n");
        return NULL;
    }
}
//保存链表中的数据到文件中
int saveData(node* head, int size)
{
    FILE* fp = NULL;
    int ret = 0;
    if (size == sizeof(ticket))
        fopen_s(&fp, "ticket.txt", "wb"); //打开一个只写的二进制文本
    else if (size == sizeof(man))
        fopen_s(&fp, "man.txt", "wb"); //打开一个只写的二进制文本
    if (!fp)
    {
        printf("fopen error!\n");
        return -1;
    }
    void* temp = NULL;
    for (node* cur = head->next; cur != NULL; cur = cur->next)
    {
        if (size == sizeof(ticket))
            temp = (ticket*)cur->dat; //获取链表节点保存的数据
        else if (size == sizeof(man))
            temp = (man*)cur->dat; //获取链表节点保存的数据
        ret = fwrite(temp, size, 1, fp); //将结构体数据写入二进制文本
        if (ret != 1)
        {
            printf("fwrite error!\n");
            return -1;
        }
    }
    fclose(fp);
    printf("fwrite success!\n");
    return 0;
}
//读取文本中的数据到链表中
int readData(node* head, int size)
{
    FILE* fp = NULL;
    if (size == sizeof(ticket))
        fopen_s(&fp, "ticket.txt", "rb"); //打开一个只读的二进制文本
    else if (size == sizeof(man))
        fopen_s(&fp, "man.txt", "rb"); //打开一个只读的二进制文本
    if (!fp)
    {
        printf("fopen error!\n");
        return -1;
    }
    void* temp = NULL;
    while (!feof(fp))
    {
        if (size == sizeof(ticket))
            temp = (ticket*)mallocMemory(sizeof(ticket)); //定义一个临时火车票结构体指针(必须定义在 while 内,每次读文件,都必须重新分配内存空间)
        else if (size == sizeof(man))
            temp = (man*)mallocMemory(sizeof(man)); //定义一个临时订票人结构体指针(必须定义在 while 内,每次读文件,都必须重新分配内存空间)
            if (fread(temp, size, 1, fp) == 1) //读取二进制文本的结构体数据
            {
                insertData_toListTail(head, temp); //插入数据到链表尾节点后
            }
    }
    fclose(fp);
    printf("fread success!\n");
    return 0;
}


/**********************************


man.h


#ifndef __MAN_H__
#define __MAN_H__

//定义订票人结构体
typedef struct _man
{
    int ID; //ID 身份证号码
    char name[10]; //名字
    int bookNum; //订票数目
}man;


extern node* g_manList; //外部声明一个全局订票人信息链表
//显示订票人信息链表中的所有节点数据
extern int showManList_allData(node* head);
//订票函数
extern int bookTicket(node* head);

//根据名字删除用户信息
extern int deleteMan(node* head, int name);
#endif

man.cpp

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "list.h"
#include "tick.h"
#include "man.h"

node* g_manList = NULL; //定义一个全局订票人信息链表
//显示订票人信息链表中的所有节点数据

int showManList_allData(node* head)
{
    if (!head->next) //检测链表是否只有一个节点
    {
        printf("list only have one node,error!\n"); //链表只有一个节点,则打印错误信息,并返回
            return -1;
    }
    man* tmpMan = NULL; //定义订票人信息的临时结构体指针
    for (node* cur = head->next; cur != NULL; cur = cur->next) //由于头节点不保存数据,所以从第二个节点开始显示数据
    {
    tmpMan = (man*)cur->dat; //将节点数据取出来,赋给临时结构体指针
    printf("%d %s %d\n", tmpMan->ID, tmpMan->name, tmpMan->bookNum);
    }
    return 0;
}


//订票函数
int bookTicket(node* head)
{
    bool findTicket_flag = false; //找到车次对应火车票的标志位
        if (!g_ticketList->next) //检测火车票信息链表是否只有一个节点
        {
            printf("g_ticketList only have one node,error!\n"); //链表只有一个节点,则打印错误信息,并返回
                return -1;
        }
    char t_reachCity[10];
    printf("请输入你要去的城市:");
    scanf_s("%s", t_reachCity, 10);
    ticket* tmpTicket = NULL;
    node* cur;
    for (cur = head->next; cur != NULL; cur = cur->next)
    {
        tmpTicket = (ticket*)cur->dat; //获取火车票信息链表节点保存的数据
        if (strcmp(t_reachCity, tmpTicket->reachCity) == 0 ) //检查输入城市对应的火车票是否存在,````始发,终点
        {
        findTicket_flag = true;
        printf(FORMAT, tmpTicket->number, tmpTicket->startCity,tmpTicket->reachCity, tmpTicket->takeoffTime, tmpTicket->reachTime, tmpTicket->price,tmpTicket->ticketNum);
        break;
        }
    }
    if (!findTicket_flag)
    {
        printf("the number isn't exist!\n");
        return -1;
    }

    char cmd;
    printf("Do you want book ticket?(y/n): ");
    getchar(); //吸收上次输入的"ENTER"
    scanf_s("%c", &cmd, 10);
    if (cmd == 'y')
    {
        ;
    }
    else if (cmd == 'n')
    {
            return -1;
    }
    else
    {
        printf("cmd error!\n");
        return -1;
    }
    man* tmpMan = (man*)mallocMemory(sizeof(man)); //定义一个临时订票人结构体指针,并分配内存空间

    printf("请输入你的 ID:");
    scanf_s("%d", &tmpMan->ID);
    printf("请输入你的姓名:");
    scanf_s("%s", tmpMan->name, 10);
    printf("请输入你的订票数目:");
    scanf_s("%d", &tmpMan->bookNum);
    //更新该车次火车票的剩余票数
    tmpTicket->ticketNum -= tmpMan->bookNum;
    cur->at = tmpTicket;
    insertData_toListTail(g_manList, tmpMan); //插入订票人数据到链表尾节点后
    printf("book ticket success!\n");
    saveData(g_manList, sizeof(man));
    return -1;
}

//删除用户信息
int deleteMan(node* head,int name)
{
    bool findman_flag = false;
        if (!head->next) //检测链表是否只有一个节点
    {
        printf("list only have one node,error!\n"); //链表只有一个节点,则打印错误信息,并返回
        return -1;
    }
    char t_name[10];
    printf("请输入要删除的名字:");
    scanf_s("%s", t_name, 10);
    man* tmpman = NULL;
    for (node* lastNode = head; lastNode->next != NULL; lastNode = lastNode->next)
    {
        tmpman = (man*)lastNode->next->dat; //获取火车票信息链表节点保存的数据
        if (strcmp(t_name, tmpman->name) == 0) //检查输入车次对应的火车票是否存在
        {
            findman_flag = true;
            node* deleteNode = lastNode->next; //“要删除节点”deleteNode,为“上个节点”lastNode 的 next 节点
            lastNode->next = deleteNode->next; //“上个节点”的 next 指向“要删除节点”的 next,则相当于删除了“要删除节点”
            free(deleteNode->dat);
            free(deleteNode); //后面要用到 deleteNode,所以不能释放,否则会崩溃
            printf("delete man success!\n");
            saveData(g_manList, sizeof(man)); //保存火车票链表中的信息到文件中
            break;
        }
    }
    if (!findman_flag)
    {
        printf("the name isn't exist!\n");
        return -1;
    }
    return 0;
}

list.h


#ifndef __LIST_H__
#define __LIST_H__

//定义单向链表节点
typedef struct node
{
    void* dat; //一般为结构体指针
    int size; //dat 指向区域的大小,一般为结构体的大小
    struct node* next; //后继节点
}node;

//创建链表
extern node* createList(int size);
//插入数据到链表尾节点后
extern int insertData_toListTail(node* head, void* dat);
#endif

list.cpp


#define _CRT_SECURE_NO_WARNINGS

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "list.h"
#include "tick.h"
#include "man.h"

//创建链表
node* createList(int size)
{
    node* head = (node*)malloc(sizeof(node)); //给链表头结点分配内存空间
    if (!head)
    {
        printf("listHead malloc error!\n");
        return NULL;
    }
    head->dat = NULL; //链表头结点不存储数据,故指向 NULL
    head->size = size; //链表的 size 一般为结构体的大小[size == sizeof(ticket)]
    head->next = NULL;
    return head;
}

//插入数据到链表尾节点后
int insertData_toListTail(node* head, void* dat)
{
    node* tmpNode = (node*)malloc(sizeof(node)); //定义一个存储插入数据的临时节点,插入该节点就相当于插入数据了
        if (!tmpNode)
        {
            printf("tmpNode malloc error!\n");
            return NULL;
        }

    //给临时节点的数据指针 dat 分配内存空间
        tmpNode->dat = malloc(sizeof(head->size)); //dat 的类型一般为 struct *,所以不再进行(void*)的强制类型转换
        if (!tmpNode->dat)
        {
            printf("tmpNode->dat malloc error!\n");
            return NULL;
        }
    tmpNode->dat = dat; //将要插入的数据保存在临时节点内
    tmpNode->size = head->size;
 
   struct node* cur = head; //定义当前节点

    while (cur->next=NULL) //找到尾节点 [若链表只有一个头节点,则头节点就是尾节点]
    {
        node*cur =(node*)cur->next;
    }
    //将保存要插入数据的临时节点,插入到尾节点后
    cur->next = tmpNode;
    tmpNode->next = NULL; //此时,tmpNode 变为尾节点
    saveData(g_ticketList, sizeof(ticket));
    return 0;
}

【以下回答由 GPT 生成】

问题解答

根据问题描述,我们需要对火车票订票系统的代码进行优化和功能改进,包括添加显示全部火车票信息的功能,根据车次查询火车票信息的功能,显示所有到目标城市的车次信息的功能,以及修改订票系统让删除用户信息通过ID进行操作。

下面是针对这些需求的代码优化和功能改进:

1. 添加显示全部火车票信息的功能

// 显示全部的火车票信息
int displayAllTickets() {
    printf(HEADER1);
    printf(HEADER2);
    printf(HEADER3);

    node *current = g_ticketList;

    while (current != NULL) {
        ticket *currentTicket = (ticket*)current->data;
        printf(FORMAT, currentTicket->number, currentTicket->startCity, currentTicket->reachCity, currentTicket->takeoffTime, currentTicket->reachTime, currentTicket->price, currentTicket->ticketNum);
        current = current->next;
    }

    return 0;
}

2. 添加根据车次查询火车票信息的功能

// 根据车次查询火车票信息
int searchTicketByNumber(char *number) {
    printf(HEADER1);
    printf(HEADER2);
    printf(HEADER3);

    node *current = g_ticketList;

    while (current != NULL) {
        ticket *currentTicket = (ticket*)current->data;
        if (strcmp(currentTicket->number, number) == 0) {
            printf(FORMAT, currentTicket->number, currentTicket->startCity, currentTicket->reachCity, currentTicket->takeoffTime, currentTicket->reachTime, currentTicket->price, currentTicket->ticketNum);
            return 0;
        }
        current = current->next;
    }

    printf("Ticket not found.\n");
    return -1;
}

3. 修改订票系统使得用户功能中可以显示所有到目标城市的车次信息

// 显示所有到目标城市的车次信息
int displayTicketsToCity(char *city) {
    printf(HEADER1);
    printf(HEADER2);
    printf(HEADER3);

    node *current = g_ticketList;

    while (current != NULL) {
        ticket *currentTicket = (ticket*)current->data;
        if (strcmp(currentTicket->reachCity, city) == 0) {
            printf(FORMAT, currentTicket->number, currentTicket->startCity, currentTicket->reachCity, currentTicket->takeoffTime, currentTicket->reachTime, currentTicket->price, currentTicket->ticketNum);
        }
        current = current->next;
    }

    return 0;
}

4. 修改订票系统使得删除用户信息通过ID进行操作

// 根据ID删除用户信息
int deleteUserInfoById(int id) {
    node *current = g_ticketList;
    node *previous = NULL;

    while (current != NULL) {
        ticket *currentTicket = (ticket*)current->data;
        if (currentTicket->id == id) {
            if (previous == NULL) {
                g_ticketList = current->next;
            } else {
                previous->next = current->next;
            }
            free(current);
            return 0;
        }
        previous = current;
        current = current->next;
    }

    printf("Ticket not found.\n");
    return -1;
}

补全代码如下:

#include "list.h"

//定义火车票信息结构体
typedef struct _ticket
{
    int id; //火车票的ID
    char number[10]; //火车票的车次
    char startCity[10]; //火车票的出发城市
    char reachCity[10]; //火车票的到达城市
    char takeoffTime[10]; //火车票的出发时间
    char reachTime[10]; //火车票的到达时间
    float price; //火车票的票价
    int ticketNum; //火车票的剩余票数
} ticket;

/************************************* 预 编 译 模 块***************************************************/
#define HEADER1 "|------------------------------book ticket sys--------------------------------| \n"
#define HEADER2 "| id | number | start city | reach city|takeoffTime| reach time|  price| ticketNum | \n"
#define HEADER3 "|-----------------------------------------------------------------------------| \n"
#define FORMAT "|%-3d|%-10s|%-10s|%-10s|%-11s|%-10s|%-10.2f|%-10d|\n" // 除了takeoffTime 这一项,为保持上下对齐的美观,其它项数据都固定只占 10 位的长度

extern node *g_ticketList;

//分配内存空间函数
extern void *mallocMemory(int size);

//保存链表中的数据到文件中
extern int saveData(node *head, int size);

//读取文本中的数据到链表中
extern int readData(node *head, int size);

//添加火车票,并保存在火车票信息链表中
extern int addTicketToList(ticket newTicket);

//显示全部的火车票信息
extern int displayAllTickets();

//根据车次查询火车票信息
extern int searchTicketByNumber(char *number);

//显示所有到目标城市的车次信息
extern int displayTicketsToCity(char *city);

//根据ID删除用户信息
extern int deleteUserInfoById(int id);

// 显示全部的火车票信息
int displayAllTickets() {
    printf(HEADER1);
    printf(HEADER2);
    printf(HEADER3);

    node *current = g_ticketList;

    while (current != NULL) {
        ticket *currentTicket = (ticket*)current->data;
        printf(FORMAT, currentTicket->id, currentTicket->number, currentTicket->startCity, currentTicket->reachCity, currentTicket->takeoffTime, currentTicket->reachTime, currentTicket->price, currentTicket->ticketNum);
        current = current->next;
    }

    return 0;
}

// 根据车次查询火车票信息
int searchTicketByNumber(char *number) {
    printf(HEADER1);
    printf(HEADER2);
    printf(HEADER3);

    node *current = g_ticketList;

    while (current != NULL) {
        ticket *currentTicket = (ticket*)current->data;
        if (strcmp(currentTicket->number, number) == 0) {
            printf(FORMAT, currentTicket->id, currentTicket->number, currentTicket->startCity, currentTicket->reachCity, currentTicket->takeoffTime, currentTicket->reachTime, currentTicket->price, currentTicket->ticketNum);
            return 0;
        }
        current = current->next;
    }

    printf("Ticket not found.\n");
    return -1;
}

// 显示所有到目标城市的车次信息
int displayTicketsToCity(char *city) {
    printf(HEADER1);
    printf(HEADER2);
    printf(HEADER3);

    node *current = g_ticketList;

    while (current != NULL) {
        ticket *currentTicket = (ticket*)current->data;
        if (strcmp(currentTicket->reachCity, city) == 0) {
            printf(FORMAT, currentTicket->id, currentTicket->number, currentTicket->startCity, currentTicket->reachCity, currentTicket->takeoffTime, currentTicket->reachTime, currentTicket->price, currentTicket->ticketNum);
        }
        current = current->next;
    }

    return 0;
}

// 根据ID删除用户信息
int deleteUserInfoById(int id) {
    node *current = g_ticketList;
    node *previous = NULL;

    while (current != NULL) {
        ticket *currentTicket = (ticket*)current->data;
        if (currentTicket->id == id) {
            if (previous == NULL) {
                g_ticketList = current->next;
            } else {
                previous->next = current->next;
            }
            free(current);
            return 0;
        }
        previous = current;
        current = current->next;
    }

    printf("Ticket not found.\n");
    return -1;
}

如果你已经解决了该问题, 非常希望你能够分享一下解决方案, 写成博客, 将相关链接放在评论区, 以帮助更多的人 ^-^

数据结构课程设计之火车票订票系统实现(C语言/C++版本)_火车订票系统c语言课程设计_~|Bernard|的博客-CSDN博客 课题描述 编制一个程序,火车票订票的业务活动包括:车次查询、订票、退票、用户管理等。需求分析用户信息包括用户姓名、身份证号、用户电话、用户所购列车号、订单号;列车信息包括:列车车站号、车票起点、车票终点、出发时间、到达时间、票价、票数等基本信息。软件需要实现以下功能:(1)录入:可以录入车次(车次号、车站1、车站2...、余票)、客户等数据;(2)查询车次:车次及分段余票信息;(3)订票业务:根据客户提出的要求(车次、起点、终点、订票数额)查询票额情况,若尚有余额,则为客户._火车订票系统c语言课程设计 https://blog.csdn.net/weixin_56054625/article/details/124570917?ops_request_misc=%257B%2522request%255Fid%2522%253A%2522169172313116800184136224%2522%252C%2522scm%2522%253A%252220140713.130102334.pc%255Fall.%2522%257D&request_id=169172313116800184136224&biz_id=0&utm_medium=distribute.pc_search_result.none-task-blog-2~all~first_rank_ecpm_v1~rank_v31_ecpm-2-124570917-null-null.142^v92^controlT0_1&utm_term=%E7%94%A8%E9%93%BE%E8%A1%A8%E5%81%9A%E4%B8%80%E4%B8%AA%E7%81%AB%E8%BD%A6%E7%A5%A8%E8%AE%A2%E7%A5%A8%E7%B3%BB%E7%BB%9F%20c%2B%2B%20c%E8%AF%AD%E8%A8%80&spm=1018.2226.3001.4187