C语言的一个课程设计
题目
图书期刊信息管理系统
阅览室对所收藏的图书与期刊信息实现计算机管理,为用户提供图书信息的查询。阅览室陈列若干工具书、期刊和其他书籍供读者在阅览室内查阅。同一刊物可以有去年和当年的多期同时放在书架上。阅览室的图书信息使用文件保存,按照书名排序。有新书刊到达时,工作人员将新书的信息添加到文件中。书籍的信息包括书刊编号、书名、出版单位、出版时间、价格、书籍分类号等,其中,期刊的书名包括刊物名称与年份期数,例如:读者-2014-21。每年的7月份开始,上一年的期刊将陆续从书架上撤走,装订成册,变成合订本上架,同时,图书信息文件中要刑去这些已经撤走的过期期刊的信息,添加合订本期刊的信息,例如,书名为读者-2014合。
图书期刊信息管理系统提供对书籍信息的录入与删除功能,提供图书信息的浏览与查询功能。其中,查询可以是对书名、出版单位、书籍分类号的模糊查询。例如,按书名查询时,输人“计算”,可以查到书名中含有“计算”字样的书刊,如计算方法(书籍)、微型计算机(期刊)、计算机工程(期刊)、英汉计算技术词典(工具书)等,这些都是符合条件的查询结果。再如,按照出版单位查询时,输入“大学”进行查询,则将阅览室收藏的所有大学出版社出版的书刊名称列出。按书籍分类号查询时,只要分类号前几位与所提供的相符即是符合条件。
需求分析
书籍的信息包括书刊编号、书名、出版单位、出版时间、价格、书籍分类号,需要定义一个book的结构体,包含以上信息,还要定义一个next指针,实现链表操作。
书籍信息按书名首写字母排序存放进文件中,书籍信息以空格或制表符分开,每一行存放不同的书籍信息。
程序所需要完成的功能是对书籍信息的录入与删除功能,提供图书信息的浏览与查询功能。
程序首先从文件中读取数据放进链表中,接下来的增加删除录入查询操作基于链表实现。
其中,增加结点时,是在链表尾部加一个结点,然后对链表进行排序,保证链表中的结点是按照书名从小到大排序。删除功能就是输入信息,找到这个结点并删除。浏览功能将文件中存储的全部书籍信息输出,查询功能输入信息,遍历链表,通过字符串匹配查找结点,若成功找到就输出结点信息。其中查询功能又分为按书名查找,按出版单位查找,按书籍分类号查找。程序结束时将链表写入文件中,更新文件信息。
概要设计
系统的模块划分
根据需求分析对系统进行下图所示的功能模块划分。
数据文件
本系统作为书籍信息来源的信息文件是file.txt,在程序中通过#define filename “file.txt”预定义。
在文本文件中,每本书籍的数据各占一行,每两项数据之间以空格或制表符分开,不含有表头文字。文件内容如下形式:分别对应书籍编号,书名,出版单位,出版时间年,出版时间月,价格和书籍分类号。
具体代码
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#define filename "file.txt"
typedef struct book {
int num;//书刊编号
char name[50];//书名
char chuban[50];//出版单位
int year;//出版时间年
int month;//出版时间月
int price;//价格
char fenlei[10];//书籍分类号
struct book *next;
}Book;
Book *creat1();//读取文件中的信息存入到链表中
Book *creat2();//手动增加信息创建链表
void output(Book *head);//显示所有结点信息
Book *Delete(Book *head);//删除链表中的一个结点信息
Book *Add(Book *head);//增加结点信息
Book *Sort(Book *head);//排序
void Refer1(Book *head);//输入书名查询结点信息
void Refer2(Book *head);//输入出版单位查询结点信息
void Refer3(Book *head);//输入书籍分类号查询结点信息
//Book *Update(Book *head);//更新结点信息
void Save(Book *head);//将链表中的信息保存至文件中
int main()
{
Book *head;
int a, b, w = 1;
while (w)
{
printf("*****************************************\n");
printf("* 图书期刊信息管理系统 *\n");
printf("* 1.书籍信息录入(从文件中读取). *\n");
printf("* 2.书籍信息录入(手动增加). *\n");
printf("*****************************************\n");
scanf("%d", &a);
if (a == 1)
{
head = creat1(); w = 0;
}
else if (a == 2)
{
head = creat2();
head=Sort(head);
w = 0;
}
else break;
}
while (1)
{
system("cls");
printf("*****************************************\n");
printf("* 图书期刊信息管理系统 *\n");
printf("* 1.书籍信息增加. *\n");
printf("* 2.书籍信息删除. *\n");
printf("* 3.书籍信息的浏览. *\n");
printf("* 4.书籍信息的查询(按书名) *\n");
printf("* 5.书籍信息的查询(按出版单位) *\n");
printf("* 6.书籍信息的查询(按书籍分类号 *\n");
printf("* 7.退出. *\n");
printf("*****************************************\n");
scanf("%d", &b);
switch (b)
{
case 1:
head = Add(head);
head = Sort(head);
system("pause");
break;
case 2:
head = Delete(head);
system("pause");
break;
case 3:
output(head);
system("pause");
break;
case 4:
Refer1(head);
system("pause");
break;
case 5:
Refer2(head);
system("pause");
break;
case 6:
Refer3(head);
system("pause");
break;
case 7:
Save(head);
return 0;
default:
printf("输入的信息错误,请重新输入!\n");
break;
}
}
return 0;
}
Book *creat1()//读取文件中的信息存入到链表中
{
FILE *fp;
int k = 0; Book st, *p, *p0 = NULL, *head = NULL;
fp = fopen(filename, "r");
if (fp == NULL)
{
printf("打开文件失败!\n");
exit(0);
}
while (!feof(fp))
{
fscanf(fp, "%d%s%s%d%d%d%s", &st.num, st.name, st.chuban, &st.year, &st.month, &st.price, st.fenlei);
p = (Book *)malloc(sizeof(Book));
*p = st;
(*p).next = NULL;
if (p0 == NULL)
{
head = p; p0 = p;
}
else {
(*p0).next = p; p0 = p;
}
}
fclose(fp);
printf("录入成功!\n");
system("pause");
return head;
}
Book *creat2()//手动增加信息创建链表
{
Book *p, *head = NULL, *p0 = NULL;
Book pnew;
Book *q = head;
char ch;
int w = 1;
while (w)
{
printf("请输入增加的书籍信息\n");
printf("书刊编号:");
scanf("%d", &pnew.num);
printf("书名:");
scanf("%s", pnew.name);
printf("出版单位:");
scanf("%s", pnew.chuban);
printf("出版时间:");
scanf("%d%d", &pnew.year, &pnew.month);
printf("价格:");
scanf("%d", &pnew.price);
printf("书籍分类:");
scanf("%s", pnew.fenlei);
while (q!= NULL)//
{
if ((*q).num == pnew.num)
{
printf("您输入的书籍信息已经存在!请重新输入\n");
system("pause");
break;
}
q = (*q).next;
}
if (q != NULL)continue;
else{
p = (Book *)malloc(sizeof(Book));
*p = pnew;
(*p).next = NULL;
if (p0 == NULL)
{
head = p; p0 = p;
}
else {
(*p0).next = p; p0 = p;
}
printf("插入成功!\n");
printf("是否继续插入(Y/N)");
scanf("\n%c", &ch);
if (ch =='N' || ch == 'n')
w = 0;
}
}
return head;
}
void Save(Book *head)//将链表中的信息保存至文件中
{
Book *p = head;
FILE *fp;
fp = fopen(filename, "w");
if (fp == NULL)
{
printf("打开文件失败!\n");
exit(0);
}
while ((*p).next != NULL)
{
fprintf(fp, "%d\t%s\t%s\t%d\t%d\t%d\t%s\n", (*p).num, (*p).name, (*p).chuban, (*p).year, (*p).month, (*p).price, (*p).fenlei);
p = (*p).next;
}
fprintf(fp, "%d\t%s\t%s\t%d\t%d\t%d\t%s", (*p).num, (*p).name, (*p).chuban, (*p).year, (*p).month, (*p).price, (*p).fenlei);
fclose(fp);
}
void output(Book *head)
{
Book *p = head;
if (p != NULL)
{
printf("所有图书信息如下:\n");
printf("编号\t书名\t出版单位\t出版时间\t价格\t书籍分类\n");
do {
printf("%d\t%10s\t%10s\t%d-%d\t%d\t%s\n", (*p).num, (*p).name, (*p).chuban, (*p).year, (*p).month, (*p).price, (*p).fenlei);
p = (*p).next;
} while (p != NULL);
printf("\n");
}
else printf("书籍信息为空!\n");
}
Book* Delete(Book *head)//删除链表中的一个结点信息
{
Book *p = head, *p0 = NULL;
int n;
printf("请输入要删除的书刊编号:");
scanf("%d", &n);
while (p)
{
if ((*p).num == n)
{
if (p == head)head = (*p).next;
else if ((*p).next == NULL)(*p0).next = NULL;
else (*p0).next = (*p).next;
free(p);
break;
}
else
{
p0 = p;
p = (*p).next;
}
}
if (p == NULL)printf("找不到信息!\n");
else printf("删除成功!\n");
return head;
}
//
Book* Add(Book *head)//增加结点信息
{
Book *p = head;
Book *pnew;
Book *q= head;
int w = 1;
while (w)
{
pnew = (Book*)malloc(sizeof(Book));
printf("请输入增加的书籍信息\n");
printf("书刊编号:");
scanf("%d", &(*pnew).num);
printf("书名:");
scanf("%s", (*pnew).name);
printf("出版单位:");
scanf("%s", (*pnew).chuban);
printf("出版时间:");
scanf("%d%d", &(*pnew).year, &(*pnew).month);
printf("价格:");
scanf("%d", &(*pnew).price);
printf("书籍分类:");
scanf("%s", (*pnew).fenlei);
while (q != NULL)//遍历链表,若插入的信息已经存在,则退出
{
if ((*q).num == (*pnew).num)
{
printf("您输入的书籍信息已经存在!");
system("pause");
return head;
}
q = (*q).next;
}
if ((*p).next != NULL){
while ((*p).next != NULL)//让尾指针循环直到最后一个结点
p = (*p).next;
}
p->next = pnew;
p = pnew;
p->next = NULL;
printf("插入成功!\n");
w = 0;
}
return head;
}
//选择排序,交换结点
Book* Sort(Book *head)//排序
{
Book *begin = NULL, *end = NULL;//链表的首尾结点指针
Book *p;
Book *min, *premin;//最小结点及其前一个结点
if (!head)return NULL;
while (head) {
//循环找出链表中的最小结点
p = head;
min = p;
while ((*p).next != NULL) {
if (strcmp((*min).name, (*(*p).next).name) > 0) {
premin = p;
min = (*p).next;
}
p = p->next;
}
//将min放进有序链表
if (begin == NULL)
{
begin = end = min;
}
else {
(*end).next = min;
end = min;
}
//在无序链表中删除min
if (min == head) {
head = (*min).next;
}
else {
(*premin).next = (*min).next;
}
}
(*end).next = NULL;
return begin;
}
void Refer1(Book *head)
{
Book *p = head;
char ch[10];
int flag = 0;
printf("请输入待查询的内容:");
scanf("%s", ch);
printf("查询到的信息如下;\n");
printf("编号\t书名\t出版单位\t出版时间\t价格\t书籍分类\n");
while (p != NULL)
{
char *res; int a;
res = (char*)memchr((*p).name, ch[0], strlen((*p).name)); //根据要查找的字符串第一个字符,切割源字符串
if (res != NULL)
{
a = memcmp(res, ch, strlen(ch)); //比较
if (a == 0)
{
printf("%d\t%10s\t%10s\t%d-%d\t%d\t%s\n", (*p).num, (*p).name, (*p).chuban, (*p).year, (*p).month, (*p).price, (*p).fenlei);
flag++;
}
}
p = (*p).next;
}
if (flag > 0) printf("共有%d条记录!\n", flag);
else printf("无任何结果!\n");
}
void Refer2(Book *head)
{
Book *p = head;
char ch[10];
int flag = 0;
printf("请输入待查询的内容:");
scanf("%s", ch);
printf("查询到的信息如下;\n");
printf("编号\t书名\t出版单位\t出版时间\t价格\t书籍分类\n");
while (p != NULL)
{
char *res; int a;
res = (char*)memchr((*p).chuban, ch[0], strlen((*p).chuban)); //根据要查找的字符串第一个字符,切割源字符串
if (res != NULL)
{
a = memcmp(res, ch, strlen(ch)); //比较
if (a == 0)
{
printf("%d\t%10s\t%10s\t%d-%d\t%d\t%s\n", (*p).num, (*p).name, (*p).chuban, (*p).year, (*p).month, (*p).price, (*p).fenlei);
flag++;
}
}
p = (*p).next;
}
if (flag > 0) printf("共有%d条记录!\n", flag);
else printf("无任何结果!\n");
}
void Refer3(Book *head)
{
Book *p = head;
char ch[10];
int flag = 0;
printf("请输入待查询的内容:");
scanf("%s", ch);
printf("查询到的信息如下;\n");
printf("编号\t书名\t出版单位\t出版时间\t价格\t书籍分类\n");
while (p != NULL)
{
char *res; int a;
res = (char*)memchr((*p).fenlei, ch[0], strlen((*p).fenlei)); //根据要查找的字符串第一个字符,切割源字符串
if (res != NULL)
{
a = memcmp(res, ch, strlen(ch)); //比较
if (a == 0)
{
printf("%d\t%10s\t%10s\t%d-%d\t%d\t%s\n", (*p).num, (*p).name, (*p).chuban, (*p).year, (*p).month, (*p).price, (*p).fenlei);
flag++;
}
}
p = (*p).next;
}
if (flag > 0) printf("共有%d条记录!\n", flag);
else printf("无任何结果!\n");
}
运行结果
读取数据
可以从文件中读取,也可以自己手动输入
从文件中读取数据创建链表
测试程序的增加节点功能
测试程序的浏览功能,可以看到上一个图增加的结点信息!
测试函数的删除功能
删除之后再进行浏览,可以看到结点信息已被删除
测试函数的查询功能
输入内容,可以找出含有该内容的信息。
按书名来查询信息
按出版社来查询信息
按书籍分类号来查询信息