c语言 结构体链表实现信息管理系统(通讯录)(增删改查并且对编号排序)

该博客介绍了用C语言通过结构体链表实现信息管理系统(通讯录),包含增、删、改、查基本功能,还实现了编号的冒泡排序,分遍历和交换两部分,交换又分相邻和不相邻情况,最后附上了头文件、主函数和函数文件的代码。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

c语言 使用结构体链表实现信息管理系统/通讯录(增删改查)(含编号排序)

前言

本章主要介绍了使用链表存储信息,包括基本的增删改查功能。

1.增加成员功能

         思路:先定义常规的头节点和尾节点,创建新节点接受信息,taii(尾部)要先遍历往后走,找到
         下一个是空节点时停下,这个时候tail下一个就是新节点,新节点又变为tail。
         tips:由于电话号码是11位的,因此要用long long来储存,不然会出现乱码现象。
         附上代码:
struct Node* Add(Node* header)
{
	int input = 0;
	Node* tail = header;
	while (tail->next != NULL)
	{
		tail = tail->next;
	}
	printf("请输入要添加的人数:>");
	scanf("%d", &input);
	for (int i = 0; i < input; i++)
	{
		Node* newnode = (Node*)malloc(sizeof(Node));//创建新节点
		tail->next = newnode;
		tail = newnode;
		newnode->next = NULL;
		printf("请输入姓名:>\n");
		while (1)
		{
			scanf("%s", &newnode->name);
			char c = getchar();
			if (c == '\n')
			{
				break;
			}
		}
		printf("请输入编号:>\n");
		scanf("%d", &newnode->number);
		printf("请输入年龄:>\n");
		scanf("%d", &newnode->age);
		printf("请输入电话号码:>\n");
		scanf("%lld", &newnode->phonenumber);
	}
	return header;
}

2.删除成员功能

       思路:通过查找删除信息的编号寻找,基本思路也是遍历之后找到就free删除,找不到就说找不到。
       tips:由于删除后保持链表的完整性,因此要创造两个节点,即front(前部节点)与back(后部节点),
       删除特定节点后应有front的下一个节点为back的下一个节点,让我画图来解释。

在这里插入图片描述
附上代码:

void Delete(Node* header)
{
	int delnumber = 0;
	printf("请输入你想删除信息的编号:>");
	scanf("%d", &delnumber);
	if (NULL == header)
	{
		return;
	}
	Node* front = header;
	Node* back = header->next;
	while (back != NULL)
	{
		if (back->number == delnumber)
		{
			break;
		}
		//遍历找delnumber
		front = back;
		back = back->next;
		
	}
	//找到了就删除,找不到就退出。
	if (back == NULL)
	{
		printf("未找到该名队员\n");
		printf("*****************************\n");
		return;
	}
	front->next = back->next;
	free(back);
	back = NULL;
	printf("删除成功!\n");
}

3.展示全部成员信息

    思路:当下一个节点不为空时,就遍历输出,有点想循环的原理。
void Display(Node* header)
{
	Node* receiver = header->next;
	if (NULL == receiver)
	{
		printf("无信息\n");
		return;
	}
	while (receiver != NULL)
	{
		printf("姓名:%s\n", receiver->name);
		printf("编号:%d\n", receiver->number);
		printf("年龄:%d\n", receiver->age);
		printf("电话号码:%lld\n", receiver->phonenumber);
		receiver = receiver->next;
		printf("\n");
		printf("*********************************************\n");
	}
}

4.使用姓名查找某一特定成员

    思路:依旧是遍历,使用了strcmp函数判断姓名字符串是否相等(注意引用头文件string.h)
    我在这里处理了重名情况,找到名字后没有跳出遍历过程,而是继续寻找,并且定义了一个sum变量,sum
    大于0时就会打印特定内容
    附上代码:
void Find(Node* header)
{
	int sum = 0;
	printf("请输入要查找的名字:>");
	char name_1[30] = { 0 };
	scanf("%s", name_1);
	struct Node* pCurrent = header->next;
	if (NULL == header)
	{
		return;
	}
	while (pCurrent != NULL)
	{
		if (strcmp(pCurrent->name, name_1) == 0)
		{
			printf("姓名:%s\n", pCurrent->name);
			printf("编号:%d\n", pCurrent->number);
			printf("年龄:%d\n", pCurrent->age);
			printf("电话号码:%lld\n", pCurrent->phonenumber);
			printf("\n");
			printf("*********************************************\n");
			sum++;//处理重名
		}
		pCurrent = pCurrent->next;
	}
	if (sum > 0)
	{
		printf("找到了重名的队员\n");
		printf("******************************\n");
	}
	if (NULL == pCurrent)
	{
		return;
	}
}

