C语言实现的 通讯录管理系统

通讯录(C语言实现)


前言:本文讲解如何用C语言来创建一个通讯录,这是一个小项目,非常适合新手上手,同时也可以提高自己的代码能力,里面用到了 结构体传参枚举常量文件动态内存开辟……等知识,自己写一个通讯录可以帮助大家巩固一下自己的C语言知识。为了详细的讲解通讯录,我写了三个版本。

通讯录1(静态)

写的第一个通讯录只能存定量的联系人,如果存的联系人超过容量,就会数组越界,报错。

(一)构思通讯录的内容

在建立一个通讯录前我们可以设想通讯录可以有那些功能,我们想让这个通讯录存哪些信息。这是由我们程序员自己定的。

我先讲几个功能:(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<stdio.h>
#include<stdlib.h>
#include<string.h>
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(动态)

这个通讯录2就解决了上一个的版本的一个问题,就是内存是动态开辟的,不用直接开辟存1000个联系人的通讯录,我可以开辟存几个联系人的通讯录,如果内存不够了,我们可以阔容,增大通讯录的内存空间。

这次我们完成上一个版本的通讯录功能,再加入一个改变联系人信息的功能。

先给头文件

#pragma once
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#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;
}

总结:这个版本的通讯录,通过创建动态数组的方式来减少内存的浪费,但是还有一个问题没解决,就是无法做到存储联系人,退出程序后联系人的信息没保存。


通讯录3(动态+储存)

如何才可以将通讯录的内容包存呢?我们需要利用文件来储存其信息,那就好办了,只要在程序开头录入文件已经存的联系人信息;在程序结束前,将联系人的信息存入文件中。这样就做到了联系人的存储。

头文件

#pragma once
#include<stdio.h>
#include<string.h>
#include<stdlib.h>
#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)看看文件里面的信息
在这里插入图片描述
这是二进制文件,里面存的是二进制码,我们不太能看懂。


这就是本章内容了,希望大家有所收获!

  • 1
    点赞
  • 12
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

动名词

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值