顺序表的实现:Book_Manage_System

一、问题引入

图书信息管理系统:
出版社有一些图书数据保存在一个文本文件book.txt 中,为简单起见,在此假设每种图书只包括三部分信息:ISBN (书号)、书名和价格,文件中的部分数据如图2.1 所示。现要求实现一个图书信息管理系统,包括以下6个具体功能。

(1) 查找:根据指定的ISBN 或书名查找相应图书的有关信息, 并返回该图书在表中的位置序号。
(2) 插入:插入一种新的图书信息。
(3) 删除:删除一种图书信息。
(4) 修改:根据指定的ISBN, 修改该图书的价格。
(5) 排序:将图书按照价格由低到高进行排序。
(6) 计数:统计图书表中的图书数量

具体实现:

图书数据由用户输入,而不直接从文本文件book.txt读取(后续考虑以这种方式载入数据,新增数据通过用户输入)。

二、解决过程

2-1 数据格式定义

  • 顺序表的定义
#define OK        0
#define ERROR    -1
#define OVERFLOW -2

#define MAXSIZE 10000 //顺序表的最大长度

typedef struct
{
	char   name[50]; // 书名
	double price;    // 单价
	char   isbn[20]; // ISBN码
}Book_T;

typedef Book_T ElemType;

typedef struct
{
	ElemType *base; // 存储空间的基地址
	int length;     // 当前长度
}SqList_T;          // 顺序表的结构类型为 Sqlist_T

2-2 功能实现

  • 顺序表的初始化
int list_init(SqList_T *sq_list_pt)
{
	sq_list_pt->base = (ElemType *)malloc(MAXSIZE * sizeof(ElemType));
	if (sq_list_pt == NULL)
		exit(OVERFLOW);
	memset(sq_list_pt->base, 0, MAXSIZE * sizeof(ElemType));
	sq_list_pt->length = 0;
	return OK;
}
  • 顺序表的销毁
void list_destory(SqList_T *sq_list_pt)
{
	if (sq_list_pt->base != NULL)
		free(sq_list_pt->base);
	sq_list_pt->base = NULL;
	sq_list_pt->length = 0;
}
  • 顺序表的查找
ElemType * element_locate(SqList_T sq_list_t, const char *isbn, int *idx)
{
	ElemType *p_elem = NULL;
	*idx = -1;
	for (int i = 0; i < sq_list_t.length; i++)
	{
		if (0 == strcmp(sq_list_t.base[i].isbn, isbn))
		{
			p_elem = &sq_list_t.base[i];
			*idx = i+1;
			break;
		}
	}
	return p_elem;
}
  • 顺序表的插入
int list_insert(SqList_T *sq_list_pt, ElemType elem)
{
	// 判断顺序表是否到达最大长度
	if (sq_list_pt->length == MAXSIZE)
		return ERROR;
	int idx = sq_list_pt->length;
	sq_list_pt->base[idx] = elem;
	(sq_list_pt->length)++;
	return OK;
}
  • 顺序表的删除
int list_delete(SqList_T *sq_list_pt, const char *isbn)
{
	// 判断顺序表是否为空
	if (sq_list_pt->length == 0)
		return ERROR;
	int idx = 0; // idx 从1开始
	if (element_locate(*sq_list_pt, isbn, &idx) != NULL)
	{
		for (int i = idx; i <= sq_list_pt->length; i++)
		{
			sq_list_pt->base[i-1] = sq_list_pt->base[i];
		}
	}
	(sq_list_pt->length)--;
	return OK;
}
  • 顺序表的遍历
int list_traverse(SqList_T sq_list_t)
{
	printf("ISBN                          "
		   "书名                          "
		   "单价                           \n");
	if (sq_list_t.length == 0)
	{
		printf("图书馆书籍为空\n");
		return ERROR;
	}
	for (int i = 0; i < sq_list_t.length; i++)
	{
		printf("%-30s%-30s%-30.2f\n", sq_list_t.base[i].isbn, 
			sq_list_t.base[i].name, sq_list_t.base[i].price);
	}
	return OK;
}
  • 顺序表的修改
int list_update(SqList_T *sq_list_pt, const char *isbn, double price)
{
	// 判断顺序表是否为空
	if (sq_list_pt->length == 0)
		return ERROR;
	ElemType *p_elem = NULL;
	int idx = 0; // idx 从1开始
	p_elem = element_locate(*sq_list_pt, isbn, &idx);
	if (p_elem == NULL)
		return ERROR;
	p_elem->price = price;
	return OK;
}
  • 顺序表的排序