5.修改成员信息:

    思路:还是遍历找特定成员,之后将其拆分为四个板块,分别可以修改四个模块的信息,这样比较清晰。
    tips:由于传了节点过去,所以重新输入节点的信息就好。
    void ReviseName(Node* node)
{
	char name_2[25] = { 0 };
	printf("请输入更改后的姓名:>");
	scanf("%s", name_2);
	strcpy(node->name, name_2);
}
void ReviseNumber(Node* node)
{
	printf("请输入更改后的编号:>");
	scanf("%d", &node->number);
}
void ReviseAge(Node* node)
{
	printf("请输入更改后的编号:>");
	scanf("%d", &node->age);
}
void RevisePhonenumber(Node* node)
{
	printf("请输入更改后的手机号码:>");
	while (1)
	{
		scanf("%lld", &node->phonenumber);
		char c = getchar();
		if (c == '\n')
		{
			break;
		}
	}
}
void Revise(Node* header)
{
	if (NULL == header)
	{
		return;
	}
	int input = 0;
	int input2 = 0;
	printf("请输入需要修改信息的队员的编号:>");
	scanf("%d", &input);
	Node* node = header->next;
	while (node != NULL)
	{
		if (node->number == input)
		{
			break;
		}
		node = node->next;
	}
	if (NULL == node)
	{
		return;
	}
	do
	{
		printf("请输入对应的编号\n");
		printf("*******1.修改姓名******\n");
		printf("*******2.修改编号******\n");
		printf("*******3.修改年龄******\n");
		printf("*******4.修改电话号码******\n");
		printf("*******0.退出修改**********\n");
		scanf("%d", &input2);
		switch (input2)
		{
		case 1:
			ReviseName(node);
			break;
		case 2:
			ReviseNumber(node);
			break;
		case 3:
			ReviseAge(node);
			break;
		case 4:
			RevisePhonenumber(node);
			break;
		}
	} while (input2);

}

6.将编号进行冒泡排序

   思路:分为两部分,一个为遍历部分,一个为交换部分。

①遍历部分

      思路:找到前一个节点编号比后一个大的,就进入函数Exchange。
      特别提示!!!:由于交换了前后节点,所以需要借助外在节点来实现调整后的后节点成为
      front节点,调整后的前节点成为后节点,不然的话外部的遍历过程就进行不下去了。建议
      读者亲自调试一下,有点难理解。
       void BubblingsSorting(Node* header)
{
	Node* front = header->next;
	if (NULL == front)
	{
		return;
	}
	while (front != NULL)
	{
		Node* back = front->next;
		while (back != NULL)
		{
			if (front->number > back->number)
			{
				Exchange(header, front, back);
				Node* help = front;//需设置一个辅助节点调整前后顺序。
				front = back;
				back = help;
			}
			back = back->next;
		}
		front = front->next;
	}
}
     

②:交换部分

      思路:大体分为两种主要情况,即node1和node2相岭与不相邻的过程
α.相邻

只需借助两个节点,即node1前一个节点和node2后一个节点。再按照以下顺序prenode1->node2->
node1->postnode2

β.不相邻

需要四个辅助节点,即从一开始的prenode1->node1->postnode1变为prenode1>node2->postnode2
另外一个同理。
建议画图理解

void Exchange(Node* header, Node* node1, Node* node2)
{
	
	Node* prenode1 = NULL;  //node1的前一个节点
	Node* postnode1 = NULL; //node1的后一个节点
	Node* prenode2 = NULL;  //node2的前一个节点
	Node* postnode2 = NULL; //node2的后一个节点
	Node* tmp = header;
	if (node1 == header)
	{
		return;
	}
	else if (node2 == header)
	{
		return;
	}
	if (node1 == node2)
	{
		return;
	}
	if (node1->next == node2)//node1与node2相邻的情况。
	{
		tmp = header;
		while (tmp->next != node1)
		{
			tmp = tmp->next;
		}//只需使用prenode1和postnode2
		prenode1 = tmp;//node1前一个
		postnode2 = node2->next;
		prenode1->next = node2;
		node2->next = node1;
		node1->next = postnode2;
		return;
	}
	while (tmp->next != node1)
	{
		tmp = tmp->next;
	}
	prenode1 = tmp;//遍历找node1
	while (tmp->next != node2)
	{
		tmp = tmp->next;
	}
	prenode2 = tmp;//遍历找node2
	postnode1 = node1->next;
	postnode2 = node2->next;
	//交换节点
	prenode1->next = node2;
	node2->next = postnode1;
	prenode2->next = node1;
	node1->next = postnode2;
}

最后附上全部代码

头文件

#define _CRT_SECURE_NO_WARNINGS 1
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<windows.h>
typedef struct Node
{
	char name[30];
	int number;
	int age;
	long long phonenumber;
	struct Node* next;
}Node;
struct Node* Add(Node* header);
void Display(Node* header);
void Delete(Node* header);
void Find(Node* header);
void Revise(Node* header);
void ReviseName(Node* node);
void ReviseNumber(Node* node);
void ReviseAge(Node* node);
void RevisePhonenumber(Node* node);
void BubblingsSorting(Node* header);
void Exchange(Node* header, Node* node1, Node* node2);

