C语言 单链表实现通讯录基础版,保证看完都大呼简单!

—————————————————————————————————
首先在写通讯录之前,必须明确我们的需求
因为是基础版,我在这里暂时只实现以下一些需求(绝不是因为我暂时只写了这么些):

/*
添加联系人信息
删除指定联系人信息
查找指定联系人信息
修改指定联系人信息
显示所有联系人信息
清空所有联系人
*/

—————————————————————————————————
首先是创建我们的联系人结构体

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");
}

源代码

.h文件

#define _CRT_SECURE_NO_WARNINGS
//宏定义
#define NAME_MAX 20
#define SEX_MAX 10
#define ADDRESS_MAX 20
#define NUMBERS_MAX 15
//头文件包含
#include<stdio.h>
#include<malloc.h>
#include<string.h>//枚举常量定义
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);

.c文件

#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;
}

以上呢,就是基础的通讯录实现啦,还有很多功能还未完善,比如排序同名同姓处理方法等,大家不妨可以关注我,我会马不停蹄的更新的进阶版的!!!
—————————————————————————————————

C语言 单链表通讯录基础版实现,保证看完都直呼easy相关推荐

  1. java语言程序设计教程第三版答案,看完跪了

    01 如何理解高并发? 高并发意味着大流量,需要运用技术手段抵抗流量的冲击,这些手段好比操作流量,能让流量更平稳地被系统所处理,带给用户更好的体验. 我们常见的高并发场景有:淘宝的双11.春运时的抢票 ...

  2. C语言一趟冒泡交换最小值,C语言单链表冒泡排序为啥以下代码实现不了?

    struct node *sort(struct node *head)/*排序*/ { struct node *p,*q; struct node *temp; for(p=head;p!=NUL ...

  3. c语言单链表功能,[数据结构]单链表(C语言)的各种功能

    06-03阅读200,000 + 链表是一种常见的基本数据结构,在此充分利用了结构指针. 链表可以动态存储和分配,即链表是一个功能非常强大的数组. 他可以在节点中定义多种数据类型,并可以根据需要随意添 ...

  4. C语言单链表,能直接运行的代码!

    C语言单链表,实现增删改查 不废话 直接上代码,COPY就能运行 #include <stdio.h> #include <stdlib.h> /** *定义数据元素 */ t ...

  5. C++语言单链表实现荷兰旗问题

    C++语言单链表实现荷兰旗问题 一.设备及软件 VC6.0 二.语言 C++ 三.涉及的数据结构与算法 单链表.尾插法 四.问题描述 荷兰旗问题亦称三色旗问题. 这里荷兰旗用0,1,2分别表示三种颜色 ...

  6. C语言单链表基本操作总结

    C语言单链表基本操作     本文是参考他人实现的C语言单链表,对多篇博文整理的结果,仅作为学习笔记.文末有参考出处. 1.单链表定义 链表是通过一组任意的存储单元来存储线性表中的数据元素,这些存储单 ...

  7. C语言单链表代码实现

    C语言单链表代码实现 一.头文件.常量以及自定义数据结构 #include<stdio.h> #include<malloc.h> #include<stdlib.h&g ...

  8. c语言单链表倒置(附原理讲解)

    c语言单链表倒置 今天博主,讲一个单链表倒置的例子,事实上 话不多说,我们直接上代码,待会会给大家讲解倒置算法实现原理 #include<stdio.h> #include<stdl ...

  9. C语言单链表初学容易掉的坑

    C语言单链表初学容易掉的坑 结点的指针没有分配内存. 一个链表最基本的操作有建立.增加.删除.查找,几乎所有操作都离不开中间结点p.比如,建立时先检查是否空链表,若是,则令head指向结点p所指向的值 ...

最新文章

  1. C++中的内存对齐介绍
  2. python在中小学教学中的应用-中小学Python教学的几点建议
  3. nginx日志分析查询异常请求IP之狙击网络黑客
  4. C语言 实现登录注册功能
  5. maven snapshot和release版本号之间的差
  6. uploadify 3.1 /3.2 在Firefox,Chrome 浏览器下,进入页面请求两次问题解决办法。
  7. 拖拽文件作为文件输入
  8. 使用 selenium 下载小视频
  9. 单例模式(java代码实现)
  10. linux中如何从txt转为nc文件,【转】linux下nc的使用
  11. 盘古搜索22日开通 欲打造一流搜索引擎
  12. Java程序员职业发展规划和方向有哪些?
  13. 【学习笔记】kaggle案例之泰坦尼克号(基于R)
  14. 安装火绒的情况下怎么关闭防火墙
  15. ORB-Mono原理梳理
  16. HZNU2509 曲院风荷——折半搜索
  17. 羊城杯2022--Writeup
  18. 星际战甲堕落轰击者结合目标_warframe星际战甲新手必备mod分享
  19. 说点我关于演员黄轩的了解
  20. 外篇:关于理财的一些个人见解

热门文章

  1. Unity 之 UGUI TextMeshPro控件详解
  2. JavaScript中的数组常用方法总结
  3. 服务器判断ua-302跳转方法--2016年4月14日
  4. 黑龙江省计算机科学与技术大学排名,2016黑龙江省大学一级学科排行榜
  5. python使用suds访问用.net开发的webservice的API接口
  6. 从0开始的生活开始了
  7. Python案例:有四个数字:1、2、3、4,能组成多少个互不相同且无重复数字的三位数?各是多少?
  8. PS教程:套索羽化法溶图
  9. 暗数据现状堪忧 Splunk给出实现数据驱动的四点建议
  10. 学计算机可以用xps吗,设计师用什么笔记本电脑好?戴尔XPS 17创作本有颜又有料...