引言
如果要用C语言实现通讯录的话,我们需要知道要实现什么功能。对于通讯录来说,除了初始化,就为最基本的增删查改,我就开始一一讲解。
步骤
我们创建文件时,因为代码比较多,为了不使代码冗余。我们需要创建一个用来执行通讯录的源文件,然后就是执行通讯录内部函数代码的源文件,再创建一个用来存放内部函数声明的头文件。
首先是通讯录的初始化,由于通讯录需要存储多种数据,所以我是使用结构体类型。
#pragma once
#include<stdio.h>
#include<string.h>
#define MAX 100
#define NA_MAX 20
#define SE_MAX 5
#define ADDR_MAX 20
#define TEL_MAX 12
typedef struct PeoInfo
{
char name[NA_MAX];
int age;
char sex[SE_MAX];
char addr[ADDR_MAX];
char tel[TEL_MAX];
}PeoInfo;
//姓名 年龄 性别 地址 电话
typedef struct Conatct
{
PeoInfo data[MAX];//存放的信息
int size;//当前存放信息的个数
}Conatct;
void InitContact(Conatct* pc);
void AddContact(Conatct* pc);
void DelContact(Conatct* pc);
void SerachContact(const Conatct* pc);
void ModiftyContact(Conatct* pc);
void SortContact(Conatct* pc);
void ShowContact(const Conatct* pc);
为了方便修改,其中的大小使用宏来替换。typedef的作用是改变类型名称,这样方便之后的书写。
我们的通讯录肯定是需要记住存储数据的个数,从而判断是否还有数据,并且是否超出数据的最大存储量,因此我们再使用一个结构体对其进行封装。
接下来,我们创建大概的整体逻辑,创建一个简单的菜单用来表明每个功能如何使用。
再整体的逻辑中我们的通讯录一定不可能只用一次,所以整体是以循环实现的。
#include"contact.h"
void menu()
{
printf("***********************************\n");
printf("**** 1.add 2.del ****\n");
printf("**** 3.search 4.modify ****\n");
printf("**** 5.show 6.sort ****\n");
printf("**** 0.exit ****\n");
printf("***********************************\n");
}
int main()
{
int input = 0;
Conatct con;
InitContact(&con);
do {
menu();
printf("请输入数字\n");
scanf("%d", &input);
switch (input)
{
case 1:
AddContact(&con);
break;
case 2:
DelContact(&con);
break;
case 3:
SerachContact(&con);
break;
case 4:
ModiftyContact(&con);
break;
case 5:
ShowContact(&con);
break;
case 6:
SortContact(&con);
break;
case 0:
printf("退出通讯录");
break;
default :
printf("选择错误");
break;
}
} while (input);
return 0;
}
通过循环来实现遍历,通过switch语句,来实习各个函数的功能。
先实现数据的初始化。
void InitContact(Conatct* pc)
{
pc->size = 0;
memset(pc->data, 0, sizeof(pc->data));
}
通过以上代码,数据个数为零,并将通讯录进行初始化,。
void AddContact(Conatct* pc)
{
if (pc->size == MAX)
{
printf("通讯录已满\n");
return;
}
printf("请输入姓名:\n");
scanf("%s", pc->data[pc->size].name);
printf("请输入年龄:\n");
scanf("%d", &pc->data[pc->size].age);
printf("请输入性别:\n");
scanf("%s", pc->data[pc->size].sex);
printf("请输入住址:\n");
scanf("%s", pc->data[pc->size].addr);
printf("请输入电话:\n");
scanf("%s", pc->data[pc->size].tel);
printf("增加成功\n");
pc->size++;
}
这个函数是用来实现增加代码的操作,首先我们需要判断一下通讯录是否已满,如果通讯录已经变慢,那么便无法增加数据,直接返回return。如果可以就通过scanf函数来实现数据的增加,最后再对size++表明数据加1。
int SerachName(Conatct* pc, char name[])
{
int i = 0;
for (i = 0; i < pc->size; i++)
{
if (strcmp(pc->data[i].name,name) == 0)
{
return i;
}
}
return -1;
}
我们在后面的编写代码中发现,删、查、改我们都需要用到找。所以我们为什么不方便封装一个函数使用呢。这个函数传参有通讯录结构体的地址和需要找到的姓名,如果没有找到我们就返回-1,如果找到的话我们就返回其下标也就是i,姓名是字符串,字符串之间的比较我们可以用到strcmp函数来执行。
void DelContact(Conatct* pc)
{
int i = 0;
char name[NA_MAX] = { 0 };
printf("请输入名字:\n");
scanf("%s", name);
int pos = SerachName(pc,name);
if (pos == -1)
{
printf("没有可删除的数据\n");
return;
}
else
{
for (i = pos; i < pc->size - 1; i++)
{
pc->data[i] = pc->data[i + 1];
}
}
pc->size--;
printf("删除成功\n");
}
实现通讯录的删除操作,首先我们需要找到需要我们删除的人的姓名,调用上面封装好的寻找姓名的代码即可,找到之后就需要进行删除操作,我们选择的方式是用后面的代码对删除的代码进行覆盖,使用循环从而实现删除操作,由于我们是将i+1的覆盖到i,所以小于size-1,因为如果小于size的情况下会造成越界的错误。
void SerachContact(const Conatct* pc)
{
char name[NA_MAX] = { 0 };
printf("请输入名字:\n");
scanf("%s", name);
int pos = SerachName(pc,name);
if (pos == -1)
{
printf("没有找到数据\n");
return;
}
else
{
printf("寻找成功\n");
printf("%-20s\t%-4d\t%-5s\t%-20s\t%-12s\n", pc->data[pos].name,
pc->data[pos].age,
pc->data[pos].sex,
pc->data[pos].addr,
pc->data[pos].tel);
}
}
实现通讯录的查找操作,同样调用上面封装好的寻找姓名的代码,找到知道将其打印出来即可。
void ModiftyContact(Conatct* pc)
{
char name[NA_MAX] = { 0 };
printf("请输入要修改的名字:\n");
scanf("%s", name);
int pos = SerachName(pc, name);
if (pos == -1)
{
printf("没有找到数据\n");
return;
}
else
{
printf("请输入姓名:\n");
scanf("%s", pc->data[pos].name);
printf("请输入年龄:\n");
scanf("%d", &pc->data[pos].age);
printf("请输入性别:\n");
scanf("%s", pc->data[pos].sex);
printf("请输入住址:\n");
scanf("%s", pc->data[pos].addr);
printf("请输入电话:\n");
scanf("%s", pc->data[pos].tel);
printf("修改成功\n");
}
}
实现通讯录的修改操作,同样调用上面封装好的寻找姓名的代码,很明显这样的分装使我们的代码更加具有逻辑性。找到之后通过pos直接将其修改即可。
void SortContact(Conatct* pc)
{
int i = 0;
PeoInfo tmp;
for (i = 0; i < pc->size-1; i++)
{
int j = 0;
for (j = 0; j < pc->size - i - 1; j++)
{
if (strcmp(pc->data[j].name,pc->data[j+1].name)>0)
{
tmp = pc->data[j];
pc->data[j] = pc->data[j + 1];
pc->data[j + 1] = tmp;
}
}
}
printf("排序成功\n");
}
排序的实现我使用了冒泡排序的方法,使用了临时变量,通过strcmp来进行比较名字的大小从而进行交换。
void ShowContact(const Conatct* pc)
{
printf("%-20s\t%-4s\t%-5s\t%-20s\t%-12s\n","姓名","年龄","性别","住址","电话");
int i = 0;
for (i = 0; i < pc->size; i++)
{
printf("%-20s\t%-4d\t%-5s\t%-20s\t%-12s\n", pc->data[i].name,
pc->data[i].age,
pc->data[i].sex,
pc->data[i].addr,
pc->data[i].tel);
}
}
最后是对通讯录展示也就是打印操作,通过循环遍历从而打印出所以的数据。而%后面的负数是为了使其对齐美观。
结语
静态通讯的实现并不是十分的复杂,只要学会对每一个功能的实现,相信你也可以成功。