目录
- 前言
- 功能分析
- 整体框架思路(佛挡杀佛法)
- 初始化通讯录
- 增(Add)
- 展示(Show)通讯录
- 删(Delete)
- 查(Search)
- 改(Modify)
- 按名字排序(Sort)通讯录
- contact.h
- contact.c
- test.c
文章图片
前言 对于刚学完C语言理论知识的我们,一定需要做一些小项目来巩固我们所学过的理论知识,把理论转化为实践是重要的一步。学过不一定学会,学会不一定会敲代码。这篇通俗易懂的通讯录实现包你一看就会。看不会打我
大家好,我是_奇奇,为一名C/C++博主。河牧院大一在读。
欢迎大家和我一起交流学习
??编程的前途是光明的,道路是曲折的。笑到最后才是赢家
戳我跳到本人个人主页,点击查看更多知识点!
此篇实现通讯录的静态版。适合刚学完C语言的初学者。
功能分析 可以实现通讯录的增、删、查、改以及排序和展示。
整体框架思路(佛挡杀佛法)
- 思路也有个敲门,我把这个方法叫做 :佛挡杀佛法。这个方法意味着你不需要想那么多,直接开干,开始写代码,需要什么写什么,佛挡杀佛,神来杀神。方法具体如下
- 【小项目集合|C语言小项目——通讯录(适合刚学完C语言的初学者)】
首先
,一个通讯录没有人怎么行呢?这时我们要面对第一个最基本的功能就是给通讯录添加人员(增(Add)),所以我们要使用结构体构造学生的基本信息和通讯录的基本信息。
如下图所示
解释一下
- 这里的学生信息和通讯录信息的结构体都在头文件contact.h中。源文件使用时只需要在前面用预处理指令#include包含头文件名字就可以了。
- 这里用#define预处理指令设置常量。可以方便后期维护和修改。
- 这里typedef用来将结构体类型定义一个新名字,方便书写繁琐的类型,简便类型的书写。
- 通讯录结构体
Contact
是一种嵌套结构体。里面包含了一个学生信息结构体的数组。数组的大小是1000。还有记录学生个数的变量sz。
文章图片
-
第二
,有了这些结构体的构造,我们就要实现联系人的增加功能了,在这之前需要准备一个框架,用switch选择语句来进行功能的选取。
文章图片
- 在用switch语句时可以用enum枚举常量来构造每一个case的数。用来实现通讯录的菜单
- 这个也是提前写到头文件中的。
文章图片
- 代码如下
int main()
{
int n = 0;
Contact con;
char name[10] = { 0 };
InitContact(&con);
do
{
menu();
scanf("%d", &n);
switch (n)
{
case exitcontact:
printf("退出程序\n");
break;
case Add:
printf("增加通讯录成员:\n");
AddContact(&con);
break;
......
default:
printf("输入错误,请重新输入:");
break;
}
} while (n);
return 0;
}
文章图片
初始化通讯录
- 在增加人之前还需要将通讯录初始化一下,至少让学生信息和通讯录信息有初值。
- assert用来判断指针的有效性。若指针为空(null),将退出程序。
void InitContact(Contact* pc)
{
assert(pc);
//将通讯录人数初始化为0.
pc->sz = 0;
//内存函数memset,作用是将结构体数组的值全都初始化为0.
memset(pc->date, 0, sizeof(pc->date));
}
增(Add)
/************contact.h***********/
//增加通讯录人员
void AddContact(Contact* pc);
/************test.c***********/
// 通过结构体变量的地址。
可以提高运行效率。防止堆栈过大。
AddContact(&con);
- 为了程序的健壮性。先判断指针是否为空
- 再判断通讯录是否满了。然后依次通过指针间接访问结构体成员增加联系人的信息。
- 最后通过sz自增来记录通讯录联系人的个数。
/************contact.c***********/
void AddContact(Contact* pc)
{
assert(pc);
if (pc->sz == CONTACT_MAX)
{
printf("通讯录满了");
return;
}
printf("请输入要添加联系人的姓名:");
scanf("%s", pc->date[pc->sz].name);
printf("请输入要添加联系人的性别:");
scanf("%s", pc->date[pc->sz].sex);
printf("请输入要添加联系人的年龄:");
scanf("%d", &(pc->date[pc->sz].age));
printf("请输入要添加联系人的电话:");
scanf("%s", pc->date[pc->sz].tel);
printf("请输入要添加联系人的地址:");
scanf("%s", pc->date[pc->sz].addr);
pc->sz++;
printf("添加联系人成功\n");
}
展示(Show)通讯录
- 增加完联系人的后我们需要得到一个反馈。查看是否增加上去了。这时候就需要展示通讯录。
/************contact.h***********/
//显示通讯录人员
void ShowContact(Contact* pc);
/************test.c***********/
case Show:
ShowContact(&con);
break;
- 为了出现在控制台界面好看,出现对齐的情景。我们用制表符,左对齐等表示方法。
printf("%10s\t%5s\t%5s\t%20s\t%20s\t\n","姓名","性别","年龄","电话","地址");
实现这个功能、图片如下。
文章图片
/************contact.c***********/
void ShowContact(Contact* pc)
{
assert(pc);
int i = 0;
printf("%10s\t%5s\t%5s\t%20s\t%20s\t\n","姓名","性别","年龄","电话","地址");
for (i = 0;
i < pc->sz;
i++)
{
printf("%10s\t%5s\t%5d\t%20s\t%20s\t\n", pc->date[i].name, pc->date[i].sex, pc->date[i].age, pc->date[i].tel, pc->date[i].addr);
}
}
删(Delete)
- 在删除通讯录人员的时候我们先需要找到我们要删除的人。这里我们就要封装一个查找联系人的函数了。
- 这里需要注意找到你要删除的联系人后需要返回这个联系人所在的位置。以便于删除。这里的删除不是真的把内存中的这个位置删除。而是依次覆盖掉
/************contact.h***********/
//删除通讯录人员
void DeleteContact(Contact* pc, char* name);
//找通讯录人员
int FindContact(Contact* pc, char* name);
----------------------------------------------------------------------
/************test.c***********/
case Delete:
printf("删除通讯录人员:");
printf("请输入要删除的人员名字");
scanf("%s", name);
DeleteContact(&con, name);
break;
----------------------------------------------------------------------
----------------------------------------------------------------------
/************contact.c***********/
//找联系人
int FindContact(Contact* pc, char* name)
{
assert(pc && name);
int i = 0;
for (i = 0;
i < pc->sz;
i++)
{
if (strcmp(pc->date[i].name, name)==0)
{
return i;
}
}
return -1;
}
------------------------------分割线----------------------------------------
//删除联系人
void DeleteContact(Contact* pc, char* name)
{
assert(pc && name);
if (pc->sz == 0)
{
printf("已经没有联系人,不可删除\n");
}
int ret = FindContact(pc, name);
if (ret == -1)
{
printf("没有此人\n");
}
else
{
int j = 0;
for (j = ret;
j < pc->sz - 1;
j++)
{
pc->date[j] = pc->date[j + 1];
}
pc->sz--;
printf("删除成功\n");
}
}
----------------------------------------------------------------------
查(Search)
- 和删除联系人类似。此处不重复赘述。
/************contact.h***********/
//查找通讯录人员
void SearchContact(Contact* pc, char* name);
/************test.c***********/
case Search:
printf("请输入你要查找的联系人\n");
scanf("%s", name);
SearchContact(&con, name);
break;
/************contact.c***********/
void SearchContact(Contact* pc, char* name)
{
assert(pc && name);
int ret = FindContact(pc, name);
if (ret != -1)
{
printf("找到了\n");
printf("%10s\t%5s\t%5d\t%20s\t%20s\t\n", pc->date[ret].name, pc->date[ret].sex, pc->date[ret].age, pc->date[ret].tel, pc->date[ret].addr);
}
else
{
printf("没有找到\n");
}
}
改(Modify)
/************contact.h***********/
//修改通讯录人员
void ModifyContact(Contact* pc, char* name);
/************test.c***********/
case Modify:
printf("请输入要修改的联系人名字:");
scanf("%s", name);
ModifyContact(&con, name);
break;
/************contact.c***********/
void ModifyContact( Contact* pc, char* name)
{
assert(pc && name);
int ret = FindContact(pc, name);
if (ret != -1)
{
printf("找到了\n");
printf("%10s\t%5s\t%5s\t%20s\t%20s\t\n", "姓名", "性别", "年龄", "电话", "地址");
printf("%10s\t%5s\t%5d\t%20s\t%20s\t\n", pc->date[ret].name, pc->date[ret].sex, pc->date[ret].age, pc->date[ret].tel, pc->date[ret].addr);
printf("请修改\n");
printf("请输入联系人的名字:");
scanf("%s", pc->date[ret].name);
printf("请输入联系人的性别:");
scanf("%s", pc->date[ret].sex);
printf("请输入联系人的年龄:");
scanf("%d", &pc->date[ret].age);
printf("请输入联系人的电话:");
scanf("%s", pc->date[ret].tel);
printf("请输入联系人的地址:");
scanf("%s", pc->date[ret].addr);
printf("修改成功!\n");
}
}
按名字排序(Sort)通讯录
- 因为我比较懒 ,所以用了快速排序(qsort函数)。
- qsort函数具体使用详情点击查看之前博客:戳我查看->>>>>>10分钟可学会的快速排序
/************contact.h***********/
//排序通讯录人员
void SortContact(Contact* pc);
/************test.c***********/
case Sort:
printf("排序通讯录人员:\n");
SortContact(&con);
break;
/************contact.c***********/
int cmp_name(const void* e1, const void* e2)
{
return strcmp(((Student*)e1)->name, ((Student*)e2)->name);
}
void SortContact(Contact* pc)
{
assert(pc);
qsort(pc->date, pc->sz, sizeof(pc->date[0]), cmp_name);
printf("排序完成\n");
}
contact.h
#define _CRT_SECURE_NO_WARNINGS
#include
#include
#include
#include #define CONTACT_MAX 1000
#define NAME_MAX 10
#define SEX_MAX 10
#define TEL_MAX 20
#define ADDR_MAX 30typedef struct student
{
char name[NAME_MAX];
char sex[SEX_MAX];
int age;
char tel[TEL_MAX];
char addr[ADDR_MAX];
}Student;
typedef struct contact
{
Student date[CONTACT_MAX];
int sz;
}Contact;
enum contactmenu
{
exitcontact,
Add,
Delete,
Search,
Modify,
Show,
Sort,
};
//初始化通讯录
void InitContact(Contact* pc);
//增加通讯录人员
void AddContact(Contact* pc);
//显示通讯录人员
void ShowContact(Contact* pc);
//找通讯录人员
int FindContact(Contact* pc, char* name);
//删除通讯录人员
void DeleteContact(Contact* pc, char* name);
//查找通讯录人员
void SearchContact(Contact* pc, char* name);
//修改通讯录人员
void ModifyContact(Contact* pc, char* name);
//排序通讯录人员
void SortContact(Contact* pc);
contact.c
#include "contact.h"
#define _CRT_SECURE_NO_WARNINGSvoid InitContact(Contact* pc)
{
assert(pc);
pc->sz = 0;
memset(pc->date, 0, sizeof(pc->date));
}void AddContact(Contact* pc)
{
assert(pc);
if (pc->sz == CONTACT_MAX)
{
printf("通讯录满了");
return;
}
printf("请输入要添加联系人的姓名:");
scanf("%s", pc->date[pc->sz].name);
printf("请输入要添加联系人的性别:");
scanf("%s", pc->date[pc->sz].sex);
printf("请输入要添加联系人的年龄:");
scanf("%d", &(pc->date[pc->sz].age));
printf("请输入要添加联系人的电话:");
scanf("%s", pc->date[pc->sz].tel);
printf("请输入要添加联系人的地址:");
scanf("%s", pc->date[pc->sz].addr);
pc->sz++;
printf("添加联系人成功\n");
}
void ShowContact(Contact* pc)
{
assert(pc);
int i = 0;
printf("%10s\t%5s\t%5s\t%20s\t%20s\t\n","姓名","性别","年龄","电话","地址");
for (i = 0;
i < pc->sz;
i++)
{
printf("%10s\t%5s\t%5d\t%20s\t%20s\t\n", pc->date[i].name, pc->date[i].sex, pc->date[i].age, pc->date[i].tel, pc->date[i].addr);
}
}int FindContact(Contact* pc, char* name)
{
assert(pc && name);
int i = 0;
for (i = 0;
i < pc->sz;
i++)
{
if (strcmp(pc->date[i].name, name)==0)
{
return i;
}
}
return -1;
}void DeleteContact(Contact* pc, char* name)
{
assert(pc && name);
if (pc->sz == 0)
{
printf("已经没有联系人,不可删除\n");
}
int ret = FindContact(pc, name);
if (ret == -1)
{
printf("没有此人\n");
}
else
{
int j = 0;
for (j = ret;
j < pc->sz - 1;
j++)
{
pc->date[j] = pc->date[j + 1];
}
pc->sz--;
printf("删除成功\n");
}
}void SearchContact(Contact* pc, char* name)
{
assert(pc && name);
int ret = FindContact(pc, name);
if (ret != -1)
{
printf("找到了\n");
printf("%10s\t%5s\t%5d\t%20s\t%20s\t\n", pc->date[ret].name, pc->date[ret].sex, pc->date[ret].age, pc->date[ret].tel, pc->date[ret].addr);
}
else
{
printf("没有找到\n");
}
}
void ModifyContact( Contact* pc, char* name)
{
assert(pc && name);
int ret = FindContact(pc, name);
if (ret != -1)
{
printf("找到了\n");
printf("%10s\t%5s\t%5s\t%20s\t%20s\t\n", "姓名", "性别", "年龄", "电话", "地址");
printf("%10s\t%5s\t%5d\t%20s\t%20s\t\n", pc->date[ret].name, pc->date[ret].sex, pc->date[ret].age, pc->date[ret].tel, pc->date[ret].addr);
printf("请修改\n");
printf("请输入联系人的名字:");
scanf("%s", pc->date[ret].name);
printf("请输入联系人的性别:");
scanf("%s", pc->date[ret].sex);
printf("请输入联系人的年龄:");
scanf("%d", &pc->date[ret].age);
printf("请输入联系人的电话:");
scanf("%s", pc->date[ret].tel);
printf("请输入联系人的地址:");
scanf("%s", pc->date[ret].addr);
printf("修改成功!\n");
}
}
int cmp_name(const void* e1, const void* e2)
{
return strcmp(((Student*)e1)->name, ((Student*)e2)->name);
}
void SortContact(Contact* pc)
{
assert(pc);
qsort(pc->date, pc->sz, sizeof(pc->date[0]), cmp_name);
printf("排序完成\n");
}
test.c
#define _CRT_SECURE_NO_WARNINGS
#include "contact.h"
void menu()
{
printf("***************************\n");
printf("***************************\n");
printf("******1.Add2.Delete****\n");
printf("******3.Search 4.Modify****\n");
printf("******5.Show6.Sort******\n");
printf("******0.exit****\n");
printf("***************************\n");
printf("***************************\n");
}
int main()
{
int n = 0;
Contact con;
char name[10] = { 0 };
InitContact(&con);
do
{
menu();
scanf("%d", &n);
switch (n)
{
case exitcontact:
printf("退出程序\n");
break;
case Add:
printf("增加通讯录成员:\n");
AddContact(&con);
break;
case Delete:
printf("删除通讯录人员:");
printf("请输入要删除的人员名字");
scanf("%s", name);
DeleteContact(&con, name);
break;
case Search:
printf("请输入你要查找的联系人\n");
scanf("%s", name);
SearchContact(&con, name);
break;
case Modify:
printf("请输入要修改的联系人名字:");
scanf("%s", name);
ModifyContact(&con, name);
break;
case Show:
ShowContact(&con);
break;
case Sort:
printf("排序通讯录人员:\n");
SortContact(&con);
break;
default:
printf("输入错误,请重新输入:");
break;
}
} while (n);
return 0;
}
推荐阅读
- 二叉树(Binary|LeetCode 337. House Robber III - 二叉树系列题25
- Java面试题大全|【备战面试】面试题打卡——Mysql相关面试题总结
- LeetCode|【每日一题】——合并区间
- LeetCode|【每日一题】——单调递增的数字
- 架构师|17:00面试,17:04就出来了 ,问的实在是太...
- 剑指offer编程题解法汇总|力扣解法汇总504-七进制数
- 国产化之虚拟ARM64-CPU安装银河麒麟操作系统
- it|.Net Core之选项模式Options使用
- 数据结构|MySQL数据库 ---MySQL表的增删改查(进阶)