引言
很多人在学习数据结构的时候感觉抽象至极,其实把数据结构和编程语言分开来学可以极大减少这些抽象。前篇我们介绍了用C语言去实现一个基础的数据结构(线性表->动态数组)。本片内容,我将和大家分享一个简单而实用的车票预定系统的实现。全程非常简单,只用到了编程中的基础知识(数组、函数、结构体、指针、控制语句),为新手小白量身打造,开始上车吧。
目录
代码结构讲解
该部分提供代码的整体结构,并对各个模块进行逐步解释,通俗易懂。(代码实现方式有很多种,此次完整代码在最后,鼓励创新)/(代码不算高级,应对学校作业绰绰有余)
结构体定义: booking
和 booking_list
1.定义常量
// 定义姓名和火车号的最大长度
#define MAX_NAME_SIZE 30
#define MAX_TRAIN_LEN 20
首先,我们定义了一些常量,这些常量用于设置姓名和火车号的最大长度。使用常量的好处在于,它使代码更易于维护。如果将来需要更改长度,只需修改这里的数值,而无需在代码中到处查找。
2.定义订单结构体(booking)
// 创建一个结构体,包含订单的基本信息;
typedef struct
{
char name[MAX_NAME_SIZE];
char train_number[MAX_TRAIN_LEN];
int seat_number;
}booking;
结构体是C语言中一种用于组合不同数据类型的方式,非常适合用于表示复杂数据。该结构体包含三个成员,表示订单的基本信息。
-
char name[MAX_NAME_SIZE];
:存储乘客的姓名,最多可存储MAX_NAME_SIZE
个字符。 -
char train_number[MAX_TRAIN_LEN];
:存储火车号,最多可存储MAX_TRAIN_LEN
个字符。 -
int seat_number;
:存储座位号,使用整数类型表示。
3.定义订单列表结构体 (booking_list)
// 定义一个结构体,作存储订单的列表;
typedef struct
{
booking* bookings;
size_t size;
size_t capacity;
}booking_list;
该结构体(如果看不懂,可以观看主页关于动态数组的那篇先做了解)包含三个成员,用于存储多个订单的列表。
-
booking* bookings;
:这是一个指向booking
结构体的指针数组,动态存储多个订单。这种设计使得我们可以灵活地扩展订单数量。 -
size_t size;
:当前列表中订单的数量。size_t
是一种无符号整数类型,适用于表示大小和数量。 -
size_t capacity;
:当前列表的容量,即可以存储的最大订单数量。这使得我们能够在需要时进行内存重新分配,以适应新的订单。
以上部分代码展示了如何通过结构体和常量定义基本的数据模型。理解这些基础知识是学习更复杂编程概念的关键。接下来,我们将讨论如何通过这些结构体实现具体的功能。
创建订单列表并进行初始化(create_list)
// 创建一个订单列表并进行初始化;
booking_list* create_list(size_t initial_capacity)
{
booking_list* list = (booking_list*)malloc(sizeof(booking_list));
if(list == NULL)
{
printf("Error:Failed to allocate memory for the booking list structure.\n");
return NULL;
}
list->bookings = (booking*)malloc(initial_capacity * sizeof(booking));
if(list->bookings == NULL)
{
printf("Error:Failed to allocate memory for the internal booking array.\n");
free(list);
return NULL;
}
list->size = 0;
list->capacity = initial_capacity;
return list;
}
在这一段代码中,创建了一个函数 create_list
,用于创建并初始化一个订单列表。下面是对每一部分的详细解释。
1.函数定义
-
booking_list*
:函数的返回值类型是一个指向booking_list
结构体的指针,表示函数将返回一个新创建的订单列表。 -
size_t initial_capacity
:该参数表示订单列表的初始容量,用于预分配内存。size_t
是一种适用于表示大小的无符号整数类型。
2.内存分配
-
malloc(sizeof(booking_list))
:分配足够存储一个booking_list
结构体的内存。 -
(booking_list*)
:将返回的void*
类型指针强制转换为booking_list*
类型,以便我们可以通过它访问booking_list
的字段。
3.检验内存分配(两次)
-
在分配内存后,我们检查返回值是否为
NULL
。如果为NULL
,这意味着内存分配失败,我们打印错误信息并返回NULL
。这样做是为了确保程序的健壮性,避免后续操作造成崩溃。 -
同样,我们检查
bookings
的内存分配是否成功。如果失败,打印错误信息,释放先前分配的list
结构体的内存,然后返回NULL
。
4.初始化并返还指针
-
如果所有内存分配都成功,我们将
size
初始化为0
,表示当前没有订单。同时将capacity
设置为传入的初始容量,以便后续添加订单时使用。 -
最后,函数返回指向新创建的
booking_list
结构体的指针,使得调用者能够访问和操作这个订单列表。
通过这个函数,我们实现了动态创建和初始化一个订单列表的功能,掌握了如何使用内存分配以及如何确保内存分配成功。这是构建更复杂数据结构和功能的基础。接下来,我们将介绍如何向订单列表中添加新订单。
向列表中添加一个新的订单(append_booking)
在这一段代码中,我们实现了一个名为 append_booking
的函数,用于向订单列表中添加新的订单。下面是对每个部分的详细解释。