基于单链表实现通讯管理系统!(有完整源码!)

                                                                                个人主页:秋风起,再归来~

                                                                                文章专栏:C语言实战项目                              

                                                                        个人格言:悟已往之不谏,知来者犹可追

                                                                                        克心守己,律己则安!

1、前言

友友们,这篇文章是基于单链表来实现通讯管理系统的,所以一定要先看完我之前写过的一篇关于单链表的实现(文章链接的文章哦~

其实基于单链表实现通讯录的思路与基于顺讯表实现通讯录的思路是一样的,在这里我就不进行赘述了。如果还没有看过我之前写的一篇基于顺序表实现通讯录(文章链接的宝子们一定要去看看哦~

2、各种接口的实现

以下是我们希望实现的接口~

//contact.h
#pragma once
#define NAME_MAX 100
#define SEX_MAX 4
#define TEL_MAX 11
#define ADDR_MAX 100

//前置声明
typedef struct SListNode contact;

//用户数据
typedef struct PersonInfo
{
    char name[NAME_MAX];
    char sex[SEX_MAX];
    int age;
    char tel[TEL_MAX];
    char addr[ADDR_MAX];
}PeoInfo;

//初始化通讯录
void InitContact(contact** con);

//添加通讯录数据
void AddContact(contact** con);

//展示通讯录数据
void ShowContact(contact* con);

//删除通讯录数据
void DelContact(contact** con);

//查找通讯录数据
void FindContact(contact* con);

//修改通讯录数据
void ModifyContact(contact** con);

//销毁通讯录数据
void DestroyContact(contact** con);

2.1 初始化通讯录

我们希望在初始化通讯录时导入之前我们原有文件中的数据,那我们就可以进行如下的操作~

//从文件中导入原数据
void DLoadContact(contact** con)
{
	FILE* pf = fopen("contact.txt", "rb");
	if (pf == NULL)
	{
		perror("open fail\n");
		return;
	}
	PeoInfo p = { 0 };
	while (fread(&p, sizeof(PeoInfo),1,pf))
	{
		SListPushBack(con, p);
	}
	printf("历史数据导入成功!\n");
	fclose(pf);
	pf = NULL;
}

在初始化通讯录之后加载数据! 

//初始化通讯录
void InitContact(contact** con)
{
	assert(con);
	(*con) = NULL;
	DLoadContact(con);
}

2.2 添加通讯录数据

//添加通讯录数据
void AddContact(contact** con)
{
	assert(con);
	PeoInfo p = {0};
	printf("请输入添加联系人的姓名:");
	scanf("%s", p.name);
	printf("请输入添加联系人的性别:");
	scanf("%s", p.sex);
	printf("请输入添加联系人的年龄:");
	scanf("%d", &(p.age));
	printf("请输入添加联系人的电话:");
	scanf("%s", p.tel);
	printf("请输入添加联系人的住址:");
	scanf("%s", p.addr);
	SListPushBack(con,p);
	printf("\n");
}

2.3 删除通讯录数据

在查找通讯录数据之外封装一个函数(findByName)来通过名字查找联系人!

(因为我们在之后的查找和修改接口中都会用到这个方法,所以我们把它封装成一个函数方便我们后续的使用!)

//通过名字查找联系人
contact* findByName(contact* con,char* name)
{
	assert(con);
	contact* cur = con;
	while (cur)
	{
		if (strcmp(cur->data.name, name) == 0)
		{
			return cur;
		}
		cur = cur->next;
	}
	return NULL;
}

在原有单链表的删除指定数据的接口上进行封装(让单链表摇身一变成为通讯录!)

//删除通讯录数据
void DelContact(contact** con)
{
	assert(con && (*con));
	char name[NAME_MAX];
	printf("请输入你要删除的联系人的名字:");
	scanf("%s", name);
	contact* pos = findByName(*con,name);
	if (pos == NULL)
	{
		printf("您要删除的联系人不存在!\n");
		return;
	}
	SListErase(con, pos);
	printf("删除成功!\n");
}

2.4 展示通讯录数据

遍历我们的通讯录打印信息!

//展示通讯录数据
void ShowContact(contact* con)
{
	assert(con);
	contact* cur = con;
	printf("名字\t\t性别\t\t年龄\t\t电话\t\t住址\n");//打印表头
	while (cur)
	{
		printf("%s\t\t%s\t\t%d\t\t%s\t\t%s\n",
			cur->data.name,
			cur->data.sex,
			cur->data.age,
			cur->data.tel,
			cur->data.addr);
		cur = cur->next;
	}
}

2.5 查找通讯录数据

//通过名字查找联系人
contact* findByName(contact* con,char* name)
{
	assert(con);
	contact* cur = con;
	while (cur)
	{
		if (strcmp(cur->data.name, name) == 0)
		{
			return cur;
		}
		cur = cur->next;
	}
	return NULL;
}

在接口内部调用该函数! 

//查找通讯录数据
void FindContact(contact* con)
{
	assert(con);
	char name[NAME_MAX];
	printf("请输入你要查找的联系人的名字:");
	scanf("%s", name);
	contact* ret = findByName(con, name);
	if (ret == NULL)
	{
		printf("您要查找的联系人不存在!\n");
		return;
	}
	printf("找到了!\n");
	printf("名字\t\t性别\t\t年龄\t\t电话\t\t住址\n");//打印表头
		printf("%s\t\t%s\t\t%d\t\t%s\t\t%s\n",
			ret->data.name,
			ret->data.sex,
			ret->data.age,
			ret->data.tel,
			ret->data.addr);
}

2.6 修改通讯录数据

//通过名字查找联系人
contact* findByName(contact* con,char* name)
{
	assert(con);
	contact* cur = con;
	while (cur)
	{
		if (strcmp(cur->data.name, name) == 0)
		{
			return cur;
		}
		cur = cur->next;
	}
	return NULL;
}

在接口内部调用该函数! 

//修改通讯录数据
void ModifyContact(contact** con)
{
	assert(con);
	char name[NAME_MAX];
	printf("请输入你要修改的联系人的名字:");
	scanf("%s", name);
	contact* ret = findByName(*con, name);
	if (ret == NULL)
	{
		printf("您要修改的联系人不存在!\n");
		return;
	}
	PeoInfo p = { 0 };
	printf("请输入修改后联系人的姓名:");
	scanf("%s", p.name);
	printf("请输入修改后联系人的性别:");
	scanf("%s", p.sex);
	printf("请输入修改后加联系人的年龄:");
	scanf("%d", &(p.age));
	printf("请输入修改后联系人的电话:");
	scanf("%s", p.tel);
	printf("请输入修改后联系人的住址:");
	scanf("%s", p.addr);
	SListModify(ret, p);
	printf("修改成功!\n");
}

2.7 销毁通讯录数据

因为我们希望在退出通讯管理系统的时候可以将我们的操作都保留下来,所以我们可以对其进行文件操作!

//将输入的数据保存到文件中
void SaveContact(contact** con)
{
	FILE* pf = fopen("contact.txt", "wb");
	if (pf == NULL)
	{
		perror("open fail!\n");
		return;
	}
	contact* cur = *con;
	while (cur)
	{
		fwrite(&(cur->data), sizeof(PeoInfo), 1, pf);
		cur = cur->next;
	}
	printf("历史数据保存成功!\n");
	fclose(pf);
	pf = NULL;
}

 在销毁通讯录之前保留数据!

//销毁通讯录数据
void DestroyContact(contact** con)
{
	SaveContact(con);
	SListDestroy(con);
}

3、完整源码

SeqList.h

#pragma once//避免头文件被多次引用
#include<stdio.h>
#include<assert.h>
#include<stdlib.h>
#include"Contact.h"
typedef PeoInfo SListDataType;//便于改变数据类型

//定义一个结构体类型的节点
typedef struct SListNode
{
	SListDataType data;
	struct SListNode* next;//存储下一个节点的地址
}SListNode;

//1. 新节点的创建
SListNode* SListCreatNode(SListDataType x);

//2. 打印单链表
void PrintSList(SListNode* phead);

//3. 头插
void SListPushFront(SListNode** phead, SListDataType x);

//4. 头删
void  SListPopFront(SListNode** phead);

//5. 尾差
void SListPushBack(SListNode** phead, SListDataType x);

//6. 尾删
void  SListPopBack(SListNode** phead);

//7. 查找元素X
SListNode* SListFind(SListNode* phead, SListDataType x);

//8. 在pos位置修改
void SListModify(SListNode* pos, SListDataType x);

//9. 在任意位置之前插入
void SListInsert(SListNode** phead, SListNode* pos, SListDataType x);

//10. 在任意位置删除
void SListErase(SListNode** phead, SListNode* pos);

//11. 销毁单链表
void SListDestroy(SListNode** phead);

Contact.h

#define _CRT_SECURE_NO_WARNINGS

//contact.h
#pragma once
#define NAME_MAX 100
#define SEX_MAX 4
#define TEL_MAX 11
#define ADDR_MAX 100

//前置声明
typedef struct SListNode contact;

//用户数据
typedef struct PersonInfo
{
    char name[NAME_MAX];
    char sex[SEX_MAX];
    int age;
    char tel[TEL_MAX];
    char addr[ADDR_MAX];
}PeoInfo;

//初始化通讯录
void InitContact(contact** con);

//添加通讯录数据
void AddContact(contact** con);

//展示通讯录数据
void ShowContact(contact* con);

//删除通讯录数据
void DelContact(contact** con);

//查找通讯录数据
void FindContact(contact* con);

//修改通讯录数据
void ModifyContact(contact** con);

//销毁通讯录数据
void DestroyContact(contact** con);

SeqList.c

#include"SList.h"

//1. 新节点的创建
SListNode* SListCreatNode(SListDataType x)
{
	SListNode* NewNode = (SListNode*)malloc(sizeof(SListNode));//开辟空间
	if (NewNode == NULL)//判断空间是否开辟成功
	{
		perror("malloc fail");
		return NULL;
	}
	NewNode->data = x;//赋值
	NewNode->next = NULL;//置空
	return NewNode;
}

#if 0
//2. 打印单链表
void PrintSList(SListNode* phead)
{
	if (phead == NULL)
	{
		printf("NULL");//如果链表没有元素就打印NULL
		return;
	}
	SListNode* cur = phead;
	//循环单链表打印
	while (cur != NULL)
	{
		printf("%d->", cur->data);
		cur = cur->next;
	}
	printf("NULL\n");
}
#endif

//3. 头插
void SListPushFront(SListNode** phead, SListDataType x)
{
	assert(phead);
	SListNode* newnode = SListCreatNode(x);//创建一个新节点
	newnode->next = *phead;
	*phead = newnode;
}

//4. 头删
void  SListPopFront(SListNode** phead)
{
	assert(phead);
	assert(*phead);//如果没有数据就不用头删,并报错
	SListNode* cur = (*phead)->next;
	free(*phead);
	*phead = cur;
}

//5. 尾插
void SListPushBack(SListNode** phead, SListDataType x)
{
	assert(phead);
	if (*phead == NULL)
	{
		*phead = SListCreatNode(x);//创建新节点并插入
	}
	else
	{
		SListNode* tail = *phead;
		while (tail->next != NULL)//找到尾节点
		{
			tail = tail->next;
		}
		tail->next = SListCreatNode(x);//创建新节点并插入
	}
}

//6. 尾删
void  SListPopBack(SListNode** phead)
{
	assert(phead);
	assert(*phead);//链表为空就不进行尾删
	SListNode* tail = *phead;
	if (tail->next == NULL)//如果链表就只有一个元素就进行头删
	{
		SListPopFront(phead);
	}
	else
	{
		while (tail->next->next != NULL)
		{
			tail = tail->next;
		}
		free(tail->next);
		tail->next = NULL;
	}
}

#if 0
//7. 查找元素X
SListNode* SListFind(SListNode* phead, SListDataType x)
{
	assert(phead);
	while (phead->next != NULL)//注意最后一个节点是没有查找的
	{
		if (phead->data == x)
			return phead;
		phead = phead->next;
	}
	if (phead->data == x)
		return phead;//最后一个节点没有查找
	else
		return NULL;//没找到
}
#endif

//8. 在pos位置修改
void SListModify(SListNode* pos, SListDataType x)
{
	assert(pos);
	pos->data = x;
}

//9. 在任意位置之前插入
void SListInsert(SListNode** phead, SListNode* pos, SListDataType x)
{
	assert(phead);
	assert(*phead);
	if (pos == *phead)//如果pos位置刚好是第一个节点就进行头插
	{
		SListPushFront(phead, x);
	}
	else
	{
		SListNode* newnode = SListCreatNode(x);
		SListNode* cur = *phead;
		while (cur->next != pos)//找到pos前一个节点
		{
			cur = cur->next;
		}
		cur->next = newnode;
		newnode->next = pos;
	}
}

//10. 在任意位置删除
void SListErase(SListNode** phead, SListNode* pos)
{
	assert(phead && *phead && pos);
	if (pos == *phead)//如果pos位置就是第一个节点就进行头删
	{
		SListPopFront(phead);
	}
	else
	{
		SListNode* cur = *phead;
		while (cur->next != pos)//找到pos前一个节点
		{
			cur = cur->next;
		}
		cur->next = pos->next;
		free(pos);
	}
}

//11. 销毁单链表
void SListDestroy(SListNode** phead)
{
	assert(*phead && phead);
	SListNode* cur = *phead;
	while (cur != NULL)
	{
		SListNode* tmp = cur->next;
		free(cur);
		cur = tmp;
	}
	*phead = NULL;
}

Contact.c

#include"SList.h"

//从文件中导入原数据
void DLoadContact(contact** con)
{
	FILE* pf = fopen("contact.txt", "rb");
	if (pf == NULL)
	{
		perror("open fail\n");
		return;
	}
	PeoInfo p = { 0 };
	while (fread(&p, sizeof(PeoInfo),1,pf))
	{
		SListPushBack(con, p);
	}
	printf("历史数据导入成功!\n");
	fclose(pf);
	pf = NULL;
}

//初始化通讯录
void InitContact(contact** con)
{
	assert(con);
	(*con) = NULL;
	DLoadContact(con);
}

//添加通讯录数据
void AddContact(contact** con)
{
	assert(con);
	PeoInfo p = {0};
	printf("请输入添加联系人的姓名:");
	scanf("%s", p.name);
	printf("请输入添加联系人的性别:");
	scanf("%s", p.sex);
	printf("请输入添加联系人的年龄:");
	scanf("%d", &(p.age));
	printf("请输入添加联系人的电话:");
	scanf("%s", p.tel);
	printf("请输入添加联系人的住址:");
	scanf("%s", p.addr);
	SListPushBack(con,p);
	printf("\n");
}

//展示通讯录数据
void ShowContact(contact* con)
{
	assert(con);
	contact* cur = con;
	printf("名字\t\t性别\t\t年龄\t\t电话\t\t住址\n");//打印表头
	while (cur)
	{
		printf("%s\t\t%s\t\t%d\t\t%s\t\t%s\n",
			cur->data.name,
			cur->data.sex,
			cur->data.age,
			cur->data.tel,
			cur->data.addr);
		cur = cur->next;
	}
}

//通过名字查找联系人
contact* findByName(contact* con,char* name)
{
	assert(con);
	contact* cur = con;
	while (cur)
	{
		if (strcmp(cur->data.name, name) == 0)
		{
			return cur;
		}
		cur = cur->next;
	}
	return NULL;
}

//删除通讯录数据
void DelContact(contact** con)
{
	assert(con && (*con));
	char name[NAME_MAX];
	printf("请输入你要删除的联系人的名字:");
	scanf("%s", name);
	contact* pos = findByName(*con,name);
	if (pos == NULL)
	{
		printf("您要删除的联系人不存在!\n");
		return;
	}
	SListErase(con, pos);
	printf("删除成功!\n");
}

//查找通讯录数据
void FindContact(contact* con)
{
	assert(con);
	char name[NAME_MAX];
	printf("请输入你要查找的联系人的名字:");
	scanf("%s", name);
	contact* ret = findByName(con, name);
	if (ret == NULL)
	{
		printf("您要查找的联系人不存在!\n");
		return;
	}
	printf("找到了!\n");
	printf("名字\t\t性别\t\t年龄\t\t电话\t\t住址\n");//打印表头
		printf("%s\t\t%s\t\t%d\t\t%s\t\t%s\n",
			ret->data.name,
			ret->data.sex,
			ret->data.age,
			ret->data.tel,
			ret->data.addr);
}

//修改通讯录数据
void ModifyContact(contact** con)
{
	assert(con);
	char name[NAME_MAX];
	printf("请输入你要修改的联系人的名字:");
	scanf("%s", name);
	contact* ret = findByName(*con, name);
	if (ret == NULL)
	{
		printf("您要修改的联系人不存在!\n");
		return;
	}
	PeoInfo p = { 0 };
	printf("请输入修改后联系人的姓名:");
	scanf("%s", p.name);
	printf("请输入修改后联系人的性别:");
	scanf("%s", p.sex);
	printf("请输入修改后加联系人的年龄:");
	scanf("%d", &(p.age));
	printf("请输入修改后联系人的电话:");
	scanf("%s", p.tel);
	printf("请输入修改后联系人的住址:");
	scanf("%s", p.addr);
	SListModify(ret, p);
	printf("修改成功!\n");
}

//将输入的数据保存到文件中
void SaveContact(contact** con)
{
	FILE* pf = fopen("contact.txt", "wb");
	if (pf == NULL)
	{
		perror("open fail!\n");
		return;
	}
	contact* cur = *con;
	while (cur)
	{
		fwrite(&(cur->data), sizeof(PeoInfo), 1, pf);
		cur = cur->next;
	}
	printf("历史数据保存成功!\n");
	fclose(pf);
	pf = NULL;
}
//销毁通讯录数据
void DestroyContact(contact** con)
{
	SaveContact(con);
	SListDestroy(con);
}

 这里我就没有单独去写一个菜单了,本身的意义也并不大,但是如果友友们想写一个来玩一玩,可以看看我之前那篇基于顺序表实现通讯录(文章链接,那里有菜单的模版(只要改几个接口的名字就行了)~

4、 完结散花

好了,这期的分享到这里就结束了~

如果这篇博客对你有帮助的话,可以用你们的小手指点一个免费的赞并收藏起来哟~

如果期待博主下期内容的话,可以点点关注,避免找不到我了呢~

我们下期不见不散~~

​​​​

  • 159
    点赞
  • 125
    收藏
    觉得还不错? 一键收藏
  • 131
    评论
基于java实现的商品出入库管理系统源码,采用了面向对象的编程思想,结合了java语言的特点和优势。系统的核心功能包括商品管理、入库管理、出库管理等模块,具有良好的可扩展性和灵活性。 商品管理模块包括对商品信息的增删改查操作,通过面向对象的设计和封装,实现了商品的属性封装和业务逻辑的统一处理。入库管理模块包括了对商品入库记录的管理,包括入库单的生成、入库数量的更新、入库记录的查询等功能。出库管理模块类似,对商品的出库记录进行管理,支持出库单的生成、出库数量的更新、出库记录的查询等操作。 在系统的架构设计上,采用了MVC(模型-视图-控制器)的设计模式,实现了用户界面和业务逻辑的分离。模块化的设计使得每个功能模块的实现相对独立,易于维护和扩展。同时,sys源码利用了java的多线程特性,提高系统的并发处理能力,保证系统的高效性和稳定性。 此外,系统还使用了数据库存储数据,通过jdbc技术实现了与数据库的连接和数据的读写操作。通过使用java的集合框架和泛型特性,实现了对数据的灵活操作和高效管理。 总的来说,基于java实现的商品出入库管理系统源码,不仅考虑了功能的完整性和稳定性,还充分利用了java语言的优势,实现了系统的高性能和可维护性。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 131
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值