【数据结构】利用单链表再实现通讯录

在之前顺序表的实现中,我们利用了顺序表实现了通讯录,基于上篇文章学习了单链表,本篇文章将介绍如何利用单链表再实现通讯录。

1. 结构体用户数据

实现结构体的函数:

复制代码
//⽤⼾数据
typedef struct PersonInfo
{
     char name[NAME_MAX];
     char sex[SEX_MAX];
     int age;
     char tel[TEL_MAX];
     char addr[ADDR_MAX];
}PeoInfo;

2. 通讯录数据导入

实现将历史数据导入通讯录的函数:

复制代码
void LoadContact(contact** con) 
{
     FILE* pf = fopen("contact.txt", "rb");
     if (pf == NULL) 
     {
         perror("fopen error!\n");
         return;
     }
     //循环读取⽂件数据
     PeoInfo info;
     while (fread(&info, sizeof(info), 1, pf))
     {
         SLTPushBack(con, info);
     }
     printf("历史数据导⼊通讯录成功!\n");
}

3. 通讯录数据初始化

实现通讯录数据初始化的函数:

复制代码
void InitContact(contact** con) 
{
     LoadContact(con);//把本地的通讯录数据导⼊到链表结构
}

4. 添加通讯录数据

实现添加通讯录数据的函数:

复制代码
void AddContact(contact** con) 
{
     PeoInfo info;
     printf("请输⼊姓名:\n");
     scanf("%s", &info.name);
     printf("请输⼊性别:\n");
     scanf("%s", &info.sex);
     printf("请输⼊年龄:\n");
     scanf("%d", &info.age);
     printf("请输⼊联系电话:\n");
     scanf("%s", &info.tel);
     printf("请输⼊地址:\n");
     scanf("%s", &info.addr);
     SLTPushBack(con, info);
     printf("插⼊成功!\n");
}

5. 删除通讯录数据

实现删除通讯录数据的函数:

复制代码
contact* FindByName(contact* con, char name[]) 
{
     contact* cur = con;
     while (cur)
     {
         if (strcmp(cur->data.name, name) == 0) 
         {
             return cur;
         }
     cur = cur->next;
     }
     return NULL;
}

void DelContact(contact** con) 
{
     char name[NAME_MAX];
     printf("请输⼊要删除的⽤⼾姓名:\n");
     scanf("%s", name);
     contact* pos = FindByName(*con, name);
     if (pos == NULL) 
     {
         printf("要删除的⽤⼾不存在,删除失败!\n");
         return;
     }
     SLTErase(con, pos);
     printf("删除成功!\n");
}

6. 展现通讯录数据

实现展现通讯录数据的函数:

复制代码
void ShowContact(contact* con) 
{
     printf("%-10s %-4s %-4s %15s %-20s\n", "姓名", "性别", "年龄", "联系电话", "地址");
     contact* cur = con;
     while (cur)
     {
         printf("%-10s %-4s %-4d %15s %-20s\n",
         cur->data.name,
         cur->data.sex,
         cur->data.age,
         cur->data.tel,
         cur->data.addr);
         cur = cur->next;
     }
}

7. 查找通讯录数据

实现查找通讯录数据的函数:

复制代码
void FindContact(contact* con) 
{
     char name[NAME_MAX];
     printf("请输⼊要查找的⽤⼾姓名:\n");
     scanf("%s", name);
     contact* pos = FindByName(con, name);
     if (pos == NULL) 
     {
         printf("要查找的⽤⼾不存在,查找失败!\n");
         return;
     }
     printf("查找成功!\n");
     printf("%-10s %-4s %-4d %15s %-20s\n",
     pos->data.name,
     pos->data.sex,
     pos->data.age,
     pos->data.tel,
     pos->data.addr);
}

8. 修改通讯录数据

实现修改通讯录数据的函数:

复制代码
void ModifyContact(contact** con) 
{
     char name[NAME_MAX];
     printf("请输⼊要修改的⽤⼾名称:\n");
     scanf("%s", &name);
     contact* pos = FindByName(*con, name);
     if (pos == NULL) 
     {
         printf("要查找的⽤⼾不存在,修改失败!\n");
         return;
     }
     printf("请输⼊要修改的姓名:\n");
     scanf("%s", pos->data.name);
     printf("请输⼊要修改的性别:\n");
     scanf("%s", pos->data.sex);
     printf("请输⼊要修改的年龄:\n");
     scanf("%d", &pos->data.age);
     printf("请输⼊要修改的联系电话:\n");
     scanf("%s", pos->data.tel);
     printf("请输⼊要修改的地址:\n");
     scanf("%s", pos->data.addr);
     printf("修改成功!\n");
}

9. 保存通讯录数据

实现保存通讯录数据的函数:

复制代码
 void SaveContact(contact* con) 
 {
     FILE* pf = fopen("contact.txt", "wb");
     if (pf == NULL) 
     {
         perror("fopen error!\n");
         return;
     }
     //将通讯录数据写⼊⽂件
     contact* cur = con;
     while (cur)
     {
         fwrite(&(cur->data), sizeof(cur->data), 1, pf);
         cur = cur->next;
     }
     printf("通讯录数据保存成功!\n");
 }

10. 销毁通讯录数据

实现销毁通讯录数据的函数:

复制代码
void DestroyContact(contact** con) 
{
     SaveContact(*con);//在通讯录销毁之前,先把历史数据保存到本地⽂件中contact.txt
     SListDesTroy(con);
}

最后附上全部代码 :

复制代码
//contact.h
#pragma once
#define NAME_MAX 100
#define SEX_MAX 4
#define TEL_MAX 11
#define ADDR_MAX 100

//前置声明
typedef struct SListNode contact;

//⽤⼾数据
typedef struct PersonInfo
{
     char name[NAME_MAX];
     char sex[SEX_MAX];
     int age;
     char tel[TEL_MAX];
     char addr[ADDR_MAX];
}PeoInfo;

//初始化通讯录
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
#define _CRT_SECURE_NO_WARNINGS
#include"contact.h"
#include"SList.h"//部分函数上篇文章讲过可以直接用

void LoadContact(contact** con) 
{
     FILE* pf = fopen("contact.txt", "rb");
     if (pf == NULL) 
     {
         perror("fopen error!\n");
         return;
     }
     //循环读取⽂件数据
     PeoInfo info;
     while (fread(&info, sizeof(info), 1, pf))
     {
         SLTPushBack(con, info);
     }
     printf("历史数据导⼊通讯录成功!\n");
}

void InitContact(contact** con) 
{
     LoadContact(con);//把本地的通讯录数据导⼊到链表结构
}

void AddContact(contact** con) 
{
     PeoInfo info;
     printf("请输⼊姓名:\n");
     scanf("%s", &info.name);
     printf("请输⼊性别:\n");
     scanf("%s", &info.sex);
     printf("请输⼊年龄:\n");
     scanf("%d", &info.age);
     printf("请输⼊联系电话:\n");
     scanf("%s", &info.tel);
     printf("请输⼊地址:\n");
     scanf("%s", &info.addr);
     SLTPushBack(con, info);
     printf("插⼊成功!\n");
}

contact* FindByName(contact* con, char name[]) 
{
     contact* cur = con;
     while (cur)
     {
         if (strcmp(cur->data.name, name) == 0) 
         {
             return cur;
         }
     cur = cur->next;
     }
     return NULL;
}

void DelContact(contact** con) 
{
     char name[NAME_MAX];
     printf("请输⼊要删除的⽤⼾姓名:\n");
     scanf("%s", name);
     contact* pos = FindByName(*con, name);
     if (pos == NULL) 
     {
         printf("要删除的⽤⼾不存在,删除失败!\n");
         return;
     }
     SLTErase(con, pos);
     printf("删除成功!\n");
}