int book_price_compare(const void *e1, const *e2)
{
	ElemType *elem1 = (ElemType *)e1;
	ElemType *elem2 = (ElemType *)e2;
	return (int)(elem1->price - elem2->price);
}

// 顺序表的排序(根据图书的价格,从低到高排序)
int list_sort(SqList_T *sq_list_pt)
{
	qsort(sq_list_pt->base, sq_list_pt->length, sizeof(sq_list_pt->base[0]), book_price_compare);
	return OK;
}

2-3 main()

int main(void)
{
	int num_of_book = 0;
	Book_T book_arr[MAXSIZE] = {0};
	SqList_T sq_list_t = {0};

	list_init(&sq_list_t);
	printf("请输入书籍数量:");
	scanf("%d", &num_of_book);
	printf("\n");

	for (int i = 0; i < num_of_book; i++)
	{
		printf("请输入第%d本的信息\n", i+1);
		printf("书籍名称:");
		scanf("%50s", book_arr[i].name);
		printf("书籍单价:");
		scanf("%lf", &book_arr[i].price);
		printf("书籍ISBN:");
		scanf("%20s", book_arr[i].isbn);
		printf("\n");
	}
	// 插入
	for (int i = 0; i < num_of_book; i++)
	{
		list_insert(&sq_list_t, book_arr[i]);
	}
	// 遍历打印所有书籍
	printf("打印图书馆所有书籍清单:\n");
	list_traverse(sq_list_t);
	printf("\n");

	// 删除
	char isbn[20] = {0};
	printf("请输入删除书籍的ISBN码:");
	scanf("%20s", isbn);
	list_delete(&sq_list_t, isbn);

	printf("打印图书馆所有书籍清单:\n");
	list_traverse(sq_list_t);
	printf("\n");

	// 查找
	ElemType *p_elem = NULL;
	char book_info[300] = {0};
	int idx = 0;
	printf("请输入查找数据的ISBN码:");
	scanf("%20s", isbn);
	p_elem = element_locate(sq_list_t, isbn, &idx);
	if (NULL != p_elem)
	{
		sprintf(book_info, "{\"name\":\"%s\",\"isbn\":\"%s\",\"price\":%.2f}",
			p_elem->name, p_elem->isbn, p_elem->price);
		printf("%s\n", book_info);
	}
	printf("\n");

	// 修改
	double price = 0;
	printf("请输入书籍的ISBN码:");
	scanf("%20s", isbn);
	printf("请输入书籍现在的价格:");
	scanf("%lf", &price);
	if (ERROR == list_update(&sq_list_t, isbn, price))
	{
		printf("价格修改失败\n");
	}
	printf("打印图书馆所有书籍清单:\n");
	list_traverse(sq_list_t);
	printf("\n");


	// 释放内存空间
	list_destory(&sq_list_t);

	return 0;
}

? 运行结果

顺序表的实现:Book_Manage_System

2-4 排序功能(新增)

int main(void)
{
	int num_of_book = 0;
	Book_T book_arr[MAXSIZE] = {0};
	SqList_T sq_list_t = {0};

	list_init(&sq_list_t);
	printf("请输入书籍数量:");
	scanf("%d", &num_of_book);
	printf("\n");

	for (int i = 0; i < num_of_book; i++)
	{
		printf("请输入第%d本的信息\n", i+1);
		printf("书籍名称:");
		scanf("%50s", book_arr[i].name);
		printf("书籍单价:");
		scanf("%lf", &book_arr[i].price);
		printf("书籍ISBN:");
		scanf("%20s", book_arr[i].isbn);
		printf("\n");
	}
	/* 插入 */
	for (int i = 0; i < num_of_book; i++)
	{
		list_insert(&sq_list_t, book_arr[i]);
	}
	/* 遍历打印所有书籍 */
	printf("打印图书馆所有书籍清单:\n");
	list_traverse(sq_list_t);
	printf("\n");

	/* 排序 */
	list_sort(&sq_list_t);
	printf("打印图书馆所有书籍清单:\n");
	list_traverse(sq_list_t);
	printf("\n");
	/* 释放内存空间 */
	list_destory(&sq_list_t);

	return 0;
}

? 运行结果

顺序表的实现:Book_Manage_System

三、反思总结

顺序表可以随机存取表中任一元素,其存储位置可用一个简单、直观的公式来表示。然而,从另一方面来看,这个特点也造成了这种存储结构的缺点:在做插入删除操作时,需移动大量元素。另外由于数组有长度相对固定的静态特性, 当表中数据元素个数较多且变化较大时,操作过程相对复杂,必然导致存储空间的浪费。所有这些问题,都可以通过线性表的另一种表示方法-链式存储结构来解决

排序算法qsort()的原型:

void qsort (void* base, size_t num, size_t size, int (*compar)(const void*,const void*));

其中涉及到函数指针的使用

四、参考引用

数据结构第二版:C语言版【严蔚敏】 第二章 线性表

qsort

原文链接:https://www.cnblogs.com/caojun97/p/17276680.html

本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:顺序表的实现:Book_Manage_System - Python技术站

(0)
上一篇 2023年4月18日
下一篇 2023年4月18日

相关文章

  • C语言 strcat()函数

    当我们需要将两个字符串连接在一起时,可以使用C语言中的strcat()函数。它可以把两个字符串拼接起来,并返回结果字符串的地址。 函数原型 char *strcat(char *dest, const char *src); 该函数有两个参数: dest:需要被追加的目标字符串。 src:需要追加的源字符串。 函数返回值是一个指向目标字符串的指针。需要注意的…

    C 2023年5月9日
    00
  • 减少OpenCV读取高分辨率图像的时间示例

    下面是减少OpenCV读取高分辨率图像时间的完整攻略。 1. 问题背景 当读取高分辨率图像时,OpenCV可能需要较长的时间来加载和处理图像。这会导致我们无法快速地处理图像,例如进行实时图像处理等操作。因此,我们需要采取一些方法来减少OpenCV读取高分辨率图像的时间。 2. 解决方案 以下是减少OpenCV读取高分辨率图像的时间的解决方案: 方案一:降低图…

    C 2023年5月22日
    00
  • C语言实现简单计算器程序

    C语言实现简单计算器程序 实现一个简单的计算器程序可以帮助我们更好地理解C语言的基本语法和逻辑思维方式。下面给出完整的攻略。 步骤一:设计计算器程序 首先,我们需要明确计算器程序的功能和界面。 本程序需要实现以下功能: 支持加、减、乘、除四种基本运算 支持整数和小数的运算 支持多次运算 支持清空和退出功能 程序界面可以设计成如下形式: ===========…

    C 2023年5月23日
    00
  • C语言实现客房管理系统

    C语言实现客房管理系统的完整攻略包含以下几个步骤: 设计数据结构和功能模块 首先需要设计客房管理系统的数据结构和功能模块。根据系统需要,可以设计出以下数据结构: Room:客房信息,包括客房号、类型、价格、当前状态(已入住或未入住)等。 Order:订单信息,包括客房号、入住时间、退房时间、客人姓名等。 根据这些数据结构,可以设计出以下功能模块: Check…

    C 2023年5月23日
    00
  • c++ 探讨奶牛生子的问题

    C++ 探讨奶牛生子的问题 问题描述 有 $N$ 只奶牛,每个奶牛的繁殖周期为 $M$ 年,每只奶牛出生后第 $1$ 年不生育,第 $2$ 年起每年生下一只小奶牛,小奶牛出生后第 $1$ 年也不能生育,第 $2$ 年起也可以生下一只小奶牛。假设所有的奶牛都没有死亡,请问 $T$ 年后一共有多少只奶牛? 解题思路 本题可以采用递归或者动态规划的方式进行求解。我…

    C 2023年5月23日
    00
  • JSON在Java中的使用方法实例

    下面是JSON在Java中的使用方法实例的详细攻略: 什么是JSON JSON是一种轻量级的数据交换格式,全称为JavaScript Object Notation。它是一种易于读写的文本格式,可与几乎所有编程语言一起使用,包括Java。 Java中的JSON库 Java中有多个库可以用于处理JSON,其中最流行的库是GSON和Jackson。这里我们以GS…

    C 2023年5月23日
    00
  • 解析Node.js异常处理中domain模块的使用方法

    解析Node.js异常处理中domain模块的使用方法 在Node.js中,异常处理是一个非常重要的话题,因为错误的产生是运行环境的本质。Node.js提供了一系列的异常处理工具来帮助我们处理错误,其中就包括domain模块。 什么是domain模块 domain模块是Node.js用于处理异步代码中错误的模块。它允许我们将多个异步操作绑定到一个错误处理上下…

    C 2023年5月23日
    00
  • 简单的汉诺塔问题解法代码

    汉诺塔问题是一道常见的算法问题,它涉及到递归算法的应用。在这道问题中,我们需要把一个塔从第一个柱子移动到第三个柱子上,移动的过程中需要遵循以下几个规则: 每次只能移动一个盘子 任何时候,大盘子都不能放在小盘子上面 下面提供一个标准的解法代码: void hannoi(int n, char A, char B, char C) { if (n == 1) {…

    C 2023年5月24日
    00
合作推广
合作推广
分享本页
返回顶部