本文章将带你从0开始,用C语言自己编写出一个具有增删改查功能的通讯录。本文只考虑大部分情况,对于细枝末节的特殊情况,您可以根据自己的需要进行补充,不影响整体功能的实现。
目录
1.用户信息
对于通讯录而言,我们需要知道每个通讯录人员的信息,其中包括但不限于:姓名、性别、年龄、电话号码、地址......,我们就暂且按照上述提到的信息来进行构建。
满足上述储存条件的类型非结构体莫属了,所以我们先构建一个结构体类型,其中包含上述提到的信息。
typedef struct peoinfor
{
char name[10];
int age;
char sex[5];
char pnum[11];
char addr[15];
}peoinfor;//使用typedef将其重命名为peoinfor
当然,通讯录中不可能只储存一个人的信息,那么我们可以创建一个类型为peoinfor(实际上是struct peoinfor)的数组,当然必不可少的就是要记录下来,现在储存了多少个人员的信息,我们当然可以将这两个变量也放入一个结构体中:
typedef struct contact
{
peoinfor num[capacity];//使用define 对 capacity进行定义,数量自行决定,此处容量为100
int size;
}contact;
2.逻辑构建
上文提到,我们使用结构体数组对用户信息进行储存,那么对于一个通讯录来说,我们必须要实现的功能有什么呢?还是老样子,跟数据库类似,必须要实现添加,删除,修改,查找这些功能,我们顺着这个思路,先构建好整体逻辑框架再慢慢填补内容:
#include <stdio.h>
#include "tongxunlu.h"
#include <stdlib.h>
#include <string.h>
#include <windows.h>
void menu()
{
printf("*******************CONTACT***********************\n");
printf("***************1.ADD 2.DEL*******************\n");
printf("***************3.SEARCH 4.MODIFY****************\n");
printf("***************5.SHOW 0.QUIT******************\n");
printf("*************************************************\n");
}
int main()
{
int input = 0;
contact pf = { memset(&pf,0,sizeof(peoinfor)),0 };
contact* p = &pf;
do
{
menu();
again:
scanf("%d", &input);
switch (input)
{
case quit://创建了枚举类型,提高代码的可读性
printf("QUIT THE CONTACT!\n");
system("cls");
break;
case add://添加
ADD(p);
Sleep(1000);
system("cls");
break;
case del://删除
DEL(p);
Sleep(1000);
system("cls");
break;
case search://查找
SEARCH(p);
Sleep(1000);
system("cls");
break;
case modify://修改
MODIFY(p);
Sleep(1000);
system("cls");
break;
case show://显示
SHOW(p);
printf("Please input:");
goto again;//这里使用go to语句是为了交互体验更好,与实现逻辑无关
break;
default:
printf("input illegal! please input again!\n");
break;
}
}while (input);
}
enum fun//枚举类型,不了解枚举类型用法的可以看上篇文章有详解
{
quit,
add,
del,
search,
modify,
show
};
3.功能实现
在实现功能之前,对于结构类型,枚举类型构建以及函数的声明我均放在了tongxunlu.h文件中,需要时直接包含该文件就可以了,如果不知道该怎么操作可以私信我。
3.1添加
接收到结构体变量的地址后,使用-》操作符对结构体进行索引,分别填入信息,代码如下:
void ADD(contact* p)
{
printf("please input the name:\n");
scanf("%s", p->num[p->size].name);//contact pf下对num[size]结构体数组中的name进行输入
//(name是字符数组,所以不用取地址)
printf("please input the age:\n");
scanf("%d", &(p->num[p->size].age));//age是整型变量,要取地址
printf("please input the sex:\n");
scanf("%s", p->num[p->size].sex);
printf("please input the phonenumber:\n");
scanf("%s", p->num[p->size].pnum);
printf("please input the addr:\n");
scanf("%s", p->num[p->size].addr);
p->size++;//添加完后size加1,准备填入下一个成员的信息
printf("SUCCESS!");
}
3.2展示
对通讯录所记录的所有成员采用左对齐的格式进行展示:
void SHOW(contact* p)
{
int i = 0;
printf("%-10s\t%-4s\t%-5s\t%-11s\t%-15s\n", "NAME", "AGE", "SEX", "PHONENUMBER", "ADDRESS");
for (i = 0; i < p->size; i++)
{
printf("%-10s\t%-4d\t%-5s\t%-11s\t%-15s\n", p->num[i].name, p->num[i].age, p->num[i].sex, p->num[i].pnum, p->num[i].addr);
}
}
3.3查找
int Findby_name(char* name,contact* p)
{
int i = 0;
int flag = -1;
for (i = 0; i < p->size; i++)
{
if (strcmp(p->num[i].name, name) == 0)//字符串比较
return i;
}
return flag;
}
int SEARCH(contact* p) //为后续删除,修改做铺垫,所以采用int类型
{
int flag = 0;
printf("please input the name:");
char name[10] = { 0 };
scanf("%s", name);
flag = Findby_name(name, p);//根据返回值来判断是否通讯录中有被查找人
if (flag != -1)
{
printf("%-10s\t%-4s\t%-5s\t%-11s\t%-15s\n", "NAME", "AGE", "SEX", "PHONENUMBER", "ADDRESS");
printf("%-10s\t%-4d\t%-5s\t%-11s\t%-15s\n", p->num[flag].name, p->num[flag].age, p->num[flag].sex, p->num[flag].pnum, p->num[flag].addr);
}
else
printf("This people can not be found in this contact!\n");
return flag;
}
3.4修改
void MODIFY(contact* p)
{
int flag = -1;
flag = SEARCH(p);//调用查找函数,首先看看是否有被查找人
if (flag == -1)
return;
if (flag != -1)
{
printf("please input the name:\n");
scanf("%s", p->num[flag].name);
printf("please input the age:\n");
scanf("%d", &(p->num[flag].age));
printf("please input the sex:\n");
scanf("%s", p->num[flag].sex);
printf("please input the phonenumber:\n");
scanf("%s", p->num[flag].pnum);
printf("please input the addr:\n");
scanf("%s", p->num[flag].addr);
}
printf("SUCCESS!");
}
3.5删除
void DEL(contact* p)
{
int flag = -1;
flag = SEARCH(p);//查找是否被查找人
if (flag == -1)
return;
else
{ //移动到被删除的地址 //选中被删除地址的后一位地址 //见图解
memmove(&(p->num[flag]), &(p->num[flag+1]), (p->size-flag)*sizeof(peoinfor));
//将num[flag]以后的所有有内容的字节整体往前移动一位
p->size--;
printf("SUCCESS!");
}
}