数据结构——基于单链表实现通讯管理系统

文章目录

  • 一、前言
    • SList.h
    • SList.c
  • 二、通讯录的实现
    • 通讯录项目
    • Contact.h
    • 载入数据
    • 初始化通讯录
    • 添加通讯录数据
    • 通过姓名查找联系人
    • 删除通讯录数据
    • 展示通讯录数据
    • 查找通讯录数据
    • 修改通讯录数据
    • 保存通讯录
    • 销毁通讯录数据
  • 三、所有源代码
    • Contact.h
    • Contact.c
    • SList.h
    • SList.c
    • test.c

一、前言

这个通讯录是基于单链表实现的,关于单链表,之前已经做过完整的实现方法——数据结构——单链表(C语言版)
用单链表实现的通讯录其实和用顺序表实现的通讯录类似,可以参考该文章——基于动态顺序表的应用——通讯录


完成该通讯录需要引进经过修改后的单链表的文件

SList.h

#pragma once
#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
#include <string.h>
#include  "Contact.h"typedef PeoInfo SLTDateType;typedef struct SListNode
{SLTDateType date;struct SListNode* next;
}SLTNode;//尾插
void SLTPushBack(SLTNode** pphead, SLTDateType x);//头插
void SLTPushFront(SLTNode** pphead, SLTDateType x);//尾删
void SLTPopBack(SLTNode** pphead);//头删
void SLTPopFront(SLTNode** pphead);//在指定位置之前插入数据
void SLTInsert(SLTNode** pphead, SLTNode* pos, SLTDateType x);//在指定位置之后插入数据
void SLTInsertAfter(SLTNode* pos, SLTDateType x);//删除pos结点
void SLTErase(SLTNode** pphead, SLTNode* pos);//删除pos之后的结点
void SLTEraseAfter(SLTNode* pos);//销毁链表
void SListDesTroy(SLTNode** pphead);

SList.c

#define _CRT_SECURE_NO_WARNINGS 1
#include "SList.h"//申请新的结点
SLTNode* SLTBuyNode(SLTDateType x)
{SLTNode* newnode = (SLTNode*)malloc(sizeof(SLTNode));if (newnode == NULL){printf("malloc fail!");exit(1);}newnode->date = x;newnode->next = NULL;return newnode;
}//尾插
void SLTPushBack(SLTNode** pphead, SLTDateType x)
{assert(pphead);SLTNode* newnode = SLTBuyNode(x);//空链表 和 非空链表if (*pphead == NULL){*pphead = newnode;}else{SLTNode* ptail = *pphead;while (ptail->next){ptail = ptail->next;}ptail->next = newnode;}
}//头插
void SLTPushFront(SLTNode** pphead, SLTDateType x)
{assert(pphead);SLTNode* newnode = SLTBuyNode(x);newnode->next = *pphead;*pphead = newnode;
}//尾删
void SLTPopBack(SLTNode** pphead)
{assert(pphead && *pphead);//只有一个结点if ((*pphead)->next == NULL){free(*pphead);*pphead = NULL;}//多个结点else{SLTNode* prev = *pphead;SLTNode* ptail = *pphead;while (ptail->next){prev = ptail;ptail = ptail->next;}free(ptail);ptail = NULL;prev->next = NULL;}
}//头删
void SLTPopFront(SLTNode** pphead)
{assert(pphead && *pphead);SLTNode* next = (*pphead)->next;free(*pphead);*pphead = next;
}//在指定位置之前插入数据
void SLTInsert(SLTNode** pphead, SLTNode* pos, SLTDateType x)
{assert(pphead && *pphead);assert(pos);if (*pphead == pos){SLTPushFront(pphead, x);}else{SLTNode* newnode = SLTBuyNode(x);SLTNode* prev = *pphead;while (prev->next != pos){prev = prev->next;}prev->next = newnode;newnode->next = pos;}}//在指定位置之后插入数据
void SLTInsertAfter(SLTNode* pos, SLTDateType x)
{assert(pos);SLTNode* newnode = SLTBuyNode(x);newnode->next = pos->next;pos->next = newnode;
}//删除pos结点
void SLTErase(SLTNode** pphead, SLTNode* pos)
{assert(pphead && *pphead);assert(pos);if (pos == *pphead){SLTPopFront(pphead);}else{SLTNode* prev = *pphead;while (prev->next != pos){prev = prev->next;}prev->next = pos->next;free(pos);pos = NULL;}}//删除pos之后的结点
void SLTEraseAfter(SLTNode* pos)
{assert(pos && pos->next);SLTNode* del = pos->next;pos->next = del->next;free(del);del = NULL;
}//销毁链表
void SListDesTroy(SLTNode** pphead)
{assert(pphead && *pphead);SLTNode* pcur = *pphead;while (pcur){SLTNode* next = pcur->next;free(pcur);pcur = next;}*pphead = NULL;
}

