图书馆管理系统【源码】

                                        

 可能稍微有点长,可以各取所需,建议先看前80行,或者直接看创建链表,查找和删除等模块

加油朋友,加油朋友,加油朋友,加油朋友

 https://download.csdn.net/download/weixin_42415731/11187856?spm=1001.2101.3001.6650.1&utm_medium=distribute.pc_relevant.none-task-download-2%7Edefault%7EOPENSEARCH%7ERate-1-11187856-blog-127061137.pc_relevant_vip_default&depth_1-utm_source=distribute.pc_relevant.none-task-download-2%7Edefault%7EOPENSEARCH%7ERate-1-11187856-blog-127061137.pc_relevant_vip_default&utm_relevant_index=2https://download.csdn.net/download/weixin_42415731/11187856?spm=1001.2101.3001.6650.1&utm_medium=distribute.pc_relevant.none-task-download-2~default~OPENSEARCH~Rate-1-11187856-blog-127061137.pc_relevant_vip_default&depth_1-utm_source=distribute.pc_relevant.none-task-download-2~default~OPENSEARCH~Rate-1-11187856-blog-127061137.pc_relevant_vip_default&utm_relevant_index=2

#include<stdio.h>
#include<stdlib.h>//包含动态内存分配malloch函数
#include<string.h>//包含字符串处理函数
typedef struct Book {//声明节点
	int num;
	char name[30];
	int amount;
	int kind;//种类0-5表示不同类别:专必专选、公必公选、大英小说
	struct Book* next;//节点数据结构
} Book; 
 
void menu();         //声明各个函数
Book* creat();
void print(Book*);
void insert(Book*);
void Delete(Book*);
void SearchName(Book*);
void DeleteKind(Book*);
void Modify(Book*);
void SearchKind(Book*);
void QsortKind(Book*, Book*);
Book* GetPartion(Book*, Book*);
void Swap(Book*, Book*);
Book* Gettail(Book*);
void QsortNum(Book*, Book*);
Book* GetPartion2(Book*, Book*);
void QsortAmount(Book*, Book*);
Book* GetPartion3(Book*, Book*);
 