主函数

#include"TeamMembers.h"
void menu()
{
	printf("************简约版信息管理系统*********\n");
	printf("*****************请选择****************\n");
	printf("***************1.添加队员**************\n");
	printf("***************2.删除队员**************\n");
	printf("***********3.按照姓名查找队员**********\n");
	printf("***********4.修改队员信息**************\n");
	printf("***********5.显示所有联系人信息********\n");
	printf("*************0.退出程序****************\n");
}
int main()
{
	int Choice = 0;
	printf("请先创建一个信息\n");
	Node* header = (Node*)malloc(sizeof(Node));
	header->next = NULL;
	header = Add(header);
	BubblingsSorting(header);
	do
	{
		printf("可以选择以下操作\n");
		menu();
		scanf("%d", &Choice);
		system("cls");
		switch(Choice)
		{
	       case 1:
			   header = Add(header);
			   BubblingsSorting(header);
			   break;
	       case 2:
			   Delete(header);
			   break;
	       case 3:
			   Find(header);
			   break;
	       case 4:
			   Revise(header);
			   BubblingsSorting(header);
			   break;
	       case 5:
			   Display(header);
			   break;
		}
	} while (Choice);
	return 0;
}

函数文件

#include"TeamMembers.h"
struct Node* Add(Node* header)
{
	int input = 0;
	Node* tail = header;
	while (tail->next != NULL)
	{
		tail = tail->next;
	}
	printf("请输入要添加的人数:>");
	scanf("%d", &input);
	for (int i = 0; i < input; i++)
	{
		Node* newnode = (Node*)malloc(sizeof(Node));//创建新节点
		tail->next = newnode;
		tail = newnode;
		newnode->next = NULL;
		printf("请输入姓名:>\n");
		while (1)
		{
			scanf("%s", &newnode->name);
			char c = getchar();
			if (c == '\n')
			{
				break;
			}
		}
		printf("请输入编号:>\n");
		scanf("%d", &newnode->number);
		printf("请输入年龄:>\n");
		scanf("%d", &newnode->age);
		printf("请输入电话号码:>\n");
		scanf("%lld", &newnode->phonenumber);
	}
	return header;
}