二、通讯录的实现

通讯录项目

创建一个通讯录项目,包含以下文件:

在这里插入图片描述

Contact.h 通讯录的头文件,包含通讯录的声明以及相关函数的声明
Contact.c 通讯录函数的具体实现方法
contact.txt 保存通讯录中的数据

SList.h 单链表的声明
SList.c 单链表函数的声明

test.c 测试代码,也可以当菜单

Contact.h

#pragma once
#define NAME_MAX 100
#define SEX_MAX 4
#define TEL_MAX 11
#define ADDR_MAX 100//联系人的数据
//姓名 性别 年龄 电话 地址
typedef struct PersonInfo
{char name[NAME_MAX];char sex[SEX_MAX];int age;char tel[TEL_MAX];char addr[ADDR_MAX];
}PeoInfo;//前置声明
typedef struct SListNode 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);

载入数据

//载入数据
void LoadContact(contact** con)
{FILE* pf = fopen("contact.txt", "r");//判断读取是否成功if (pf == NULL){perror("fopen fail!");return;}//循环读取数据PeoInfo info;while (fread(&info, sizeof(PeoInfo), 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);
}

通过姓名查找联系人

//通过姓名查找联系人
contact* FindByName(contact* con, char name[])
{contact* pcur = con;while (pcur){if (strcmp(pcur->date.name, name) == 0){return pcur;}pcur = pcur->next;}return NULL;
}

删除通讯录数据

//删除通讯录数据
void DelContact(contact** con)
{char name[NAME_MAX];printf("请输入要删除的联系人的姓名->");scanf("%s", name);contact* pos = FindByName(*con, name);if (pos != NULL){SLTErase(con, pos);printf("删除成功!\n");}else{printf("删除失败!没有该联系人!\n");}
}

展示通讯录数据

//展示通讯录数据
void ShowContact(contact* con)
{printf("%6s %6s %6s %6s %6s\n", "姓名", "性别", "年龄", "电话", "地址");contact* pcur = con;while (pcur){printf("%6s %6s %6d %6s %6s\n",pcur->date.name,pcur->date.sex,pcur->date.age,pcur->date.tel,pcur->date.addr);pcur = pcur->next;}
}

查找通讯录数据

//查找通讯录数据
void FindContact(contact* con)
{char name[NAME_MAX];printf("请输入要查找的联系人的姓名->");scanf("%s", name);contact* pos = FindByName(con, name);if (pos == NULL){printf("没有该联系人!\n");}else{printf("找到了!该联系人的信息如下:\n");printf("%6s %6s %6s %6s %6s\n", "姓名", "性别", "年龄", "电话", "地址");printf("%6s %6s %6d %6s %6s\n",pos->date.name,pos->date.sex,pos->date.age,pos->date.tel,pos->date.addr);}
}

修改通讯录数据

//修改通讯录数据
void ModifyContact(contact** con)
{char name[NAME_MAX];printf("请输入要修改的联系人的姓名->");scanf("%s", name);contact* pos = FindByName(*con, name);if (pos == NULL){printf("没有该联系人!\n");}else{printf("开始修改!\n");printf("联系人的新姓名为:\n");scanf("%s", pos->date.name);printf("联系人的新性别为:\n");scanf("%s", pos->date.sex);printf("联系人的新年龄为:\n");scanf("%d", &pos->date.age);printf("联系人的新电话为:\n");scanf("%s", pos->date.tel);printf("联系人的新地址为:\n");scanf("%s", pos->date.addr);printf("修改成功!\n");}
}

保存通讯录

//保存通讯录
void SaveContact(contact* con)
{FILE* pf = fopen("contact.txt", "w");if (pf == NULL){perror("fopen fail!");return;}//将通讯录数据写入文件contact* pcur = con;while (pcur){fwrite(&(pcur->date), sizeof(pcur->date), 1, pf);pcur = pcur->next;}printf("通讯录保存成功!\n");
}

销毁通讯录数据