int main()           //主函数
{
	menu();
    return 0;
}
void menu()     //菜单函数
{
	int n, i = 1;
	Book* head;     //定义头尾指针
	Book* tail;
	double time;
	while (i == 1)
	{
		printf("\n");
		printf("|-----------------------------------------------------------------|\n");
		printf("|欢迎使用李氏图书管理系统                                         |\n");
		printf("|输入1创建链表并导入图书信息、输入2输出链表、输入3插入            |\n");
		printf("|输入4删除、输入5查找、输入6按种类排序、输入7修改                 |\n");
		printf("|输入8按类别删除、输入9按类别查找、10按编号排序、11按数量排序     |\n");
		printf("|-----------------------------------------------------------------|\n");
		printf("请输入:");
		scanf("%d", &n);
		printf("\n");
		switch (n)
		{
		case 1:head = creat(); break;
		case 2:print(head); break;
		case 3:insert(head); break;
		case 4:Delete(head); break;
		case 5:SearchName(head); break;
		case 6:tail = Gettail(head); QsortKind(head->next, tail); printf("排序完成\n"); break;//排序函数传入链表头尾节点,head->next是跳过头结点指向第一个有用的节点,tail指向链表末尾最后一个节点
		case 7:Modify(head);break;
		case 8:DeleteKind(head); break;
		case 9:SearchKind(head); break;
		case 10:tail = Gettail(head); QsortNum(head->next, tail); printf("排序完成\n"); break;
		case 11:tail = Gettail(head); QsortAmount(head->next, tail); printf("排序完成\n"); break;
		default:printf("输入错误\n"); i = 0;
		}
	}
}
/*********************************************************************
先用creat函数创建链表并导入图书文件信息,然后返回指向所创建链表的指针,
就能根据该指针找到所创建的链表并执行各种操作;
这些各种操作的函数基本都是在顺序遍历链表的同时外加一个判断条件,
符合该条件就执行一组操作,否则就继续遍历,直到遍历完全
另,给字符数组赋初值可用strcpy函数
*********************************************************************/
Book* creat()     //创建链表并导入图书信息的函数,返回指向所创建链表的指针
{
	Book* p1, * p2;     //h为头结点,p1用来开辟新节点,p2用来指向当前链表最后一个节点;用p2->next=p1建立连接关系
	Book* head;
	Book* h;
	h = (Book*)malloc(sizeof(Book));
	h->num = h->amount = h->kind = -1;         //给头结点赋初值,并初始化h->next为空
	strcpy(h->name, "null");                 //用字符串复制函数给头结点的name数组赋初值,直接赋值的话会有错
	h->next = NULL;
	head = p2 = h;                            //head和p2指向头结点h
	p1 = (Book*)malloc(sizeof(Book));         //开辟新单元,并使p1指向它
	printf("链表创建成功\n");
 
	FILE* fp;
	fp = fopen("D:\\Grade2_a\\数据结构c语言\\图书管理系统\\Book.txt", "r");
	if (fp == NULL)
		printf("error\n");
	while (1)     //把文件信息逐个导入;fscanf函数的返回值是导入参数的个数,如果每行都导入了4个参数就是正确的,否则就说明全部信息已导入完成
	{
		if (fscanf(fp, "%d %s %d %d", &p1->num, p1->name, &p1->amount, &p1->kind) == 4)//注意字符数组不用取址符
		{
			p2->next = p1;
			p2 = p1;
			p1 = (Book*)malloc(sizeof(Book));
		}
		else
		{
			p2->next = NULL;
			break;
		}
	}
	fclose(fp);
	printf("图书信息导入成功\n");
	printf("\n");
	return(head);
}
void print(Book* head)      //打印链表的函数(参数是指向链表的指针);先使p指向头结点,如果p->next!=NULL,就把p的下一个节点打印出来
{
	Book* p = head;
	printf("输出的图书信息为:\n"); 
	printf("\n");
	printf("编号    书名                           数量       种类\n");     //在打印前加这句话是用来说明接下来打印出的图书信息
	while (p->next != NULL)
	{   
		p = p->next;
		printf("%-7d %-30s %-10d %-10d\n", p->num, p->name, p->amount, p->kind);//这格式控制和上面加的一行说明都是凭感觉搞的,print、SearchName和SearchKind函数都用到这两个输出语句
	}
	printf("\n");
}
void insert(Book* head)      //插入到表尾的函数,用while(p->next!=NULL)这个循环条件遍历链表并找到链表最后一个节点
{
	Book* p = head;
	Book* r;
	r = (Book*)malloc(sizeof(Book));
	printf("请输入要插入的书籍信息(按编号、书名、数量、种类的顺序输入):\n");
	scanf("%d %s %d %d", &r->num, r->name, &r->amount, &r->kind);
	while (p->next != NULL)
	{
		p = p->next;
	} 
	p->next = r;   //插入到表尾的核心语句
	r->next = NULL;
	printf("已插入\n");
	printf("\n");
}
void SearchName(Book*head)      //按书名搜索的函数;用while (strcmp(p->name, name) != 0 && p->next != NULL)作为循环条件遍历链表查找书名
{
	Book* p = head;
	char name[30];
	printf("请输入你想查找的书名:\n");
	scanf("%s", name);
	if (p->next == NULL) printf("链表为空,无法查询\n");//表空时直接打印链表为空无法查询
	p = p->next;
	while (strcmp(p->name, name) != 0 && p->next != NULL)     //注意是p->nex!=NULL,不是p!=NULL
	{
		p = p->next;
	}      //退出循环有两种可能:一是在前面的节点就找到了;一是前面的节点都不是,已经遍历到链表的最后一个节点,这种情况要对最后一个节点再进行一次判断
	if (strcmp(p->name, name) == 0)
	{
		printf("已为你查找,书籍信息如下:\n");
		printf("\n");
		printf("编号    书名                           数量       种类\n");
		printf("%-7d %-30s %-10d %-10d\n", p->num, p->name, p->amount, p->kind);
	}
	else printf("查无此书\n");
	printf("\n");
}
void DeleteKind(Book* head)     //按类别删除的函数;遍历每个节点,对每个节点都进行判断,如果是要删的就删掉,再判断下一个;不是的话就直接判断下一个
{
	int kind;
	Book* p1, * p2;
	p1 = p2 = head;
	printf("请输入你想删除的类别:");
	scanf("%d", &kind);
	if (p1->next == NULL) printf("链表为空,无法删除\n");
	p1 = p1->next;
	while (p1 != NULL)
	{
		if (p1->kind == kind)
		{
			p2->next = p1->next;
			free(p1);
			p1 = p2->next;
		}
		else
		{
			p2 = p1;
			p1 = p1->next;
		}
	}
	printf("已删除\n");
	printf("\n");
}
void SearchKind(Book* head)     //按类别查找的函数;遍历每个节点,对每个节点都进行判断,如果类别一样就打印出来再判断下一个;类别不一样就跳过,接着判断下一个
{
	int kind;
	Book* p = head;
	printf("请输入你想查找的类别:");
	scanf("%d", &kind);
	if (p->next == NULL) printf("链表为空,无法查找\n");
	p = p->next;
	printf("已为你查找,书籍信息如下:\n");
	printf("\n");
	printf("编号    书名                           数量       种类\n");
	while (p != NULL)
	{
		if (p->kind == kind)
		{
			printf("%-7d %-30s %-10d %-10d\n", p->num, p->name, p->amount, p->kind);
			p = p->next;
		}
		else p = p->next;
	}
	printf("\n");
}
void Delete(Book* head)     //按编号删除的函数
{
	Book* p1, * p2;
	p1 = p2 = head;
	int num;
	printf("请输入你想删除的书本编号:");
	scanf("%d", &num);
	if (p1->next == NULL) printf("链表为空,无法删除\n");
	p1 = p1->next;
	while (p1 != NULL && p1->num != num)      //这里有个细节,写p1!=NULL和写p1->next!=NULL,这两种情况后面的if语句不一样,需要自己画个链表流程判断该怎么写
	{
		p2 = p1;
		p1 = p1->next;
	}
	if (p1 == NULL) printf("找不到你要删的图书编号\n");
	else
	{
		p2->next = p1->next;
		free(p1);
		printf("已删除\n");
	}
	printf("\n");
}
void Modify(Book* head)      //按编号修改的函数
{
	Book* p = head;
	int num;
	printf("请输入你想修改的图书编号:");
	scanf("%d", &num);
	if (p->next == NULL) printf("链表为空,无法修改\n");
	p = p->next;
	while (p->next != NULL && p->num != num)
	{
		p = p->next;
	}
	if (p->num == num)
	{
		printf("请输入修改后的书籍信息(按编号、书名、数量、种类的顺序输入):\n");
		scanf("%d %s %d %d", &p->num, p->name, &p->amount, &p->kind);
		printf("已修改\n");
		printf("\n"); 
	}
	else printf("找不到你要修改的图书编号\n");
	printf("\n");
}
/*************************************************************
排序函数用快速排序的方法,分成值交换交换模块、找到支点模块和排序核心递归模块
**************************************************************/
Book* Gettail(Book* head)//得到链表尾指针的函数
{
	Book* p = head;
	while (p->next != NULL)
		p = p->next;
	return p;//返回链表尾指针
}
void Swap(Book* p1, Book* p2)//两个指针所指向的值的值交换函数
{
	Book* tmp;
	tmp = (Book*)malloc(sizeof(Book));
	tmp->next = NULL;
	tmp->num = p1->num; 
	strcpy(tmp->name, p1->name); 
	tmp->amount = p1->amount; 
	tmp->kind = p1->kind;
	p1->num = p2->num; 
	strcpy(p1->name, p2->name); 
	p1->amount = p2->amount; 
	p1->kind = p2->kind;
	p2->num = tmp->num; 
	strcpy(p2->name, tmp->name); 
	p2->amount = tmp->amount; 
	p2->kind = tmp->kind;
	free(tmp);
}
Book* GetPartion(Book* pbegin, Book* pend)//找到支点的函数
{
	int kind = pbegin->kind;
	Book* p1 = pbegin;
	Book* p2 = p1->next;
	while(p2 != pend->next)//p2 != pend->next说明还未遍历到链表末尾,继续循环
	{ 
	    if(p2->kind < kind) // 比较,交换链表值,这里是按种类排序所以就比较种类
	    {
		    p1 = p1->next;
		    Swap(p1, p2);
		    p2 = p2->next;
	    }
		else
			p2 = p2->next;
	}
	Swap(pbegin, p1);
	return p1;
}
void QsortKind(Book* pbegin, Book* pend)//排序核心递归函数,一开始只需传入(head->next,tail)即可,执行一组操作(把链表值交换,没有改变指针的指向),不需要返回值
{
	Book* partion;
	Book* parnext; 
	partion = GetPartion(pbegin, pend);//调用函数找partion
	parnext = partion->next;
	if (partion != pbegin && partion != pend)//下面分三种情况,GetPartion函数结束时,返回的指针p1的位置分为3种:p1指向pbegin;p1指向pend;p1指向中间某处,这里是指向中间的情况,这时p1两边都要继续排序
	{
		QsortKind(pbegin, partion);
		QsortKind(parnext, pend);
	}
	else if (partion != pbegin && partion == pend)//这时p1指针已经移到pend处,说明这次的p2一直小于pbegin,导致p1一直往后移;这时只需排p1前面的
		QsortKind(pbegin, partion);
	else if (partion == pbegin && parnext != pend)//这时p1指针还在初始pbegin的位置,说明这次的p2一直>=pbegin,导致p1一直没动;这时只需排p1后面的
		QsortKind(parnext, pend);
}
 
void QsortNum(Book* pbegin, Book* pend)
{
	Book* partion;
	Book* parnext;
	partion = GetPartion2(pbegin, pend);
	parnext = partion->next;
	if (partion != pbegin && partion != pend)
	{
		QsortNum(pbegin, partion);
		QsortNum(parnext, pend);
	}
	else if (partion != pbegin && partion == pend)
		QsortNum(pbegin, partion);
	else if (partion == pbegin && partion != pend)
		QsortNum(parnext, pend);
}
Book* GetPartion2(Book* pbegin, Book* pend)
{
	int num = pbegin->num;
	Book* p1 = pbegin;
	Book* p2 = p1->next;
	while (p2 != pend->next)
	{
		if (p2->num < num)
		{
			p1 = p1->next;
			Swap(p1, p2);
			p2 = p2->next;
		}
		else
			p2 = p2->next;
	}
	Swap(pbegin, p1);
	return p1;
}
 
void QsortAmount(Book* pbegin, Book*pend)
{
	Book* partion, * parnext;
	partion = GetPartion3(pbegin, pend);
	parnext = partion->next;
	if (partion != pbegin && partion != pend)
	{
		QsortAmount(pbegin, partion);
		QsortAmount(parnext, pend);
	}
	else if (partion != pbegin && partion == pend)
		QsortAmount(pbegin, partion);
	else if (partion == pbegin && partion != pend)
		QsortAmount(parnext, pend);
}
Book* GetPartion3(Book*pbegin, Book*pend)
{
	int amount = pbegin->amount;
	Book* p1 = pbegin;
	Book* p2 = p1->next;
	while (p2 != pend->next)
	{
		if (p2->amount >= amount)
			p2 = p2->next;
		else
		{
			p1 = p1->next;
			Swap(p1, p2);
			p2 = p2->next;
		}
	}
	Swap(p1, pbegin);
	return p1;
}

