—————————————————————————————————
首先在写通讯录之前,必须明确我们的需求:
因为是基础版,我在这里暂时只实现以下一些需求(绝不是因为我暂时只写了这么些):
/*
添加联系人信息
删除指定联系人信息
查找指定联系人信息
修改指定联系人信息
显示所有联系人信息
清空所有联系人
*/
—————————————————————————————————
首先是创建我们的联系人结构体
typedef struct Contacts
{
char name[NAME_MAX];
int age;
char sex[SEX_MAX];
char address[ADDRESS_MAX];
char numbers[NUMBERS_MAX];
struct Contacts* next;
}Contacts;
—————————————————————————————————
添加联系人
这里最大的要点,也是经常有人会犯错误的点,就是传入结构体头指针时,必须得是二级指针,因为我们是要对指针进行修改的。
而且我们需要对链表一开始是否为NULL进行分类讨论。
void ConInfor(Contacts* con)
{
printf("请输入姓名:");
scanf("%s", con->name);
printf("请输入年龄:");
scanf("%d", &con->age);
printf("请输入性别:");
scanf("%s", con->sex);
printf("请输入家庭地址:");
scanf("%s", con->address);
printf("请输入电话号码:");
scanf("%s", con->numbers);
con->next = NULL;
}
void AddContacts(Contacts** pphead)//一定是二级指针!!!!!
{
Contacts* new_contacts = (Contacts*)malloc(sizeof(Contacts));
ConInfor(new_contacts);
if (*pphead == NULL)
{
*pphead = new_contacts;
}
else
{
Contacts* cur = *pphead;
while (cur->next != NULL)
{
cur = cur->next;
}
cur->next = new_contacts;
}
}
这里有个小细节,就是我把输入联系人单独封装成了一个函数,因为这块代码一定会在我们修改联系人那一个功能上用到。
—————————————————————————————————
删除联系人
我认为这一块是实现单链表通讯录的一个难点之一。
难点其一,还是二级指针
其二,就是如何在删除结点的同时,再连接被删除位置前后的结点。
其三,就是针对链表为NULL,只有一个结点和不止一个结点的三种情况的不同解决方法。
解决方法:1,链表为空,直接返回
2.仅有一个结点,删除(释放)结点,头结点置成NULL
3.多个结点,使用双指针,分别记录当前结点地址,和当前结点上一个的地址。
void DelContacts(Contacts** pphead)
{
printf("请输入被删除联系人姓名:");
char name[NAME_MAX];
scanf("%s", name);
int flag = 1;
if (*pphead == NULL)//链表为空
{
printf("删除失败,通讯录为空!\n");
return;
}
else if ((*pphead)->next==NULL)//链表有一个结点
{
if (strcmp(name, (*pphead)->name) == 0)
{
*pphead = NULL;
printf("删除成功!\n");
flag = 0;
}
}
else//链表有多个结点
{
Contacts* prve =*pphead;
Contacts* cur = *pphead;
if (strcmp(name, cur->name) == 0)
{
*pphead = cur->next;
printf("删除成功!\n");
return;
}
while (cur != NULL)
{
if (strcmp(name,cur->name) == 0)
{
prve->next = cur->next;
free(cur);
flag = 0;
printf("删除成功!\n");
break;
}
prve = cur;
cur = cur->next;
}
}
if (flag == 1)
{
printf("查无此人,无法删除!\n");
}
}
—————————————————————————————————
查找联系人
这一块就很简单了,和删除联系人的函数有很大的重叠部分,因为我们删除的时候就需要找到被删的联系人对不对?这里对一二级指针要求就不严格了,但我建议是用一级指针,防止误操作。
void CheckContacts(Contacts* phead)
{
Contacts* cur = phead;
printf("请输入所要查找联系人姓名:");
char name[NAME_MAX];
scanf("%s", name);
while (cur != NULL)
{
if (strcmp(name, cur->name) == 0)
{
printf("已找到!\n");
printf("姓名 年龄 性别 电话号码 住址\n");
Print(cur);
return;
}
cur = cur->next;
}
printf("查无此人!\n");
}
显示所有联系人信息
按照查找的方式,遍历链表时打印就欧克了。
void PrintContacts(Contacts* phead)
{
if (phead == NULL)
{
printf("通讯录为空\n");
}
else
{
printf("姓名 年龄 性别 电话号码 住址\n");
while (phead != NULL)
{
Print(phead);
phead = phead->next;
}
}
}
void Print(Contacts* phead)
{
printf("%-20s ", phead->name);//这里的-是左对齐,20是域宽
printf("%-5d ", phead->age);//这里的-是左对齐,5是域宽
printf("%-5s ", phead->sex);//这里的-是左对齐,5是域宽
printf("%-20s ", phead->numbers);
printf("%-20s \n", phead->address);
}
—————————————————————————————————
清空联系人
这一块就得注意了,可不能以为给头指针置NULL就拍拍屁股走人了,这就是典型的穿上裤子就不认人了,我们可不能做这样的程序猿。必须得挨个给每个结点释放了,防止内存泄漏。这里依然要用到双指针!!
void ClearContacts(Contacts** pphead)
{
Contacts* prve = *pphead;
Contacts* cur = *pphead;
while (cur != NULL)
{
prve = cur;
cur = cur->next;
free(prve);
}
*pphead = NULL;//最后置NULL,才是负责的程序猿
printf("已清空!\n");
}
#define _CRT_SECURE_NO_WARNINGS
//宏定义
#define NAME_MAX 20
#define SEX_MAX 10
#define ADDRESS_MAX 20
#define NUMBERS_MAX 15
//头文件包含
#include
#include
#include
//枚举常量定义
enum Choose
{
EXIT,
ADD,
DEL,
CHECK,
MODIFY,
PRINT,
CLEAR,
SORT
};
//结构体定义
typedef struct Contacts
{
char name[NAME_MAX];
int age;
char sex[SEX_MAX];
char address[ADDRESS_MAX];
char numbers[NUMBERS_MAX];
struct Contacts* next;
}Contacts;
//函数声明
void menu();
/*
添加联系人信息
删除指定联系人信息
查找指定联系人信息
修改指定联系人信息
显示所有联系人信息
清空所有联系人
*/
//同名同姓暂不处理
void AddContacts(Contacts** pphead);//添加联系人
void PrintContacts(Contacts* phead);//打印联系人
void Print(Contacts* phead);//打印单独封装
void DelContacts(Contacts** pphead);//删除联系人
void CheckContacts(Contacts* phead);//查找联系人,仅姓名
void ClearContacts(Contacts** pphead);//清空通讯录
void SortContacts(Contacts** pphead);
#include"Contaction.h"
void menu()
{
printf(" __________________________\n");
printf("|______ 1.添加联系人 ______|\n");
printf("|______ 2.删除联系人 ______|\n");
printf("|______ 3.查找联系人 ______|\n");
printf("|______ 4.修改联系人 ______|\n");
printf("|______ 5.打印联系人 ______|\n");
printf("|______ 6.清空联系人 ______|\n");
printf("|______ 7.通讯录排序 ______|\n");
printf("|______ 0.退出通讯录 ______|\n");
printf("|__________________________|\n");
}
void ConInfor(Contacts* con)
{
printf("请输入姓名:");
scanf("%s", con->name);
printf("请输入年龄:");
scanf("%d", &con->age);
printf("请输入性别:");
scanf("%s", con->sex);
printf("请输入家庭地址:");
scanf("%s", con->address);
printf("请输入电话号码:");
scanf("%s", con->numbers);
con->next = NULL;
}
void AddContacts(Contacts** pphead)
{
Contacts* new_contacts = (Contacts*)malloc(sizeof(Contacts));
ConInfor(new_contacts);
if (*pphead == NULL)
{
*pphead = new_contacts;
}
else
{
Contacts* cur = *pphead;
while (cur->next != NULL)
{
cur = cur->next;
}
cur->next = new_contacts;
}
}
void DelContacts(Contacts** pphead)
{
printf("请输入被删除联系人姓名:");
char name[NAME_MAX];
scanf("%s", name);
int flag = 1;
if (*pphead == NULL)
{
printf("删除失败,通讯录为空!\n");
return;
}
else if ((*pphead)->next==NULL)
{
if (strcmp(name, (*pphead)->name) == 0)
{
*pphead = NULL;
printf("删除成功!\n");
flag = 0;
}
}
else
{
Contacts* prve =*pphead;
Contacts* cur = *pphead;
if (strcmp(name, cur->name) == 0)
{
*pphead = cur->next;
printf("删除成功!\n");
return;
}
while (cur != NULL)
{
if (strcmp(name,cur->name) == 0)
{
prve->next = cur->next;
free(cur);
flag = 0;
printf("删除成功!\n");
break;
}
prve = cur;
cur = cur->next;
}
}
if (flag == 1)
{
printf("查无此人,无法删除!\n");
}
}
void CheckContacts(Contacts* phead)
{
Contacts* cur = phead;
printf("请输入所要查找联系人姓名:");
char name[NAME_MAX];
scanf("%s", name);
while (cur != NULL)
{
if (strcmp(name, cur->name) == 0)
{
printf("已找到!\n");
printf("姓名 年龄 性别 电话号码 住址\n");
Print(cur);
return;
}
cur = cur->next;
}
printf("查无此人!\n");
}
void PrintContacts(Contacts* phead)
{
if (phead == NULL)
{
printf("通讯录为空\n");
}
else
{
printf("姓名 年龄 性别 电话号码 住址\n");
while (phead != NULL)
{
Print(phead);
phead = phead->next;
}
}
}
void Print(Contacts* phead)
{
printf("%-20s ", phead->name);
printf("%-5d ", phead->age);
printf("%-5s ", phead->sex);
printf("%-20s ", phead->numbers);
printf("%-20s \n", phead->address);
}
void ClearContacts(Contacts** pphead)
{
Contacts* prve = *pphead;
Contacts* cur = *pphead;
while (cur != NULL)
{
prve = cur;
cur = cur->next;
free(prve);
}
*pphead = NULL;
printf("已清空!\n");
}
void SortContacts(Contacts** pphead)
{
}
int main()
{
menu();
int input = 0;
Contacts *con=NULL;
do {
printf("请选择:\n");
scanf("%d", &input);
switch (input)
{
case EXIT:
printf("已退出!\n");
break;
case ADD:
AddContacts(&con);
break;
case DEL:
DelContacts(&con);
break;
case CHECK:
CheckContacts(con);
break;
case MODIFY:
break;
case PRINT:
PrintContacts(con);
break;
case CLEAR:
ClearContacts(&con);
break;
case SORT:
break;
default:
break;
}
} while (input);
return 0;
}
以上呢,就是基础的通讯录实现啦,还有很多功能还未完善,比如排序,同名同姓处理方法等,大家不妨可以关注我,我会马不停蹄的更新的进阶版的!!!
—————————————————————————————————