本文中的代码都在Visual Studio(版本为2022)软件中运行,在使用scanf函数记得在第一行写下面的代码:
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
#include <string.h>
//定义结构体中各类型变量的大小
#define NAME_MAX 20
#define GENDER_MAX 5
#define PHONE_MAX 11
#define ADDRESS_MAX 100
//存放联系人信息的结构体
struct PersonalInformation
{
char name[NAME_MAX];
char gender[GENDER_MAX];
int age;
char phone[PHONE_MAX];
char address[ADDRESS_MAX];
};
typedef struct PersonalInformation SLTDataType; //为 struct PersonalInformation起一个别名PI
//存放节点的结构体
struct SingleLinkedListNode
{
SLTDataType data; //存放个人信息
struct SingleLinkedListNode* next; //存放下一个节点的地址
};
typedef struct SingleLinkedListNode SLTNode; //为struct SingleLinkedListNode SLTNode起一个别名SLTNode
//添加联系人的信息
void AddContact(SLTNode** pphead) //pphead存放的是一级指针的地址,*pphead是一级指针存放的地址,**pphead是一级指针存放的地址中的值
{
assert(pphead); //判断二级指针是否为空
SLTNode* temp = (SLTNode*)malloc(sizeof(SLTNode)); //创建指向节点的指针变量
if (temp == NULL)
{
perror("申请空间失败");
exit(1);
}
SLTNode* newNode = temp;
printf("请输入联系人的名字:");
scanf("%s", newNode->data.name);
printf("请输入联系人的性别:");
scanf("%s", newNode->data.gender);
printf("请输入联系人的年龄:");
scanf("%d", &newNode->data.age);
printf("请输入联系人的电话号码:");
scanf("%s", newNode->data.phone);
printf("请输入联系人的地址:");
scanf("%s", newNode->data.address);
newNode->next = NULL;
if (*pphead == NULL) //创建的节点为第一个节点
{
*pphead = newNode;
printf("添加成功\n");
return;
}
SLTNode* pcur = *pphead; //创建的节点不是第一个节点
while (pcur->next != NULL)
{
pcur = pcur->next;
}
pcur->next = newNode;
printf("添加成功\n");
}
//在进行删除和修改之前,通过名字查找
int ByNameSearch(SLTNode* phead)
{
char name[NAME_MAX] = "";
printf("请输入你要查找或修改的名字:");
scanf("%s", name);
SLTNode* pcur = phead;
int count = 0; //执行while循环中代码的次数,方便后续进行删除和修改操作。
//若pcur指向第n个节点,则count的值为n - 1;
while (pcur != NULL)
{
if (strcmp(pcur->data.name, name) == 0)
{
return count;
}
pcur = pcur->next;
count++;
}
return -1;
}
//删除联系人的信息
void DeleteContact(SLTNode** pphead)
{
assert(pphead);
if (*pphead == NULL)
{
printf("通讯录中没有联系人的信息,无法删除");
return;
}
int num = ByNameSearch(*pphead); //根据返回值判断通讯录中是否有要删除的联系人的信息
if (num == -1)
{
printf("没有此人的联系信息,无法删除\n");
}
else
{
if (num == 0) //要删除的节点为第一个节点(联系人的信息)
{
if ((*pphead)->next != NULL) //通讯录中有1个以上的节点(联系人的信息)
{
SLTNode* temp = *pphead;
(*pphead) = (*pphead)->next;
free(temp); //用free函数,释放由malloc函数申请的空间(malloc函数申请的空间需要手动释放)
temp = NULL; //将指针temp置为NULL,避免指针temp成为野指针
printf("删除成功\n");
return;
}
else
{
free(*pphead); //通讯录中只有一个节点(联系人的信息)
*pphead = NULL;
printf("删除成功\n");
printf("通讯录中已无联系人的信息\n");
return;
}
}
else //要删除的节点不是第一个节点(联系人的信息)
{
SLTNode* pcur = *pphead; //定义指针变量用于找到并删除节点
SLTNode* prev = *pphead; //定义指针变量用于将要删除节点之前的节点和之后的节点连接起来
while (num != 0)
{
prev = pcur;
pcur = pcur->next;
num--;
}
if (pcur->next == NULL) //要删除的节点是尾节点
{
prev->next = NULL;
printf("删除成功\n");
free(pcur);
pcur = NULL;
return;
}
else //要删除的节点不是尾节点
{
prev->next = pcur->next;
printf("删除成功\n");
free(pcur);
pcur = NULL;
return;
}
}
}
}
//查找联系人的信息
void SearchContact(SLTNode** pphead)
{
assert(pphead);
if (*pphead == NULL)
{
printf("通讯录中已无信息,无法查询");
return;
}
char phone[PHONE_MAX] = "";
printf("请输入你要查询的联系人的电话号码:");
scanf("%s", phone);
SLTNode* pcur = *pphead;
while (pcur != NULL)
{
if (strcmp(pcur->data.phone, phone) == 0)
{
printf("%-7s %-7s %-7s %-20s %-30s\n", "姓名", "性别", "年龄", "电话号码", "地址");
printf("%-8s", pcur->data.name);
printf("%-8s", pcur->data.gender);
printf("%-8d", pcur->data.age);
printf("%-21s", pcur->data.phone);
printf("%-30s\n", pcur->data.address);
return;
}
pcur = pcur->next;
}
printf("没有此电话号码的联系人,无法查找\n");
}
//修改联系人的信息
void ModifyContact(SLTNode** pphead)
{
assert(pphead);
if (*pphead == NULL)
{
printf("通讯录中已无信息,无法修改");
return;
}
char phone[PHONE_MAX] = "";
printf("请输入你要修改的联系人的电话号码:");
scanf("%s", phone);
SLTNode* pcur = *pphead;
while (pcur != NULL)
{
if (strcmp(pcur->data.phone, phone) == 0)
{
printf("请输入修改后的姓名:");
scanf("%s", pcur->data.name);
printf("请输入修改后的性别:");
scanf("%s", pcur->data.gender);
printf("请输入修改后的年龄:");
scanf("%d", &pcur->data.age);
printf("请输入修改后的电话号码:");
scanf("%s", pcur->data.phone);
printf("请输入修改后的地址:");
scanf("%s\n", pcur->data.address);
printf("修改成功\n");
return;
}
pcur = pcur->next;
}
printf("没有此电话号码的联系人,无法修改\n");
}
//展示联系人的信息
void DisplayContact(SLTNode** pphead)
{
assert(pphead);
if (*pphead == NULL)
{
printf("通讯录中已无信息,无法展示\n");
}
else
{
printf("%-7s %-7s %-7s %-20s %-30s\n", "姓名", "性别", "年龄", "电话号码", "地址");
SLTNode* pcur = *pphead;
while (pcur != NULL)
{
//调整展示通讯录信息的格式
printf("%-8s", pcur->data.name);
printf("%-8s", pcur->data.gender);
printf("%-8d", pcur->data.age);
printf("%-21s", pcur->data.phone);
printf("%-30s\n", pcur->data.address);
pcur = pcur->next;
}
}
}
void menu()
{
printf("*****************************************\n");
printf("********1.添加联系人 2.删除联系人********\n");
printf("********3.查找联系人 4.修改联系人********\n");
printf("********5.展示联系人 0. 退 出 ********\n");
printf("*****************************************\n");
}
int main()
{
SLTNode* contact = NULL;
int option = -1;
do
{
menu();
printf("请输入你要选择的数字:");
scanf("%d", &option);
switch (option)
{
case 1:
AddContact(&contact); //添加联系人的信息
break;
case 2:
DeleteContact(&contact); //删除联系人的信息
break;
case 3:
SearchContact(&contact); //查找联系人的信息
break;
case 4:
ModifyContact(&contact); //修改联系人的信息
break;
case 5:
DisplayContact(&contact); //展示联系人的信息
break;
case 0:
printf("退出成功");
break;
default:
printf("输入错误,请重新选择\n");
}
} while (option != 0); //option为0时,循环才终止
return 0;
}
个人总结:
①创建存放联系人信息的结构体。
②创建节点结构体,成员为存放联系人信息的结构体和指向下一个节点结构体的结构体指针。
③通讯录中的功能有添加联系人、删除联系人信息、查找联系人信息、修改联系人信息、展示联系人信息,故可用菜单、switch语句和一个整型变量来判断执行哪个函数(实现某一功能)再用上do while循环就能实现对选择功能的循环,直到选择的数字为0时退出循环④编写实现各种功能的函数
⑤测试运行
注意:在实现某一功能后,应先调试,然后再编写代码。
996

被折叠的 条评论
为什么被折叠?



