通讯录 2.0
之前分享过使用顺序表思想实现通讯录,现在分享使用单链表实现的通讯录,我们只需要规定每个链表的元素是结构体类型,每个结构体内存放联系人信息即可。
**不断地练习才能熟练掌握!**代码逻辑很简单,实现时注意边界的处理即可。
头文件
//Contact.h
#pragma once
#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
#include <string.h>
#define NAME_MAX 100
#define GENDER_MAX 4
#define TEL_MAX 11
//用户数据
typedef struct PersonInfo
{
char name[NAME_MAX];
char gender[GENDER_MAX];
size_t age;
char tel[TEL_MAX];
}PeoInfo;
typedef struct Contact
{
PeoInfo data;
struct Contact* next;
}contact;
//初始化通讯录
void InitContact(contact** con);
//添加通讯录数据
void AddContact(contact** con);
//删除通讯录数据
void DelContact(contact** con);
//展示通讯录数据
void ShowContact(contact* con);
//查找通讯录数据
void FindContact(contact* con);
//修改通讯录数据
void ModifyContact(contact** con);
//销毁通讯录数据
void DestroyContact(contact** con);
通讯录操作函数
通讯录
//Contact.c
#include "Contact.h"
void InitContact(contact** con)
{
*con = NULL;
}
void AddContact(contact** con)
{
assert(con);
PeoInfo new;
printf("请输入新联系人的姓名:\n");
scanf("%s", new.name);
printf("请输入新联系人的年龄:\n");
scanf("%zd", &new.age);
printf("请输入新联系人的电话:\n");
scanf("%s", new.tel);
printf("请输入新联系人的性别:\n");
scanf("%s", new.gender);
contact* newnode = (contact*)malloc(sizeof(contact));
if (NULL == newnode)
{
perror("malloc");
exit(-1);
}
newnode->data = new;
newnode->next = NULL;
if (*con == NULL)
{
*con = newnode;
return;
}
contact* cur = *con;
while (cur->next)
{
cur = cur->next;
}
cur->next = newnode;
}
void DelContact(contact** con)
{
//链表为空
if (!(*con))
{
printf("通讯录为空!\n");
return;
}
char newname[NAME_MAX] = { 0 };
printf("请输入要删除的联系人的姓名:\n");
scanf("%s", newname);
//链表首结点元素匹配,避免后续prev为NULL时,对它解引用
if (strcmp((*con)->data.name, newname) == 0)
{
if ((*con)->next == NULL)
{
free(*con);
*con = NULL;
}
else
{
contact* tmp = (*con)->next;
free(*con);
*con = tmp;
}
printf("删除成功!\n");
return;
}
contact* cur = (*con)->next;
contact* prev = *con;
while (cur)
{
if (strcmp(newname, cur->data.name) == 0)
{
prev->next = cur->next;
free(cur);
printf("删除成功!\n");
return;
}
prev = cur;
cur = cur->next;
}
printf("您要删除的联系人不存在!\n");
}
void ShowContact(contact* con)
{
if (!con)
{
printf("通讯录为空!\n");
}
printf("----------------------------------------------------------------------------------\n");
printf("%-11s %-11s %-11s %-11s\n", "姓名", "年龄", "电话", "性别");
contact* cur = con;
while (cur)
{
printf("%-11s %-11zd %-11s %-11s\n", cur->data.name, cur->data.age, cur->data.tel, cur->data.gender);
cur = cur->next;
}
printf("----------------------------------------------------------------------------------\n");
}
void FindContact(contact* con)
{
if (!con)
{
printf("通讯录为空!\n");
return;
}
printf("请输入您要查询的联系人的姓名:\n");
char find[NAME_MAX] = { 0 };
scanf("%s", find);
contact* cur = con;
while (cur)
{
if (strcmp(find, cur->data.name) == 0)
{
printf("查询结果如下:\n");
printf("%-11s %-11zd %-11s %-11s\n", cur->data.name, cur->data.age, cur->data.tel, cur->data.gender);
return;
}
cur = cur->next;
}
printf("您要查询的联系人不存在!\n");
}
void ModifyContact(contact** con)
{
if (!(*con))
{
printf("通讯录为空!\n");
return;
}
printf("请输入您要修改的联系人的姓名:\n");
char obj[NAME_MAX] = { 0 };
scanf("%s", obj);
//char newname[NAME_MAX] = { 0 };
//int newage = 0;
//char newtel[TEL_MAX] = { 0 };
//char newgender[GENDER_MAX] = { 0 };
contact* cur = *con;
while (cur)
{
if (strcmp(obj, cur->data.name) == 0)
{
printf("请输入修改后的姓名:\n");
scanf("%s", cur->data.name);
printf("请输入修改后的年龄:\n");
scanf("%zd", &(cur->data.age));
printf("请输入修改后的电话:\n");
scanf("%s", cur->data.tel);
printf("请输入修改后的性别:\n");
scanf("%s", cur->data.gender);
printf("修改成功!\n");
return;
}
cur = cur->next;
}
printf("您要修改的联系人不存在!\n");
}
void DestroyContact(contact** con)
{
contact* cur = *con;
while (cur)
{
contact* tail = cur->next;
free(cur);
cur = tail;
}
*con = NULL;
}
通讯录主函数
包括菜单、读取数据、保存数据的函数实现。
//test.c
#include "Contact.h"
//菜单
void menu()
{
printf("******************通讯录*******************\n");
printf("*******1.添加联系人 2.删除联系人*******\n");
printf("*******3.修改联系人 4.查询联系人*******\n");
printf("*******5.展示通讯录 0.退出通讯录*******\n");
printf("*******************************************\n");
}
//载入数据函数
void LoadContact(contact** con)
{
FILE* pf = fopen("Contact.txt", "rb");
if (NULL == pf)
{
perror("fopen");
exit(-1);
}
PeoInfo buff;
while (fread(&buff, sizeof(PeoInfo), 1, pf))
{
contact* newnode = (contact*)malloc(sizeof(contact));
if (NULL == newnode)
{
perror("malloc");
exit(-1);
}
newnode->next = NULL;
newnode->data = buff;
if (*con == NULL)
{
*con = newnode;
continue;
}
contact* cur = *con;
while (cur->next)
{
cur = cur->next;
}
cur->next = newnode;
}
printf("历史数据载入成功!\n");
}
//保存数据函数
void SaveContact(contact* con)
{
FILE* pf = fopen("Contact.txt", "wb");
if (NULL == pf)
{
perror("fopen");
exit(-1);
}
contact* cur = con;
while (cur)
{
PeoInfo wr = cur->data;
fwrite(&wr, sizeof(PeoInfo), 1, pf);
cur = cur->next;
}
printf("数据保存成功!\n");
}
//主函数
int main()
{
contact* con;
InitContact(&con);
LoadContact(&con);
int input = 0;
do
{
menu();
printf("请输入你想执行的操作:\n");
scanf("%d", &input);
switch (input)
{
case 1:AddContact(&con);
break;
case 2:DelContact(&con);
break;
case 3:ModifyContact(&con);
break;
case 4:FindContact(con);
break;
case 5:ShowContact(con);
break;
case 0:printf("退出通讯录\n");
break;
default:
printf("输入非法,请重新输入!\n");
break;
}
} while (input);
SaveContact(con);
DestroyContact(&con);
return 0;
}
执行程序的效果: