首先,图书管理系统中每本图书的信息至少包括:书名、编号、作者、出版社。
我们可以将这些内容定义为一个结构体,因为每本图书的信息都有这几个要素:
struct Book
{
char name[15];
int id;
char author[5];
char publish[20];
};//每一本图书的信息内容
但是我们仔细想想,当我们要操作图书管理系统中图书的信息内容时,比如增加图书信息,这时我们需要知道图书管理系统中的图书是否已经到达上限,如果达到上限就无法再添加图书。
所以,我们可以将图书信息和图书管理系统中已有图书本数,一同放入一个结构体中,这样就避免了执行每个功能时都要相同地传入两个变量(图书信息,已有图书本数)。
struct Contact
{
struct Book data[1000];//存放1000本图书的信息
int size;//记录当前已有图书的本数
};
定义好变量后,我们需要将待用内存空间清理一下,并将图书管理系统中起始图书本数设为0,以便使用:
//初始化图书管理系统
void InitContact(struct Contact* ps)
{
memset(ps->data, 0, sizeof(ps->data));//将待用内存空间设置为0
ps->size = 0;//设置图书管理系统最初只有0个元素
}
这样,一个空白的图书管理系统就创建好了!
首先,进入该函数体我们就需要判断图书管理系统内图书本数是否已达上限,达到上限就无法继续添加,如果未达上限,用户就可以输入待添加的图书的信息,而我们可以通过传入的指针找到图书信息应当存放在哪一块内存空间。
添加完成后一定要记得将size,即图书管理系统中图书本数+1。
//添加一本图书的信息
void AddContact(struct Contact* ps)
{
if (ps->size == 1000)
{
printf("图书管理系统已满,无法添加!\n");
}//图书管理系统内图书数量已达上限
else
{
printf("请输入书名:>");
scanf("%s", ps->data[ps->size].name);
printf("请输入编号:>");
scanf("%d", &(ps->data[ps->size].id));
printf("请输入作者:>");
scanf("%s", ps->data[ps->size].author);
printf("请输入出版社:>");
scanf("%s", ps->data[ps->size].publish);
ps->size++;//图书管理系统中图书本数+1
printf("添加成功\n");
}
}
首先,我们需要用户输入待删除图书的书名,并在图书管理系统中查找是否存在该名字的图书。(因为后面还会有此相同的操作,所以将其封装为一个函数,避免代码冗余)
如果找到了此书,我们将其信息进行删除,删除的方法有两种:
虽然第二种方法操作起来比较简单,移动的次数也更少,但是我们还是使用第一种方法进行“删除”,因为第二种方法会捣乱图书的先后顺序。
删除完成后也一定要记得将size,即图书管理系统中图书本数-1。
int FindByName(char name[15],const struct Contact* ps)
{
int i = 0;
for (i = 0; i < ps->size; i++)
{
if (strcmp(ps->data[i].name, name) == 0)
return i;//找到了返回下标
}
return -1;//找不到的情况
}
//删除一本图书的信息
void DeleteContact(struct Contact* ps)
{
char name[15];
printf("请输入要删除图书的书名:>");
scanf("%s", name);
//查找
int pos = FindByName(name, ps);//找到了返回下标,没找到返回-1
//删除
if (pos == -1)
{
printf("查无此书\n");
}
else
{
int j = 0;
for (j = pos; j < ps->size - 1; j++)
{
ps->data[j] = ps->data[j + 1];
}//从要删除的图书位置开始,后一本图书信息覆盖前一本图书信息
printf("删除成功\n");
ps->size--;//图书管理系统中图书本数-1
}
}
首先,我们也需要用户输入待查找图书的书名,如果存在此书我们就将其信息打印出来。
/查找指定联系人并打印其信息
void SreachContact(const struct Contact* ps)
{
char name[15];
printf("请输入要查找图书的书名:>");
scanf("%s", name);
int pos = FindByName(name, ps);//找到了返回下标,没找到返回-1
if (pos == -1)
{
printf("查无此书\n");
}
else
{
printf("%-15s\t%-4s\t%-5s\t%-12s\t\n", "书名", "编号", "作者", "出版社");
printf("%-15s\t%-4d\t%-5s\t%-12s\t\n",
ps->data[pos].name,
ps->data[pos].id,
ps->data[pos].author,
ps->data[pos].publish;
}//打印该图书的信息内容
}
要修改图书信息自然也要先在图书管理系统中找到该书,如果找到了,我们就将该图书信息重新录入一次就行了。
//修改指定图书的信息
void ModifyContact(struct Contact* ps)
{
char name[15];
printf("请输入要修改的图书的书名:>");
scanf("%s", name);
int pos = FindByName(name, ps);//找到了返回下标,没找到返回-1
if (pos == -1)
{
printf("查无此书\n");
}
else
{
printf("请输入书名:>");
scanf("%s", ps->data[pos].name);
printf("请输入编号:>");
scanf("%d", &(ps->data[pos].id));
printf("请输入作者:>");
scanf("%s", ps->data[pos].author);
printf("请输入出版社:>");
scanf("%s", ps->data[pos].publish);
printf("修改成功\n");
}//修改图书信息,即将该图书信息重新录入
}
首先判断图书管理系统是否为空(如果没有图书,那就没有打印的必要了)。如果图书管理系统不为空,我们首先打印一排信息栏,接下来循环size次(即图书本数次),打印每本图书的信息即可。
//打印图书管理系统中的全部信息
void ShowContact(const struct Contact* ps)
{
if (ps->size == 0)
{
printf("图书管理系统为空\n");
}//图书管理系统中图书本数为0
else
{
printf("%-15s\t%-4s\t%-5s\t%-12s\t\n", "书名", "编号", "作者", "出版社");
//打印信息栏
int i = 0;
for (i = 0; i < ps->size; i++)
{
printf("%-15s\t%-4d\t%-5s\t%-12s\t\n",
ps->data[i].name,
ps->data[i].id,
ps->data[i].author,
ps->data[i].publish;
}//打印图书管理系统全部信息内容
}
}
这个排序功能我们可以借助于已有的qosrt函数进行排序,只需要写一个自定义的比较函数即可。
//自定义的比较函数
int CmpByName(const void* e1, const void* e2)
{
return strcmp((const char*)e1, (const char*)e2);
}
//通过名字排序图书管理系统中图书的先后顺序
void SortContact(struct Contact* ps)
{
qsort(ps->data, ps->size, sizeof(struct Book), CmpByName);//排序
}
实现该图书管理系统的代码比较多,为了能够看起来结构清晰,我们需要用3个文件将代码封装:contact.h、contact.c、test.c。
contact.h中存放函数的声明、结构体的定义以及一些库函数的头文件等。
#define _CRT_SECURE_NO_WARNINGS 1
#define MAX 1000
#define MAX_NAME 15
#define MAX_ID 5
#define MAX_AUTHOR 12
#define MAX_PUBLISH 20
#include
#include
#include
enum Option
{
EXIT,//0
ADD,//1
DELETE,//2
SREACH,//3
MODIFY,//4
SHOW,//5
SORT//6
};//增加代码可读性
struct Book
{
char name[MAX_NAME];
int id;
char author[MAX_AUTHOR];
char publish[MAX_PUBLISH];
};//每一本图书的信息内容
//图书管理系统类型
struct Contact
{
struct Book data[MAX];//存放1000本图书的信息
int size;//记录当前已有图书的本数
};
//初始化图书管理系统
void InitContact(struct Contact* ps);
//添加一本图书的信息
void AddContact(struct Contact* ps);
//删除一本图书的信息
void DeleteContact(struct Contact* ps);
//查找指定图书并打印其信息
void SreachContact(const struct Contact* ps);
//修改指定图书的信息
void ModifyContact(struct Contact* ps);
//打印图书管理系统中的全部信息
void ShowContact(const struct Contact* ps);
//通过名字排序图书管理系统中图书的先后顺序
void SortContact(struct Contact* ps);
contact.c中主要就是contact.h中声明的函数的具体实现。
#include "contact.h"
//初始化图书管理系统
void InitContact(struct Contact* ps)
{
memset(ps->data, 0, sizeof(ps->data));//将待用内存空间设置为0
ps->size = 0;//设置图书管理系统最初只有0个元素
}
//添加一本图书的信息
void AddContact(struct Contact* ps)
{
if (ps->size == MAX)
{
printf("图书管理系统已满,无法添加!\n");
}//图书管理系统内图书本数已达上限
else
{
printf("请输入书名:>");
scanf("%s", ps->data[ps->size].name);
printf("请输入编号:>");
scanf("%d", &(ps->data[ps->size].id));
printf("请输入作者:>");
scanf("%s", ps->data[ps->size].author);
printf("请输入出版社:>");
scanf("%s", ps->data[ps->size].publish);
ps->size++;//图书管理系统中图书本数+1
printf("添加成功\n");
}
}
//通过名字查找图书,找到了返回下标,没找到返回-1
static int FindByName(char name[MAX_NAME],const struct Contact* ps)
{
int i = 0;
for (i = 0; i < ps->size; i++)
{
if (strcmp(ps->data[i].name, name) == 0)
return i;//找到了返回下标
}
return -1;//找不到的情况
}
//删除一本图书的信息
void DeleteContact(struct Contact* ps)
{
char name[MAX_NAME];
printf("请输入要删除图书的书名:>");
scanf("%s", name);
//查找
int pos = FindByName(name, ps);//找到了返回下标,没找到返回-1
//删除
if (pos == -1)
{
printf("查无此书\n");
}
else
{
int j = 0;
for (j = pos; j < ps->size - 1; j++)
{
ps->data[j] = ps->data[j + 1];
}//从要删除的图书位置开始,后一本图书信息覆盖前一本图书信息
printf("删除成功\n");
ps->size--;//图书管理系统中图书本数-1
}
}
//查找指定图书并打印其信息
void SreachContact(const struct Contact* ps)
{
char name[MAX_NAME];
printf("请输入要查找图书的书名:>");
scanf("%s", name);
int pos = FindByName(name, ps);//找到了返回下标,没找到返回-1
if (pos == -1)
{
printf("查无此书\n");
}
else
{
printf("%-15s\t%-4s\t%-5s\t%-12s\t\n", "书名", "编号", "作者", "出版社");
printf("%-15s\t%-4d\t%-5s\t%-12s\t\n",
ps->data[pos].name,
ps->data[pos].id,
ps->data[pos].author,
ps->data[pos].publish;
}//打印该图书的信息内容
}
//修改指定图书的信息
void ModifyContact(struct Contact* ps)
{
char name[MAX_NAME];
printf("请输入要修改的图书的书名:>");
scanf("%s", name);
int pos = FindByName(name, ps);//找到了返回下标,没找到返回-1
if (pos == -1)
{
printf("查无此书\n");
}
else
{
printf("请输入书名:>");
scanf("%s", ps->data[pos].name);
printf("请输入编号:>");
scanf("%d", &(ps->data[pos].id));
printf("请输入作者:>");
scanf("%s", ps->data[pos].author);
printf("请输入出版社:>");
scanf("%s", ps->data[pos].publish);
printf("修改成功\n");
}//修改图书信息,即将该图书信息重新录入
}
//打印图书管理系统中的全部信息
void ShowContact(const struct Contact* ps)
{
if (ps->size == 0)
{
printf("图书管理系统为空\n");
}//图书管理系统中图书本数为0
else
{
printf("%-15s\t%-4s\t%-5s\t%-12s\t\n", "书名", "编号", "作者", "出版社");
//打印信息栏
int i = 0;
for (i = 0; i < ps->size; i++)
{
printf("%-15s\t%-4d\t%-5s\t%-12s\t\n",
ps->data[i].name,
ps->data[i].id,
ps->data[i].author,
ps->data[i].publish;
}//打印图书管理系统全部信息内容
}
}
//自定义的比较函数
int CmpByName(const void* e1, const void* e2)
{
return strcmp((const char*)e1, (const char*)e2);
}
//通过名字排序图书管理系统中图书的先后顺序
void SortContact(struct Contact* ps)
{
qsort(ps->data, ps->size, sizeof(struct Book), CmpByName);//排序
}
test.c中就存放主函数(main函数),也就是通讯录主要的逻辑。
#include "contact.h"
void menu()
{
printf("|-----------------------|\n");
printf("| contact |\n");
printf("| 1.Add 2.Delete |\n");
printf("| 3.Search 4.Modify |\n");
printf("| 5.Show 6.Sort |\n");
printf("| 0.Exit |\n");
printf("|-----------------------|\n");
}//打印菜单
int main()
{
int input = 0;
//创建图书管理系统
struct Contact con;//con就是图书管理系统,里面包含1000个元素的数组和size
//初始化图书管理系统
InitContact(&con);
do
{
menu();
printf("请选择:>");
scanf("%d", &input);
switch (input)
{
case ADD:
AddContact(&con);
break;
case DELETE:
DeleteContact(&con);
break;
case SREACH:
SreachContact(&con);
break;
case MODIFY:
ModifyContact(&con);
break;
case SHOW:
ShowContact(&con);
break;
case SORT:
SortContact(&con);
break;
case EXIT:
printf("退出图书管理系统\n");
break;
default:
printf("选择错误,请重新选择\n");
break;
}
} while (input);
return 0;
}
注意:
1> 运用枚举,可以增加代码的可读性,避免自己写代码以及别人阅读代码时不明确0,1,2,3,4,5,6的具体意义。
2> 用#define定义一些常用数据,如图书本数1000,以便之后需要修改时只需修改一处,而不是修改全部用到1000的地方。
点击此处,浏览图书管理系统进阶内容