//销毁通讯录数据
void DestroyContact(contact** con)
{//在销毁通讯录之前,保存数据SaveContact(*con);SListDesTroy(con);
}

三、所有源代码

Contact.h

#pragma once
#define NAME_MAX 100
#define SEX_MAX 4
#define TEL_MAX 11
#define ADDR_MAX 100//联系人的数据
//姓名 性别 年龄 电话 地址
typedef struct PersonInfo
{char name[NAME_MAX];char sex[SEX_MAX];int age;char tel[TEL_MAX];char addr[ADDR_MAX];
}PeoInfo;//前置声明
typedef struct SListNode 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

#define _CRT_SECURE_NO_WARNINGS 1
#include "Contact.h"
#include "SList.h"//载入数据
void LoadContact(contact** con)
{FILE* pf = fopen("contact.txt", "r");//判断读取是否成功if (pf == NULL){perror("fopen fail!");return;}//循环读取数据PeoInfo info;while (fread(&info, sizeof(PeoInfo), 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);
}//通过姓名查找联系人
contact* FindByName(contact* con, char name[])
{contact* pcur = con;while (pcur){if (strcmp(pcur->date.name, name) == 0){return pcur;}pcur = pcur->next;}return NULL;
}//删除通讯录数据
void DelContact(contact** con)
{char name[NAME_MAX];printf("请输入要删除的联系人的姓名->");scanf("%s", name);contact* pos = FindByName(*con, name);if (pos != NULL){SLTErase(con, pos);printf("删除成功!\n");}else{printf("删除失败!没有该联系人!\n");}
}//展示通讯录数据
void ShowContact(contact* con)
{printf("%6s %6s %6s %6s %6s\n", "姓名", "性别", "年龄", "电话", "地址");contact* pcur = con;while (pcur){printf("%6s %6s %6d %6s %6s\n",pcur->date.name,pcur->date.sex,pcur->date.age,pcur->date.tel,pcur->date.addr);pcur = pcur->next;}
}//查找通讯录数据
void FindContact(contact* con)
{char name[NAME_MAX];printf("请输入要查找的联系人的姓名->");scanf("%s", name);contact* pos = FindByName(con, name);if (pos == NULL){printf("没有该联系人!\n");}else{printf("找到了!该联系人的信息如下:\n");printf("%6s %6s %6s %6s %6s\n", "姓名", "性别", "年龄", "电话", "地址");printf("%6s %6s %6d %6s %6s\n",pos->date.name,pos->date.sex,pos->date.age,pos->date.tel,pos->date.addr);}
}//修改通讯录数据
void ModifyContact(contact** con)
{char name[NAME_MAX];printf("请输入要修改的联系人的姓名->");scanf("%s", name);contact* pos = FindByName(*con, name);if (pos == NULL){printf("没有该联系人!\n");}else{printf("开始修改!\n");printf("联系人的新姓名为:\n");scanf("%s", pos->date.name);printf("联系人的新性别为:\n");scanf("%s", pos->date.sex);printf("联系人的新年龄为:\n");scanf("%d", &pos->date.age);printf("联系人的新电话为:\n");scanf("%s", pos->date.tel);printf("联系人的新地址为:\n");scanf("%s", pos->date.addr);printf("修改成功!\n");}
}//保存通讯录
void SaveContact(contact* con)
{FILE* pf = fopen("contact.txt", "w");if (pf == NULL){perror("fopen fail!");return;}//将通讯录数据写入文件contact* pcur = con;while (pcur){fwrite(&(pcur->date), sizeof(pcur->date), 1, pf);pcur = pcur->next;}printf("通讯录保存成功!\n");
}//销毁通讯录数据
void DestroyContact(contact** con)
{//在销毁通讯录之前,保存数据SaveContact(*con);SListDesTroy(con);
}

SList.h

#pragma once
#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
#include <string.h>
#include  "Contact.h"typedef PeoInfo SLTDateType;typedef struct SListNode
{SLTDateType date;struct SListNode* next;
}SLTNode;//尾插
void SLTPushBack(SLTNode** pphead, SLTDateType x);//头插
void SLTPushFront(SLTNode** pphead, SLTDateType x);//尾删
void SLTPopBack(SLTNode** pphead);//头删
void SLTPopFront(SLTNode** pphead);//在指定位置之前插入数据
void SLTInsert(SLTNode** pphead, SLTNode* pos, SLTDateType x);//在指定位置之后插入数据
void SLTInsertAfter(SLTNode* pos, SLTDateType x);//删除pos结点
void SLTErase(SLTNode** pphead, SLTNode* pos);//删除pos之后的结点
void SLTEraseAfter(SLTNode* pos);//销毁链表
void SListDesTroy(SLTNode** pphead);

SList.c

#define _CRT_SECURE_NO_WARNINGS 1
#include "SList.h"//申请新的结点
SLTNode* SLTBuyNode(SLTDateType x)
{SLTNode* newnode = (SLTNode*)malloc(sizeof(SLTNode));if (newnode == NULL){printf("malloc fail!");exit(1);}newnode->date = x;newnode->next = NULL;return newnode;
}//尾插
void SLTPushBack(SLTNode** pphead, SLTDateType x)
{assert(pphead);SLTNode* newnode = SLTBuyNode(x);//空链表 和 非空链表if (*pphead == NULL){*pphead = newnode;}else{SLTNode* ptail = *pphead;while (ptail->next){ptail = ptail->next;}ptail->next = newnode;}
}//头插
void SLTPushFront(SLTNode** pphead, SLTDateType x)
{assert(pphead);SLTNode* newnode = SLTBuyNode(x);newnode->next = *pphead;*pphead = newnode;
}//尾删
void SLTPopBack(SLTNode** pphead)
{assert(pphead && *pphead);//只有一个结点if ((*pphead)->next == NULL){free(*pphead);*pphead = NULL;}//多个结点else{SLTNode* prev = *pphead;SLTNode* ptail = *pphead;while (ptail->next){prev = ptail;ptail = ptail->next;}free(ptail);ptail = NULL;prev->next = NULL;}
}//头删
void SLTPopFront(SLTNode** pphead)
{assert(pphead && *pphead);SLTNode* next = (*pphead)->next;free(*pphead);*pphead = next;
}//在指定位置之前插入数据
void SLTInsert(SLTNode** pphead, SLTNode* pos, SLTDateType x)
{assert(pphead && *pphead);assert(pos);if (*pphead == pos){SLTPushFront(pphead, x);}else{SLTNode* newnode = SLTBuyNode(x);SLTNode* prev = *pphead;while (prev->next != pos){prev = prev->next;}prev->next = newnode;newnode->next = pos;}}//在指定位置之后插入数据
void SLTInsertAfter(SLTNode* pos, SLTDateType x)
{assert(pos);SLTNode* newnode = SLTBuyNode(x);newnode->next = pos->next;pos->next = newnode;
}//删除pos结点
void SLTErase(SLTNode** pphead, SLTNode* pos)
{assert(pphead && *pphead);assert(pos);if (pos == *pphead){SLTPopFront(pphead);}else{SLTNode* prev = *pphead;while (prev->next != pos){prev = prev->next;}prev->next = pos->next;free(pos);pos = NULL;}}//删除pos之后的结点
void SLTEraseAfter(SLTNode* pos)
{assert(pos && pos->next);SLTNode* del = pos->next;pos->next = del->next;free(del);del = NULL;
}//销毁链表
void SListDesTroy(SLTNode** pphead)
{assert(pphead && *pphead);SLTNode* pcur = *pphead;while (pcur){SLTNode* next = pcur->next;free(pcur);pcur = next;}*pphead = NULL;
}

test.c

#define _CRT_SECURE_NO_WARNINGS 1
#include "SList.h"
//测试代码——菜单
void menu()
{printf("****************通讯录*******************\n");printf("******1.添加联系人    2.删除联系人*******\n");printf("******3.修改联系人    4.查找联系人*******\n");printf("******5.展示联系人    0. 退出************\n");printf("*****************************************\n");
}int main()
{int input = 0;contact* con = NULL;//初始化InitContact(&con);do{menu();printf("选择你的操作->");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 != 0);//销毁通讯录;DestroyContact(&con);return 0;
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/615982.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

OpenHarmony南向开发案例:【智能门锁】

一. 简介 本demo是基于Openharmony 3.1 Beta本版开发&#xff0c;不仅可以接收数字管家应用下发的指令来控制门锁开启&#xff0c;而且还可以通过数字管家设置不同的开锁密码以及一次性密码&#xff0c;实现给临时用户一个临时密码&#xff0c;保证门户安全。当然除了开锁的功…

2024年公共管理、健康与大数据国际学术会议(ICPAHBD 2024)

2024 International Conference on Public Administration, Health and Big Data (ICPAHBD 2024) ●会议简介 2024年公共管理、健康与大数据国际学术会议&#xff08;ICPAHBD 2024&#xff09;即将在宁波盛大召开。本次会议旨在汇聚全球公共管理、健康与大数据领域的专家学者…

【计算机毕业设计】疫情期间医院门诊管理系统——后附源码

&#x1f389;**欢迎来到我的技术世界&#xff01;**&#x1f389; &#x1f4d8; 博主小档案&#xff1a; 一名来自世界500强的资深程序媛&#xff0c;毕业于国内知名985高校。 &#x1f527; 技术专长&#xff1a; 在深度学习任务中展现出卓越的能力&#xff0c;包括但不限于…

中级物流师、高级物流师资格认证考试大纲《物流管理实务》

物流管理实务 第一章 物流市场调查 一、市场调查基本知识 二、物流市场调研 三、物流市场预测 四、物流市场调研报告 第二章 仓库规划与设计 一、仓储规划概述 二、仓库规模和数量规划 三、仓库选址规划 四、仓库的结构与布局 五、自动化立体仓库的规划与设计 第…

STL库 —— list 的编写

目录 一、成员变量 ​编辑 二、push_back 函数 三、迭代器 iterator 3.1 iterator 结构体 3.2 begin() 与 end() 函数 3.3 iterator 运算符重载 3.4 -> 的重载 3.5 const_iterator 四、测试代码 五、修饰符成员 5.1 insert 函数 5.2 erase 函数 5.3 push 函数…

PE文件的分析和构造超详细过程

本文详细讲述如何从0构造一个PE文件&#xff0c;运行该文件会弹出一个HelloPE的窗口 目录 预备知识 1. 构造DOS头IMAGE_DOS_HEADER 1.1 构造DOS_MZ头 1.2 构造DOS_STUB 2、构造PE头IMAGE_NT_HEADERS 248字节 2.1 signature 2.2 IMAGE_FILE_HEADER 2.3 IMAGE_OPTI…

iOS开发之为什么需要引用计数

iOS开发之为什么需要引用计数 在iOS开发中&#xff0c;Objective-C与Swift语言都是通过引用计数进行内存管理&#xff0c;实际上Python、Ruby、C等语言也提供了基于引用计数的内存管理方式&#xff0c;它们有一个共同点&#xff0c;那就是都是面向对象的编程语言。 引用计数可…

LeetCode-72. 编辑距离【字符串 动态规划】

LeetCode-72. 编辑距离【字符串 动态规划】 题目描述&#xff1a;解题思路一&#xff1a;动规五部曲解题思路二&#xff1a;动态规划【版本二】解题思路三&#xff1a;0 题目描述&#xff1a; 给你两个单词 word1 和 word2&#xff0c; 请返回将 word1 转换成 word2 所使用的最…

java项目之校园兼职系统(ssm框架+mysql数据库+文档)

项目简介 校园兼职系统的主要使用者分为&#xff1a;管理员&#xff1a;首页、个人中心、专业管理、商家管理、热门兼职管理、学生管理、兼职接单管理、学生咨询管理、兼职任务管理、完成评价管理、管理员管理、系统管理等模块信息的查看及相应操作&#xff1b;学生&#xff1…

·13·1dawwd

c语言中的小小白-CSDN博客c语言中的小小白关注算法,c,c语言,贪心算法,链表,mysql,动态规划,后端,线性回归,数据结构,排序算法领域.https://blog.csdn.net/bhbcdxb123?spm1001.2014.3001.5343 给大家分享一句我很喜欢我话&#xff1a; 知不足而奋进&#xff0c;望远山而前行&am…

使用 Python 标记具有相同名称的条目

如果大家想在 Python 中标记具有相同名称的条目&#xff0c;可以使用字典&#xff08;Dictionary&#xff09;或集合&#xff08;Set&#xff09;来实现。这取决于你们希望如何存储和使用这些条目。下面我将提供两种常见的方法来实现这个目标。 1、问题背景 在处理数据时&…

Unity让地图素材遮挡人物

点击编辑/项目设置/图形&#xff0c;透明度排序模式设置自定义轴&#xff0c;透明度排序轴Y设置为1其他为0。 此时人物和地图素材的图层排序相等&#xff0c;当人物的高度大于地图素材时&#xff0c;人物则被遮挡。