学习完了单链表的基本操作后,我掌握了其增删改查等基本操作。基于这些操作,我用实现了简易通讯录管理系统。包含初始化、添加、删除、打印、搜索、排序和修改等功能。以下为源代码(测试环境为VS2013):
#define _CRT_SECURE_NO_WARNINGS 1
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int count = 0;//计数
typedef struct PersonNode
{
int pid;//联系人的序号(节点序号)
char name[20]; //姓名
int age; //年龄
char phone_num[20]; //手机号码
struct PersonNode* next; //指向下一个结构体的指针
}PersonNode;
typedef struct SList
{
struct PersonNode* first;
}SList;
//初始化通讯录
void Init(SList* list)
{
list->first = NULL;
printf("通讯录初始化成功!\n");
}
//添加联系人(单链表的尾插)
void AddPerson(SList* list)
{
char c;
PersonNode* Node;
PersonNode* p = list->first;
do
{
//申请新节点用来存储联系人的信息
Node = (PersonNode*)malloc(sizeof(PersonNode));
printf("请输入联系人姓名:");
scanf("%s", &Node->name);
printf("请输入联系人年龄:");
scanf("%d", &Node->age);
printf("请输入联系人手机号码:");
scanf("%s", &Node->phone_num);
//美申请一个节点,count自加,再赋值给pid
count++;
Node->pid = count;
//将新申请的节点链接到链表尾部,再使新节点的next指向空
Node->next = NULL;
if (p == NULL)
{
//若添加时此通讯录是空的
list->first= Node;
p = list->first;
}
else
{
while (p->next != NULL)
{
//寻找最后一个节点进行尾插
p = p->next;
}
p->next = Node;
}
printf("是否继续添加?(Y/N):");
while ((c = getchar()) != EOF && c != '\n'); //清除缓冲区内容
c = getchar();
} while (c == 'Y'||c=='y');
return;
}
//删除联系人
void DelPerson(SList* list)
{
int num = 0;
PersonNode* prev = NULL;
PersonNode* cur = list->first;
//若通讯录为空
if (list->first == NULL)
{
printf("通讯录为空,删除失败!\n");
return;
}
printf("请输入想要删除的序号: ");
scanf("%d", &num);
//若通讯录不空且还没有匹配到序号
while (cur != NULL && cur->pid != num)
{
prev = cur;
cur = cur->next;
}
//若要删除的序号不存在(已经遍历完了整个链表)
if (cur == NULL)
{
printf("输入的序号有误,删除失败!\n");
return;
}
//若要删除的联系人即为第一个
if (prev == NULL)
{
//头删
PersonNode* old_node = list->first;
list->first = list->first->next;
free(old_node);
count--;
printf("删除成功!\n");
return;
}
//否则,若删除的为中间某一节点
prev->next = cur->next;
free(cur);
printf("删除成功!\n");
count--;
}
//打印联系人
void PrintPerson(SList* list)
{
PersonNode* p ;
p = list->first;
int i = 0;//计数器
printf("序号\t\t姓名\t\t年龄\t\t手机号码 \n");
printf("====\t\t======\t\t====\t\t===========\n");
for (p = list->first; p != NULL; p = p->next)
{
i++;
printf("%2d\t\t%s\t\t%d\t\t%s\n",i, p->name, p->age, p->phone_num);
}
printf("共有%d条记录!\n", count);
return;
}
//查找
int Find(char* name, SList* list)
{
int i = 0;
PersonNode* cur = list->first;
for (i = 1,cur=list->first; i <= count,cur!=NULL; i++,cur=cur->next)
{
//若姓名匹配
if (strcmp(name, cur->name) == 0)
{
return 1;
}
}
//查找失败
return -1;
}
//搜索联系人
void SearchPerson(SList* list)
{
PersonNode* cur = list->first;
int tmp = 0;//定义临时变量来接收Find函数的返回值
int n = 0;//临时计数器
char name[20] = "0";
//若还没有录入
if (list->first == NULL)
{
printf("通讯录为空,搜索失败!\n");
return;
}
printf("请输入联系人的姓名来进行搜索: ");
scanf("%s", name);
if (-1 == Find(name, list))
{
printf("查询失败!\n");
}
else
{
printf("序号\t\t姓名\t\t年龄\t\t手机号码 \n");
printf("====\t\t======\t\t====\t\t===========\n");
for (cur = list->first; cur != NULL; cur = cur->next)
{
if (strcmp(cur->name, name) == 0)
{
n++;
printf("%2d\t\t%s\t\t%d\t\t%s\n", n, cur->name, cur->age, cur->phone_num);
}
}
printf("共有%d条记录!\n", n);
}
}
//联系人排序
void SortPerson(SList* list)
{
//若通讯录还没有联系人
if (list->first == NULL)
{
printf("通讯录为空,排序失败!\n");
return;
}
//若通讯录只有一个人
if (list->first->next == NULL)
{
printf("排序成功!\n");
return;
}
//若通讯录里有多个联系人
PersonNode* cur = NULL;
PersonNode* tail = NULL;
cur = list->first;
while (cur != tail)
{
while (cur->next != tail)
{
if (cur->age > cur->next->age)
{
//交换姓名
char tmp1[20] = "0";
strcpy(tmp1, cur->name);
strcpy(cur->name, cur->next->name);
strcpy(cur->next->name, tmp1);
//交换年龄
int temp = 0;
temp = cur->age;
cur->age = cur->next->age;
cur->next->age = temp;
//交换手机号码
char tmp2[20] = "0";
strcpy(tmp2, cur->phone_num);
strcpy(cur->phone_num, cur->next->phone_num);
strcpy(cur->next->phone_num, tmp2);
}
cur = cur->next;
}
//cur找到最后一个节点,使tail指向最后的节点,
//再使cur从链表头部开始遍历
tail = cur;
cur = list->first;
}
printf("排序成功!\n");
}
//修改联系人信息
void ModifyPerson(SList* list)
{
char name[15] = "0";
char new_name[15] = "0";
int new_age = 0;
char new_phone_num[20] = "0";
int choice = 0;
//若联系人为空
if (list->first == NULL)
{
printf("通讯录为空,修改失败!\n");
return;
}
//若通讯录不为空
//通过cur指针来遍历链表,找到欲修改的节点然后再操作
PersonNode * cur = list->first;
//先根据名字查询联系人
printf("请输入你想要修改的联系人的姓名: ");
scanf("%s", name);
while (cur != NULL)
{
//若匹配成功
if (strcmp(name, cur->name) == 0)
{
printf("请选择你想要修改的信息的标号: 1.姓名 2.年龄 3.手机号码: ");
scanf("%d", &choice);
if (1 == choice)
{
printf("请输入新的姓名: ");
scanf("%s", new_name);
strcpy(cur->name, new_name);
}
if (2 == choice)
{
printf("请输入新的年龄: ");
scanf("%d", &new_age);
cur->age = new_age;
}
if (3 == choice)
{
printf("请输入新的手机号码: ");
scanf("%s", new_phone_num);
strcpy(cur->phone_num, new_phone_num);
}
printf("修改成功!\n");
return;
}
cur = cur->next;
}
printf("查询失败!通讯录无此联系人!\n");
return;
}
//菜单
void menu()
{
printf(" ----------欢迎使用Romeo的通讯录----------\n");
printf(" 0.数据初始化 1.添加联系人 \n");
printf(" 2.删除联系人 3.打印联系人 ");
printf(" 4.搜索联系人 5.联系人排序 ");
printf(" 6.修改联系人 7.退出通讯录 ");
printf(" ----------------Romeo制作----------------\n");
}
int main()
{
SList list;
int select = 0;
while (1)
{
menu();
printf("请输入相应的选项: ");
scanf("%d", &select);
switch (select)
{
case 0: Init(&list);
break;
case 1: AddPerson(&list);
break;
case 2:DelPerson(&list);
break;
case 3: PrintPerson(&list);
break;
case 4: SearchPerson(&list);
break;
case 5: SortPerson(&list);
break;
case 6: ModifyPerson(&list);
break;
case 7:
printf("即将退出本系统,谢谢您的使用!\n");
system("pause");
return 0;
default:printf("输入有误,请重新输入!\n");
break;
}
}
system("pause");
return 0;
}
运行结果:
初始化:
添加联系人:
打印联系人:
删除并打印结果:
搜索联系人:
联系人排序(按年龄从小到大):
修改联系人: