C语言实现通讯录

咱们手机上面还有教务系统上都可以存储信息,这些都是使用编程语言来实现的,那么今天,咱们今天就用C语言来实现通讯录。

一. 实验名称

通讯录

二. 实验目标

1.数据的储存

2.数据的增加

3.数据的删除

4.数据的修改

5.数据的展示

6.数据的保存

7.数据的排序

三. 实现的方法

首先,咱们需要一个头文件用来包括数据类型的定义,函数声明,以及所需要使用函数的头文件,然后还需要一个.c文件用来存放所有函数的定义,不然使得主函数所在的.c文件过于冗杂。

test.c(即主函数所在的文件)

#include "test.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");
}

enum option
{
	EXIT,//0
	ADD,//1
	DEL,//2
	SEARCH,
	MODIFY,
	SHOW,
	SORT
};


int main()
{
	int input = 0;
	//创建通讯录并将其初始化
	Contact con;//创建
	Init_Contact(&con);//将通讯录初始化

	do
	{
		menu();
		printf("请输入那要选择的操作:");
		scanf("%d", &input);
		switch (input)
		{
		case ADD:
			Add_Contact(&con);
			break;
		case DEL:
			Del_Contact(&con);
			break;
		case SEARCH:
			Search_Contact(&con);
			break;
		case MODIFY:
			Modify_Contact(&con);
			break;
		case SHOW:
			Show_Contact(&con);
			break;
		case SORT:
			Sort_Contact(&con);
			break;
		case EXIT:
			Save_Contact(&con);
			Destroy_Contact(&con);
			printf("退出通讯录!\n");
			break;
		default:
			printf("输入错误,请重新选择!\n");
			break;
		}
	} while (input);
	return 0;
}

为什么上面采用了枚举类型(后续博客会讲到的),因为第一个枚举数默认为0,后面每一个元素都是往后加一,这个Contact con是一个结构体类型(后续博客会讲到的)我们会在头文件中定义。


test.h(即对于函数的声明,结构体定义)

#define _CRT_SECURE_NO_WARNINGS 1
#include <string.h>
#include <stdlib.h>
#include <assert.h>
#include <stdio.h>
#pragma once
#define NAME_MAX 20
#define SEX_MAX 5
#define TELE_MAX 11
#define NUMBER_MAX 8
#define SZ 3
#define ADD_SZ 2

//定义一个结构体类型,存放通讯录人物的基本信息
typedef struct PeoInfo
{
	char name[NAME_MAX];
	int age;
	char sex[SEX_MAX];
	char tele[TELE_MAX];
	char number[NUMBER_MAX];
}PeoInfo;

//定义一个结构体类型,存放通讯录的信息
typedef struct Contact
{
	PeoInfo* data;//结构体类型,用于存储通讯录人物信息
	int sz;//当前已经存放的信息的个数
	int capacity;//内存空间大小
}Contact;

//函数声明(初始化通讯录)
void Init_Contact(Contact* pc);

//函数声明(增加通讯录信息)
void Add_Contact(Contact* pc);

//函数声明(删除通讯录信息)
void Del_Contact(Contact* pc);

//函数声明(查找通讯录信息)
void Search_Contact(const Contact* pc);

//函数声明(更改通讯录信息)
void Modify_Contact(Contact* pc);

//函数声明(展示通讯录信息)
void Show_Contact(Contact* pc);

//函数声明(排序通讯录)
void Sort_Contact(Contact* pc);

//函数声明(存储通讯录)
void Save_Contact(Contact* pc);

//函数声明(销毁通讯录)
void Destroy_Contact(Contact* pc);

//函数声明(加载通讯录)
void Load_Contact(Contact* pc);

这里的结构体类型后续博客会详细的讲解。


contact.h(函数定义)

#include "test.h"
//信息初始化
void Init_Contact(Contact* pc)
{
	assert(pc);
	pc->sz = 0;
	PeoInfo* ptr = (PeoInfo*)calloc(SZ, sizeof(PeoInfo));
	if (ptr == NULL)
	{
		perror("Init_Contact::calloc");
		return;
	}
	pc->data = ptr;
	pc->capacity = SZ;

	//加载文件到通讯录
	Load_Contact(pc);
}
//检查容量
void Check_Capacity(Contact* pc)
{
	if (pc->capacity == pc->sz)//此时容量与已存入数据相同,这时需要增容
	{
		PeoInfo* ptr = realloc(pc->data, ((pc->capacity) + ADD_SZ) * sizeof(PeoInfo));
		if (ptr == NULL)
		{
			perror("Check_Capacity;;realloc");
			return;
		}
		pc->data = ptr;
		pc->capacity += ADD_SZ;
		printf("增容成功!\n");
	}
}
//增加信息
void Add_Contact(Contact* pc)
{
	assert(pc);
	//检查是否容量已满,已满则选择扩容
	Check_Capacity(pc);

	//增加一个新的信息
	printf("请输入名字:");
	scanf("%s", pc->data[pc->sz].name);
	printf("请输入年龄:");
	scanf("%d", &pc->data[pc->sz].age);
	printf("请输入性别:");
	scanf("%s", pc->data[pc->sz].sex);
	printf("请输入电话:");
	scanf("%s", pc->data[pc->sz].tele);
	printf("请输入学号:");
	scanf("%s", pc->data[pc->sz].number);

	//信息个数加一
	pc->sz++;
}
//查找删除人姓名
int Find_Name(Contact* pc, char name[])
{
	assert(pc);
	
	int i = 0;
	for (i = 0; i < pc->sz; i++)
	{
		if (strcmp(pc->data[i].name, name[i]) == 0)
		{
			return i;
		}
	}
	return -1;
}
//删除信息
void Del_Contact(Contact* pc)
{
	assert(pc);
	char name[NAME_MAX] = { 0 };
	if (pc->sz == 0)
	{
		printf("通讯录为空,无法删除!\n");
		return;
	}
	//删除
	printf("请输入你要删除人的姓名:");
	scanf("%s", name);
	int ret = Find_Name(pc,name);
	if (-1 == ret)
	{
		printf("你要删除的人不存在!\n");
		return;
	}
	int i = 0;
	for (i = ret; i < pc->sz-1; i++)
	{
		pc->data[i] = pc->data[i + 1];
	}
	pc->sz--;
	printf("删除成功!\n");
}
//查找信息
void Search_Contact(const Contact* pc)
{
	assert(pc);
	char name[NAME_MAX] = { 0 };
	printf("请输入你查找人的姓名:");
	scanf("%s",name);
	int tmp = Find_Name(pc,name);
	if (-1 == tmp)
	{
		printf("你要查找的人不存在!\n");
		return;
	}

	printf("%-20s\t%-4s\t%-5s\t%-11s\t%-8s\n", "名字", "年龄", "性别", "电话", "学号");
	printf("%-20s\t%-4d\t%-5s\t%-11s\t%-8s\n", pc->data [tmp].name ,
		pc->data[tmp].age,
		pc->data[tmp].sex, 
		pc->data[tmp].tele, 
		pc->data[tmp].number);
}
//更改信息
void Modify_Contact(Contact* pc)
{
	assert(pc);
	char name[NAME_MAX] = { 0 };
	printf("请输入你更改人的姓名:");
	scanf("%s", name);
	int pos = Find_Name(pc, name);
	if (-1 == pos)
	{
		printf("你要更改的人不存在!\n");
		return;
	}
	//更改
	printf("请输入更改的名字:");
	scanf("%s", pc->data[pos].name);
	printf("请输入更改的年龄:");
	scanf("%d", &pc->data[pos].age);
	printf("请输入更改的性别:");
	scanf("%s", pc->data[pos].sex);
	printf("请输入更改的电话:");
	scanf("%s", pc->data[pos].tele);
	printf("请输入更改的学号:");
	scanf("%s", pc->data[pos].number);
	printf("修改完成!\n");
}
//展示信息
void Show_Contact(Contact* pc)
{
	assert(pc);
	int i = 0;
	printf("%-20s\t%-4s\t%-5s\t%-11s\t%-8s\n", "名字", "年龄", "性别", "电话", "学号");
	printf("%-20s\t%-4d\t%-5s\t%-11s\t%-8s\n", pc->data[i].name,
		pc->data[i].age,
		pc->data[i].sex,
		pc->data[i].tele,
		pc->data[i].number);
}
//比较名字大小
int cmp_name(const void* n1, const void* n2)
{
	return (strcmp(((PeoInfo*)n1)->name, ((PeoInfo*)n2)->name));
}
//排序通讯录
void Sort_Contact(Contact* pc)
{
	assert(pc);
	qsort(pc->data, pc->sz, sizeof(PeoInfo), cmp_name);
	printf("排序完成!\n");
}
//储存数据
void Save_Contact(Contact* pc)
{
	FILE* pf = fopen("contact.txt", "wb");
	if (NULL == pf)
	{
		perror("Save_Contact");
	}
	else
	{
		int i = 0;
		for (i = 0; i < pc->sz; i++)
		{
			fwrite(pc->data + i, sizeof(PeoInfo), 1, pf);
		}
	}
	fclose(pf);
	pf = NULL;
	printf("保存成功!\n");
}
//
void Load_Contact(Contact* pc)
{
	FILE* pf = fopen("contact.txt", "rb");
	if (pf == NULL)
	{
		perror("Load_Contact");
	}
	else
	{
		PeoInfo tmp = { 0 };
		int i = 0;
		while (fread(&tmp, sizeof(PeoInfo), 1, pf))
		{
			Check_Capacity(pc);
			pc->data[i] = tmp;
			pc->sz++;
			i++;
		}
		fclose(pf);
		pf = NULL;
	}	
}
//销毁信息
void Destroy_Contact(Contact* pc)
{
	free(pc->data);
	pc->data = NULL;
	pc->sz = 0;
	pc->capacity = 0;
	pc = NULL;
}

这段代码很长,接下来我们将一一介绍:

assert函数,就是断言,用于判断传入指针是否为空指针,

calloc函数,为创建空间的函数,并会初始化,与melloc还是有略微差异的,

perror函数,查看函数错误的原因并打印出错误信息,

realloc函数,在原有空间上增加空间,

FILE文档类型,

fopen,以某种方式打开文档,

fclose,关闭文档,并且需要将其置位空指针,

free,释放空间函数创建的空间,也需要将其置位空,

这些就是我们所使用的数组,下面就要介绍我们是如何实现的了。

根据主函数我们所需要的功能有增加,删除,展示,排序,查找,展示,保存退出,首先我们需要一个通讯录,一个通讯录需要数据(data),容量(capacity)还有大小(size),并且需要将其初始化,当容量满了之后就需要扩容,增加就只需要让数据的容量内存都变大一个相应的值,非常容易实现,删除,更改和查找都需要先找到所需要元素的名字,找到直接删除,更改即可,展示通讯录使用遍历即可,排序我们则采用qsort快排来实现,最后存储文件我们在后续博客中会讲到,这就是通讯录的全部思路。

  • 3
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 3
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

Vex小摆子

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

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

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

打赏作者

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

抵扣说明:

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

余额充值