通讯录(C语言实现)
写的第一个通讯录只能存定量的联系人,如果存的联系人超过容量,就会数组越界,报错。
(一)构思通讯录的内容
在建立一个通讯录前我们可以设想通讯录可以有那些功能,我们想让这个通讯录存哪些信息。这是由我们程序员自己定的。
我先讲几个功能:(1)添加联系人(2)删除联系人(3)
查找联系人(4)显示通讯录表(5)退出通讯录
存联系人的信息,我可以存他的姓名,性别,电话。当然还可以存其它信息,但在本例中只存这三个简单的信息。
(二)代码实现
在构思好通讯录的功能后,我们就可以敲代码来实现通讯的功能了。我们需要做完一个功能后就去验证其正确性,不推荐,大家一口气写完,再去调试,这会让调试变得很复杂。
首先,建立存放联系人的结构体。
struct people //一个联系人的信息
{
char name[20];
char sex[10];
char phone[20];
};
struct q1//通讯录
{
int xx;//存进去的联系人个数
struct people arr[1000];//总共可以存1000个联系人
};
然后建立一个框架:
nt main()
{
int input = 0;
struct q1 wx1;//声明了一个通讯录
//初始化
chushihua(&wx1);
do
{
mune();//菜单
scanf("%d", &input);
switch (input)
{
case Add://Add以及下面的是枚举常量,头文件有
add(&wx1);
break;
case Del:
del(&wx1);
break;
case Chaxun:
chaxun(&wx1);
break;
case Show:
show(&wx1);
break;
case Exit:
break;
default:
break;
}
} while (input);
return 0;
}
最后我们去实现通讯录的功能:
//初始化通讯录
void chushihua(struct q1 *py)
{
py->xx = 0;
memset(py->arr, 0, sizeof(py->arr));
}
//添加联系人
void add(struct q1 *py)
{
//添加联系人信息
printf("请输入联系人姓名:");
scanf("%s", py->arr[py->xx].name);
printf("请输入联系人性别:");
scanf("%s", py->arr[py->xx].sex);
printf("请输入联系人电话:");
scanf("%s", py->arr[py->xx].phone);
py->xx++;//有效联系人+1
}
//查询联系人
int chaxun(struct q1 *py)
{
//输入联系人姓名来进行查找
char s[20] = { 0 };
printf("请输入查找联系人的姓名:");
scanf("%s", s);
//遍历通讯录,如果查找成功返回下标
for (int i = 0; i < py->xx; i++)
{
if (strcmp(s,py->arr[i].name) == 0)
{
printf("联系人姓名:%s", py->arr[i].name);
printf("联系人电话:%s", py->arr[i].phone);
return i;
}
}
//查找失败返回 -1
printf("未查找到联系人\n");
return -1;
}
//删除联系人
void del(struct q1 *py)
{
//调用查询函数找到删除人的下标
int a=chaxun(py);
if (a != (-1))
{
//挪动数据,来删除联系人,相当于把它覆盖了
for (int i = a; i < py->xx - 1; i++)
{
py->arr[i] = py->arr[i + 1];
}
py->xx--;//联系人-1
printf("删除成功\n");
return;
}
}
//展示通讯录
void show(struct q1 *py)
{
for (int i = 0; i < py->xx; i++)
{
printf("姓名:%s\n", py->arr[i].name);
printf("性别:%s\n", py->arr[i].sex);
printf("电话:%s\n", py->arr[i].phone);
}
}
源代码:
(1)头文件
#pragma once
#include
#include
#include
struct people
{
char name[20];
char sex[10];
char phone[20];
};
struct q1
{
int xx;
struct people arr[1000];
};
enum gn
{
Exit,
Add,
Del,
Chaxun,
Show,
};
void mune();
void add(struct q1*);
void show(struct q1*);
void chushihua(struct q1*);
int chaxun(struct q1*);
void del(struct q1*);
(2)头文件对应的源文件
#include"txl1.h"
void mune()
{
printf("*********************************\n");
printf("***** 通讯录1 *****\n");
printf("*****1.add 2.del*****\n");
printf("*****3.chaxun 4.show*****\n");
printf("*****0.exit *****\n");
printf("*********************************\n");
}
int chaxun(struct q1 *py)
{
char s[20] = { 0 };
printf("请输入查找联系人的姓名:");
scanf("%s", s);
for (int i = 0; i < py->xx; i++)
{
if (strcmp(s,py->arr[i].name) == 0)
{
printf("联系人姓名:%s", py->arr[i].name);
printf("联系人电话:%s", py->arr[i].phone);
return i;
}
}
printf("未查找到联系人\n");
return -1;
}
void add(struct q1 *py)
{
printf("请输入联系人姓名:");
scanf("%s", py->arr[py->xx].name);
printf("请输入联系人性别:");
scanf("%s", py->arr[py->xx].sex);
printf("请输入联系人电话:");
scanf("%s", py->arr[py->xx].phone);
py->xx++;
}
void show(struct q1 *py)
{
for (int i = 0; i < py->xx; i++)
{
printf("姓名:%s\n", py->arr[i].name);
printf("性别:%s\n", py->arr[i].sex);
printf("电话:%s\n", py->arr[i].phone);
}
}
void chushihua(struct q1 *py)
{
py->xx = 0;
memset(py->arr, 0, sizeof(py->arr));
}
void del(struct q1 *py)
{
int a=chaxun(py);
if (a != (-1))
{
for (int i = a; i < py->xx - 1; i++)
{
py->arr[i] = py->arr[i + 1];
}
py->xx--;
printf("删除成功\n");
return;
}
}
(3)main函数
#include"txl1.h"
int main()
{
int input = 0;
struct q1 wx1;
//初始化
chushihua(&wx1);
do
{
mune();
scanf("%d", &input);
switch (input)
{
case Add:
add(&wx1);
break;
case Del:
del(&wx1);
break;
case Chaxun:
chaxun(&wx1);
break;
case Show:
show(&wx1);
break;
case Exit:
break;
default:
break;
}
} while (input);
return 0;
}
总结:对上面的静态通讯录做一个小结,它的缺陷在于只能存放1000个人的数据,可能会浪费空间,而且非常不好的地方在于,它在程序运行结束后保存的联系人信息就没了,那我还要这个通讯录做甚。但优点就是不用扩容,简单。
这个通讯录2就解决了上一个的版本的一个问题,就是内存是动态开辟的,不用直接开辟存1000个联系人的通讯录,我可以开辟存几个联系人的通讯录,如果内存不够了,我们可以阔容,增大通讯录的内存空间。
这次我们完成上一个版本的通讯录功能,再加入一个改变联系人信息的功能。
先给头文件
#pragma once
#include
#include
#include
#define MAX 3
enum gn//枚举常量
{
EXIT,
ADD,
DEL,
CHAXUN,
SHOW,
CHANGE,
};
struct people//联系人信息
{
char name[10];
char sex[20];
char phone[20];
};
struct qq2//动态通讯录
{
struct people *p;//动态联系人指针
int sz;//存进去的联系人个数
int capcity;//通讯录容量
};
void mune();
void chushihua(struct qq2 *);
void zenrong(struct qq2 *);
void add(struct qq2 *);
int chaxun(struct qq2 *);
void del(struct qq2 *);
void change(struct qq2*);
void show(struct qq2 *);
main函数
#include"txl2.h"
int main()
{
int input = 0;
struct qq2 con;
chushihua(&con);
do
{
mune();
scanf("%d", &input);
switch (input)
{
case ADD:
add(&con);
break;
case DEL:
del(&con);
break;
case CHAXUN:
chaxun(&con);
break;
case SHOW:
show(&con);
break;
case CHANGE:
change(&con);
break;
case EXIT:
break;
}
} while (input);
return 0;
}
功能实现
#include"txl2.h"
void mune()
{
printf("*********************************\n");
printf("**********tongxunlv2*************\n");
printf("********1.add *********2.del*****\n");
printf("********3.chaxun*******4.show****\n");
printf("********5.change*********0.exit**\n");
printf("*********************************\n");
}
//初始化
void chushihua(struct qq2 *py)
{
py->sz = 0;//有效联系人先置成0
py->capcity = MAX;//初始容量为max=3,头文件有
//动态开辟一块空间
py->p = (struct people *)malloc(MAX*sizeof(struct people));
}
//扩容
void zenrong(struct qq2 *py)
{
//先检查是否需要扩容
//如果容量和有效联系人相等,说明空间满了
if (py->capcity == py->sz)
{
//调整通讯录空间
struct people *tmp = (struct people *) realloc(py->p, (py->capcity+2) * sizeof(struct people));
//设一个tmp检查开辟空间是否成功
//如果不为NULL,就说明开辟空间成功
if (tmp != NULL)
{
py->capcity += 5;
py->p = tmp;
}
else
{
//开辟不成功直接结束程序
perror("通讯录内存不足\n");
exit(1);
}
}
else
return;
}
//增加联系人
void add(struct qq2 *py)
{
//先检验是否需要扩容
zenrong(py);
//输入联系人数据
printf("请输入名字:");
scanf("%s",py->p[py->sz].name);
printf("请输入性别: ");
scanf("%s",py->p[py->sz].sex);
printf("请输入电话: ");
scanf("%s",py->p[py->sz].phone);
py->sz++;
printf("增加成功\n");
}
//查找联系人
int chaxun(struct qq2 *py)
{
char s[10] = { 0 };
printf("请输入查找的联系人姓名:");
scanf("%s", s);
//查找成功返回下标
for (int i = 0; i < py->sz; i++)
{
if (strcmp(s,py->p[i].name) == 0)
{
printf("%s\n", py->p[i].name);
printf("%s\n", py->p[i].sex);
printf("%s\n", py->p[i].phone);
return i;
}
}
//查找不成功返回-1
printf("该联系人不存在\n");
return -1;
}
//删除联系人
void del(struct qq2 *py)
{
int set=chaxun(py);
if (set>= 0)
{
for (int i = set; i < py->sz; i++)
{
py->p[i] = py->p[i+1];
}
py->sz--;
printf("联系人已经删除\n");
return;
}
else
{
return;
}
}
//改变联系人
void change(struct qq2 *py)
{
int ret = chaxun(py);
if (ret >= 0)
{
//如果查找成功,就重新输入联系人信息
printf("请输入联系人的新姓名:");
scanf("%s", py->p[ret].name);
printf("请输入联系人的性别:");
scanf("%s", py->p[ret].sex);
printf("请输入联系人的新电话:");
scanf("%s", py->p[ret].phone);
}
return;
}
//展示通讯录信息
void show(struct qq2 *py)
{
for (int i = 0; i < py->sz; i++)
{
printf("%s ", py->p[i].name);
printf("%s ", py->p[i].sex);
printf("%s ", py->p[i].phone);
printf("\n");
}
return;
}
总结:这个版本的通讯录,通过创建动态数组的方式来减少内存的浪费,但是还有一个问题没解决,就是无法做到存储联系人,退出程序后联系人的信息没保存。
如何才可以将通讯录的内容包存呢?我们需要利用文件来储存其信息,那就好办了,只要在程序开头录入文件已经存的联系人信息;在程序结束前,将联系人的信息存入文件中。这样就做到了联系人的存储。
头文件
#pragma once
#include
#include
#include
#define max 3
//功能函数声明
void mune();
void chushihua(struct gg *pc);
void Add(struct gg * pc);
int Search(struct gg * pc);
void Del(struct gg* pc);
void Change(struct gg *pc);
void Show(struct gg * pc);
void Esc(struct gg *pc);
void baocun(struct gg * pc);
void luru(struct gg * pc);
void zenrong(struct gg * pc);
//一个联系人的信息
struct connact
{
char name[20];
char sex[5];
char phone[30];
};
//通讯录声明
struct gg
{
struct connact* data;
int sz;
int capacity;
};
//枚举常量
enum option
{
esc,
add,
del,
change,
show,
search,
};
main函数
#include"gg.h"
int main()
{
//创建了通讯录 con
struct gg con;
int input=0;
chushihua(&con);
//调用录入文件信息函数
luru(&con);
do
{
mune();
scanf("%d", &input);
switch (input)
{
case add:
Add(&con);
break;
case del:
Del(&con);
break;
case change:
Change(&con);
break;
case show:
Show(&con);
break;
case search:
Search(&con);
break;
case esc:
//将联系人保存到文件中
baocun(&con);
Esc(&con);
break;
}
} while (input);
return 0;
}
功能实现
#include"gg.h"4
//打印菜单
void mune()
{
printf("*********************************\n");
printf("*************通讯录**************\n");
printf("*********************************\n");
printf("***请选择:**********************\n");
printf("****1.add ***2.del***3.change **\n");
printf("****4.show ***5.search***********\n");
printf("****0.esc \n");
}
//增容
void zenrong(struct gg* pc)
{
if (pc->sz == pc->capacity)
{
struct connact *str = (struct connact*)realloc(pc->data, (pc->capacity + 2)*sizeof(struct connact));
if (str != NULL)
{
pc->data = str;
pc->capacity += 2;
}
else
{
perror("通讯录内存不足");
exit(1);
}
}
}
//录入文件里的信息
void luru(struct gg* pc)
{
//创建一个文件指针并且打开文件
//二进制只读信息
FILE *str = fopen("connact.txt", "rb");
//判断文件是否打开成功,打开失败str为NULL
if (NULL == str)
{
perror("fopencao");
return;
}
struct connact tmp = { 0 };
//一步步的将文件里的信息存到通讯录中
//fread返回NULL时,循环结束,文件信息全部录完
while (fread(&tmp, sizeof(struct connact), 1, str))
{
zenrong(pc);
pc->data[pc->sz] = tmp;
pc->sz++;
}
}
//初始化
void chushihua(struct gg* pc)
{
pc->sz = 0;
pc->data = (struct connact *)malloc(max*sizeof(struct connact));
pc->capacity = max;
}
//查找联系人
int Search(struct gg * pc)
{
int i = 0;
char na[20] = { 0 };
printf("请输入查找联系人的姓名:");
scanf("%s", na);
for (i = 0; i < pc->sz; i++)
{
if (strcmp(na, pc->data[i].name) == 0)
{
printf("找到此联系人:\n");
printf("姓名:%15s\n", pc->data[i].name);
printf("性别:%15s\n", pc->data[i].sex);
printf("电话:%15s\n", pc->data[i].phone);
return i;
}
}
return -1;
}
//添加联系人
void Add(struct gg* pc)
{
zenrong(pc);
printf("请输入名字:");
scanf("%s", pc->data[pc->sz].name);
printf("请输入性别: ");
scanf("%s", pc->data[pc->sz].sex);
printf("请输入电话: ");
scanf("%s", pc->data[pc->sz].phone);
pc->sz++;
printf("增加成功\n");
}
//删除联系人
void Del(struct gg *pc)
{
int a = Search(pc); int b;
if (a >= 0)
{
//这里增加了一个防止误删的功能
printf("请确认是否删除联系人\n");
printf("删除请选1,取消删除请选0\n");
scanf("%d", &b);
if (b == 1)
{
for (int i = a; i < pc->sz - 1; i++)
{
pc->data[i] = pc->data[i + 1];
}
pc->sz--;
printf("删除成功\n");
}
else
{
return;
}
}
else
{
printf("此联系人不存在\n");
}
}
//改变联系人
void Change(struct gg* pc)
{
struct connact tmp = { 0 };
int a = Search(pc);
if (a >= 0)
{
printf("请修改;\n");
printf("请输入新名字: ");
scanf("%s", tmp.name);
printf("请输入新性别: ");
scanf("%s", tmp.sex);
printf("请输入新电话: ");
scanf("%s", tmp.phone);
pc->data[a] = tmp;
printf("修改成功\n");
}
else
{
printf("此联系人不存在\n");
}
}
//展示通讯录
void Show(struct gg* pc)
{
for (int i = 0; i < pc->sz; i++)
{
printf("%15s %15s %15s\n", pc->data[i].name, pc->data[i].sex, pc->data[i].phone);
}
}
//退出通讯录
void Esc(struct gg*pc)
{
//释放储存联系人的空间
free(pc->data);
//将释放完的指针设为NULL
pc->data = NULL;
//将容量和有效联系人置为0
pc->capacity = 0;
pc->sz = 0;
}
//将联系人信息存到文件中
void baocun(struct gg*pc)
{
//打开文件,只写(二进制写)
FILE *str = fopen("connact.txt", "wb");
//判断是否打开成功
if (str == NULL)
{
perror("fopen");
return;
}
//将已有联系人的信息依次写入文件中
for (int i = 0; i < pc->sz; i++)
{
fwrite(pc->data + i, sizeof(struct connact), 1, str);
}
//关闭文件
fclose(str);
str = NULL;
}
==总结:==这个版本的通讯录就挺好,它可以将联系人的信息储存,并且空间也不浪费。
代码运行如下:
(1)添加联系人并展示
(2)删除联系人并展示
(3)改变联系人信息并展示
(4)查找联系人
(5)退出程序,在打开看看数据是否保存
可以发现数据以及被储存了。
(6)看看文件里面的信息
这是二进制文件,里面存的是二进制码,我们不太能看懂。
这就是本章内容了,希望大家有所收获!