这是一个比较复杂的数据库 包含图书管理 借书还书 学生管理 老师管理 和数据连接的相关应用 代码有详细的解释 压缩包里面也有 数据库的文件 代码里设置的数据库 用户是 sa 密码是 123456 请使用的时候做相关的修改 下面给出 一部分的代码 请继续关注本资源的发布 会后面有很多实用的代码上传 using System.Windows.Forms; namespace LibraryMis { public class DatabaseAccess { /* 声明成员变量,这样这个类中的所有方法就可是使用这些变量了 */ private SqlConnection myConnection; private SqlCommand myCommand; private SqlDataAdapter myDataAdapter; private DataSet mySet = new DataSet(); /* 写该类的构造方法,该方法名要跟类名相同,无返回值 * 当new这个类时就会执行这个构造方法 */ public DatabaseAccess() { /* 获得保存连接字符串的文件名及路径 */ //获得应用程序路径 string exePath = AppDomain.CurrentDomain.SetupInformation.ApplicationBase; //根据路径和文件名构建FileInfo对象 string fileName = exePath + "connectionString.txt"; //建立FileInfo对象 FileInfo f = new FileInfo(fileName); //判断该文件是否存在 if (f.Exists)//文件存在 { //获得文件内容即存在文件中的连接字符串 //打开文件,获得读文件的数据流对象 StreamReader sr = f.OpenText(); //读文件到变量中 string connectionString = sr.ReadToEnd(); //关闭流 sr.Close(); //由读出的连接字符串创建Connection对象 myConnection = new SqlConnection(connectionString); //由Connection对象创建Command对象 myCommand = myConnection.CreateCommand(); //创建DataAdapter对象 myDataAdapter = new SqlDataAdapter(); myDataAdapter.SelectCommand = myCommand; //创建CommandBuilder对象 SqlCommandBuilder cb = new SqlCommandBuilder(myDataAdapter); //尝试是否能够打开连接 try { myConnection.Open(); } catch (Exception ex) //打开连接出错,可能是连接字符串有问题,这里调用数据库访问设置窗体来重新设置服务器名和数据库名 { MessageBox.Show("连接不到数据库LibraryMis,请在“数据库访问设置窗体中对数据库访问进行正确的设置”" + ",取消登录后重新启动图书馆管理系统!","警告",MessageBoxButtons.OK,MessageBoxIcon.Warning ); //创建 数据库访问设置窗体,并显示 FormSetDatabase fmsd = new FormSetDatabase(); fmsd.ShowDialog(); } finally { try { myConnection.Close(); } catch (Exception ex) { } } return; } else //文件不存在 { //设置默认的连接字符串 string connectionString = "server=.;database=LibraryMis;uid=sa;pwd=123456"; //把这个字符串写入文件 StreamWriter sw = new StreamWriter(fileName); sw.Write(connectionString); sw.Close(); MessageBox.Show("文件" + fileName + "不存在,已创建该文件,请重新启动图书馆管理系统","警告",MessageBoxButtons.OK, MessageBoxIcon.Information); return; } } /*创建查询的方法,返回数据集对象DataSet,参数SelectString表示查询的Sql语句,TableName表示要查询的表名*/ public DataSet FillDataSet(string SelectString, string TableName) { myDataAdapter.SelectCommand.CommandText = SelectString;//设置查询的Sql语句 myDataAdapter.Fill(mySet,TableName); return mySet; } /*执行插入,更新,修改的操作,参数CommandString表示Sql语句*/ public void ExeCommand(string CommandString) { myCommand.CommandText = CommandString; myConnection.Open(); try { myCommand.ExecuteNonQuery(); } catch (Exception ex) { MessageBox.Show(ex.ToString(),"警告",MessageBoxButtons.OK,MessageBoxIcon.Warning); } finally { myConnection.Close(); } } /*执行存储过程的方法,参数为Command对象*/ public void ExeStoreProcedure(SqlCommand command) { command.Connection = myConnection; myCommand = command; myConnection.Open(); try { myCommand.ExecuteNonQuery(); } catch (Exception ex) { MessageBox.Show(ex.ToString(), "警告", MessageBoxButtons.OK, MessageBoxIcon.Warning); } finally { myConnection.Close(); } }
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值