void ShowContact(contact* con) 
{
     printf("%-10s %-4s %-4s %15s %-20s\n", "姓名", "性别", "年龄", "联系电话", "地址");
     contact* cur = con;
     while (cur)
     {
         printf("%-10s %-4s %-4d %15s %-20s\n",
         cur->data.name,
         cur->data.sex,
         cur->data.age,
         cur->data.tel,
         cur->data.addr);
         cur = cur->next;
     }
}

void FindContact(contact* con) 
{
     char name[NAME_MAX];
     printf("请输⼊要查找的⽤⼾姓名:\n");
     scanf("%s", name);
     contact* pos = FindByName(con, name);
     if (pos == NULL) 
     {
         printf("要查找的⽤⼾不存在,查找失败!\n");
         return;
     }
     printf("查找成功!\n");
     printf("%-10s %-4s %-4d %15s %-20s\n",
     pos->data.name,
     pos->data.sex,
     pos->data.age,
     pos->data.tel,
     pos->data.addr);
}

void ModifyContact(contact** con) 
{
     char name[NAME_MAX];
     printf("请输⼊要修改的⽤⼾名称:\n");
     scanf("%s", &name);
     contact* pos = FindByName(*con, name);
     if (pos == NULL) 
     {
         printf("要查找的⽤⼾不存在,修改失败!\n");
         return;
     }
     printf("请输⼊要修改的姓名:\n");
     scanf("%s", pos->data.name);
     printf("请输⼊要修改的性别:\n");
     scanf("%s", pos->data.sex);
     printf("请输⼊要修改的年龄:\n");
     scanf("%d", &pos->data.age);
     printf("请输⼊要修改的联系电话:\n");
     scanf("%s", pos->data.tel);
     printf("请输⼊要修改的地址:\n");
     scanf("%s", pos->data.addr);
     printf("修改成功!\n");
}

 void SaveContact(contact* con) 
 {
     FILE* pf = fopen("contact.txt", "wb");
     if (pf == NULL) 
     {
         perror("fopen error!\n");
         return;
     }
     //将通讯录数据写⼊⽂件
     contact* cur = con;
     while (cur)
     {
         fwrite(&(cur->data), sizeof(cur->data), 1, pf);
         cur = cur->next;
     }
     printf("通讯录数据保存成功!\n");
 }

void DestroyContact(contact** con) 
{
     SaveContact(*con);//在通讯录销毁之前,先把历史数据保存到本地⽂件中contact.txt
     SListDesTroy(con);
}

在接下来我们将会学习更多有意思的东西,如果本篇有不理解的地方,欢迎私信我或在评论区指出,期待与你们共同进步。创作不易,望各位大佬一键三连!

相关推荐
YUS云生35 分钟前
Python学习笔记·第31天:FastAPI入门——路由、路径参数、查询参数与请求体
笔记·python·学习
玖玥拾1 小时前
C# 语言进阶(十五)C# 游戏服务端 MySQL 数据库
服务器·开发语言·网络·数据库·mysql·c#
铅笔侠_小龙虾1 小时前
Rust 学习目录
开发语言·学习·rust
云泽8082 小时前
从零吃透 C++ 异常:抛出捕获、栈展开、异常重抛与编码规范详解
开发语言·c++·代码规范
灯澜忆梦2 小时前
GO---可见性规则
开发语言·golang
逝水无殇2 小时前
C# 文件的输入与输出详解
开发语言·数据库·后端·c#
渣渣灰飞3 小时前
MySQL 系统学习 第五阶段:企业级 MySQL 实战开发 第二章:RBAC 权限系统设计
android·学习·mysql
六bring个六3 小时前
open Harmony中分布式软总线的学习任务清单
分布式·学习·c/c++·open harmony
这是个栗子3 小时前
前端开发中的常用工具函数(八)
开发语言·前端·javascript
凤凰院凶涛QAQ3 小时前
《Java版数据结构 & 集合类剖析》栈与队列:“push/pop 是栈的灵魂,offer/poll 是队列的骨架——四组 API,两种人生”
java·开发语言·数据结构