void Delete(Node* header)
{
	int delnumber = 0;
	printf("请输入你想删除信息的编号:>");
	scanf("%d", &delnumber);
	if (NULL == header)
	{
		return;
	}
	Node* front = header;
	Node* back = header->next;
	while (back != NULL)
	{
		if (back->number == delnumber)
		{
			break;
		}
		//遍历找delnumber
		front = back;
		back = back->next;
		
	}
	//找到了就删除,找不到就退出。
	if (back == NULL)
	{
		printf("未找到该名队员\n");
		printf("*****************************\n");
		return;
	}
	front->next = back->next;
	free(back);
	back = NULL;
	printf("删除成功!\n");
}
void Display(Node* header)
{
	Node* receiver = header->next;
	if (NULL == receiver)
	{
		printf("无信息\n");
		return;
	}
	while (receiver != NULL)
	{
		printf("姓名:%s\n", receiver->name);
		printf("编号:%d\n", receiver->number);
		printf("年龄:%d\n", receiver->age);
		printf("电话号码:%lld\n", receiver->phonenumber);
		receiver = receiver->next;
		printf("\n");
		printf("*********************************************\n");
	}
}
void Find(Node* header)
{
	int sum = 0;
	printf("请输入要查找的名字:>");
	char name_1[30] = { 0 };
	scanf("%s", name_1);
	struct Node* pCurrent = header->next;
	if (NULL == header)
	{
		return;
	}
	while (pCurrent != NULL)
	{
		if (strcmp(pCurrent->name, name_1) == 0)
		{
			printf("姓名:%s\n", pCurrent->name);
			printf("编号:%d\n", pCurrent->number);
			printf("年龄:%d\n", pCurrent->age);
			printf("电话号码:%lld\n", pCurrent->phonenumber);
			printf("\n");
			printf("*********************************************\n");
			sum++;//处理重名
		}
		pCurrent = pCurrent->next;
	}
	if (sum > 0)
	{
		printf("找到了重名的队员\n");
		printf("******************************\n");
	}
	if (NULL == pCurrent)
	{
		return;
	}
}
void ReviseName(Node* node)
{
	char name_2[25] = { 0 };
	printf("请输入更改后的姓名:>");
	scanf("%s", name_2);
	strcpy(node->name, name_2);
}
void ReviseNumber(Node* node)
{
	printf("请输入更改后的编号:>");
	scanf("%d", &node->number);
}
void ReviseAge(Node* node)
{
	printf("请输入更改后的编号:>");
	scanf("%d", &node->age);
}
void RevisePhonenumber(Node* node)
{
	printf("请输入更改后的手机号码:>");
	while (1)
	{
		scanf("%lld", &node->phonenumber);
		char c = getchar();
		if (c == '\n')
		{
			break;
		}
	}
}
void Revise(Node* header)
{
	if (NULL == header)
	{
		return;
	}
	int input = 0;
	int input2 = 0;
	printf("请输入需要修改信息的队员的编号:>");
	scanf("%d", &input);
	Node* node = header->next;
	while (node != NULL)
	{
		if (node->number == input)
		{
			break;
		}
		node = node->next;
	}
	if (NULL == node)
	{
		return;
	}
	do
	{
		printf("请输入对应的编号\n");
		printf("*******1.修改姓名******\n");
		printf("*******2.修改编号******\n");
		printf("*******3.修改年龄******\n");
		printf("*******4.修改电话号码******\n");
		printf("*******0.退出修改**********\n");
		scanf("%d", &input2);
		switch (input2)
		{
		case 1:
			ReviseName(node);
			break;
		case 2:
			ReviseNumber(node);
			break;
		case 3:
			ReviseAge(node);
			break;
		case 4:
			RevisePhonenumber(node);
			break;
		}
	} while (input2);

}
void Exchange(Node* header, Node* node1, Node* node2)
{
	
	Node* prenode1 = NULL;  //node1的前一个节点
	Node* postnode1 = NULL; //node1的后一个节点
	Node* prenode2 = NULL;  //node2的前一个节点
	Node* postnode2 = NULL; //node2的后一个节点
	Node* tmp = header;
	if (node1 == header)
	{
		return;
	}
	else if (node2 == header)
	{
		return;
	}
	if (node1 == node2)
	{
		return;
	}
	if (node1->next == node2)//node1与node2相邻的情况。
	{
		tmp = header;
		while (tmp->next != node1)
		{
			tmp = tmp->next;
		}//只需使用prenode1和postnode2
		prenode1 = tmp;//node1前一个
		postnode2 = node2->next;
		prenode1->next = node2;
		node2->next = node1;
		node1->next = postnode2;
		return;
	}
	while (tmp->next != node1)
	{
		tmp = tmp->next;
	}
	prenode1 = tmp;//遍历找node1
	while (tmp->next != node2)
	{
		tmp = tmp->next;
	}
	prenode2 = tmp;//遍历找node2
	postnode1 = node1->next;
	postnode2 = node2->next;
	//交换节点
	prenode1->next = node2;
	node2->next = postnode1;
	prenode2->next = node1;
	node1->next = postnode2;
}
void BubblingsSorting(Node* header)
{
	Node* front = header->next;
	if (NULL == front)
	{
		return;
	}
	while (front != NULL)
	{
		Node* back = front->next;
		while (back != NULL)
		{
			if (front->number > back->number)
			{
				Exchange(header, front, back);
				Node* help = front;//需设置一个辅助节点调整前后顺序。
				front = back;
				back = help;
			}
			back = back->next;
		}
		front = front->next;
	}
}

感谢您读到这里,谢谢!


通讯录管理系统 通讯录(add_book)中的联系人包含以下信息项:姓名、手机、办公电话、家庭电话、电子邮箱、所在省市、工作单位、家庭住址,群组分类(亲属、同事、同学、朋友、其他)。 Name Mobile phones Office phone Family telephone E-mail In cities Work units0 Address Group classification (relative, colleagues, friends, classmates, other). 系统的主要功能包括: 1. 输入联系人的信息,要求:至少输入10个联系人的数据,且注意数据的多样性。 2. 按姓名对联系人信息进行排序,并将排序后信息存放到一个文本文件中。 3. 添加联系人的信息,在已经存在的通讯录文件中添加若干个联系人。要求:添加后仍按联系人的姓名排序,并保存至原文件。 4. 删除联系人的信息,输入一个姓名,若通讯录中有该联系人的信息,则删除该联系人,否则输出提示信息,并提示用户选择是否继续进行删除操作。 5. 修改联系人的信息,输入一个姓名,根据具体需要修改该联系人的某一项信息,将修改后的信息重新保存到通讯录文件中,并提示用户选择是否继续进行修改操作。 6. 按不同条件对通讯录进行查询操作,输出满足条件的联系人的信息。 (1) 按姓名查询,包括精确查询(输入全名),模糊查询(输入姓)(2) 按手机号码查询,输入全部号码或号码位段(如输入130、133、139等); (3) 按群组分类查询,输入分类名称,输出该群组的全部联系人信息。 7. 输出联系人的信息Contact information,按一定格式输出信息,保证信息排列整齐美观。ContactPerson
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值