通讯录(C语言版)

用c语言实现一个通讯录

功能:.添加、删除、查找、更改、显示、排序联系人

内存存储方式:结构体数组

1.打印菜单,各个功能分别用函数实现,将函数声明放在头文件中。

2.定义联系人信息,将联系人信息与count(用来记录当前通讯录人数),capacity(记录最大容量)。一起定义到结构体中,完成联系人的创建:

//定义联系人
typedef struct PenInfo {
	char name[20];
	int age;
	char sex[10];
	char tele[12];
	char addr[30];
}PenInfo;

typedef struct Contact {
	PenInfo* data;
	int count;
	int capacity;//设置我通讯录的最大容量
}Contact;

3.创建联系人,并用malloc或calloc函数向内存堆区开辟内存,在退出时记得释放内存,将count初始化为0

int Initcontact(Contact* pc) {
	assert(pc);
	pc->data =(PenInfo*) calloc(3,3 * sizeof(PenInfo));//为data开辟三个空间
	if (pc->data == NULL) {
		printf("%s", strerror(errno));
		return 1;
	}
	pc->count = 0;
	pc->capacity = 3;//设置最大容量为3

	//从文件中读取联系人内容
	LoadContact(pc);
	return 0;
}

4.添加联系人,当联系人容量达到最大容量时,增容,然后进行联系人的信息输入:

void AddCapacity(Contact *pc) {
	assert(pc);
	if (pc->count == pc->capacity) {
		pc->capacity +=2;
		//printf("增容成功\n");
	}
	return;
}

void Addcontact(Contact* pc){
	assert(pc);
	//增容
	AddCapacity(pc);
	//添加联系人
	printf("请输入联系人名字:>");
	scanf("%s", pc->data[pc->count].name);
	printf("请输入联系人年龄:>");
	scanf("%d", &(pc->data[pc->count].age));
	printf("请输入联系人性别:>");
	scanf("%s", pc->data[pc->count].sex);
	printf("请输入联系人电话:>");
	scanf("%s", pc->data[pc->count].tele);
	printf("请输入联系人地址:>");
	scanf("%s", pc->data[pc->count].addr);

	pc->count++;

	printf("添加成功\n");
}

5. 显示联系人(记得格式化)通过for循环标准输出:

void Showcontact(const Contact* pc) {
	assert(pc);
	if (pc->count == 0) {
		printf("还没添加联系人\n");
		return;
	}
	printf("%-20s\t%-3s\t%-10s\t%-12s\t%-30s\n", "名字", "年龄", "性别", "电话", "地址");
	printf("-----------------------------------------------------------------------------\n");
	for (int i = 0; i < pc->count; i++) {
		
		printf("%-20s\t%-5d\t%-10s\t%-12s\t%-30s", pc->data[i].name,
			pc->data[i].age,
			pc->data[i].sex,
			pc->data[i].tele,
			pc->data[i].addr);
		printf("\n");
		printf("-----------------------------------------------------------------------------\n");
	}
}

6.当查找、删除、更改时都需要进行查找,所以直接封装一个查找函数(找到了返回下标)

//查找联系人
static int Findcontact(Contact* pc, char* name) {
	assert(pc);
	for (int i = 0; i < pc->count; i++) {
		if (strcmp(name, pc->data[i].name) == 0) {
			return i;
		}
	}
	return -1;
}

7.查找联系人

void Searchcontact(Contact* pc) {
	assert(pc);
	char name[20] = { 0 };
	printf("请输入要查找的联系人名字:>");
	scanf("%s", name);
	//查找
	int pos = Findcontact(pc, name);
	//删除
	if (pos == -1) {
		printf("没有该联系人\n");
		return;
	}
	else {
		printf("找到了\n");
		printf("%-20s\t%-3s\t%-10s\t%-12s\t%-30s\n", "名字", "年龄", "性别", "电话", "地址");
		printf("-----------------------------------------------------------------------------\n");

		printf("%-20s\t%-5d\t%-10s\t%-12s\t%-30s", pc->data[pos].name,
			pc->data[pos].age,
			pc->data[pos].sex,
			pc->data[pos].tele,
			pc->data[pos].addr);
		printf("\n");
		printf("-----------------------------------------------------------------------------\n");
	}

}

 8.删除联系人,删除后,由于是顺序表存储,将后面的数据向前一个结点覆盖,且count--

void Delcontact(Contact* pc) {
	assert(pc);
	char name[20] = { 0 };
	printf("请输入要删除的联系人名字:>");
	scanf("%s", name);
	//查找
	int pos = Findcontact(pc, name);
	//删除
	if (pos == -1) {
		printf("没有该联系人\n");
		return;
	}
	for (int i = pos; i < pc->count + 1; i++) {//count+1防止溢出
		pc->data[i] = pc->data[i + 1];
	}
	pc->count--;
	printf("删除成功\n");

}

9.修改联系人,将信息覆盖即可:

void Modifycontact(Contact* pc) {
	assert(pc);
	char name[20] = { 0 };
	printf("请输入要修改的联系人的名字:>");
	scanf("%s", name);
	//查找
	int pos = Findcontact(pc, name);
	//删除
	if (pos == -1) {
		printf("没有该联系人\n");
		return;
	}else {
		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].addr);
		printf("\n");
		printf("修改成功\n");
		}
}

10.排序,分为年龄和姓名,都用库函数qsort(默认升序)实现,年龄进行时稍微复杂,细节如下:

//按姓名排序函数
int Sort_by_name(const void* e1, const void* e2) {
	return strcmp(((PenInfo*)e1)->name, ((PenInfo*)e2)->name);
}
//按年龄排序
int Sort_by_age(const void* e1, const void* e2) {
	if (((PenInfo*)e1)->age < ((PenInfo*)e2)->age) {
		return -1;
	}
	if (((PenInfo*)e1)->age > ((PenInfo*)e2)->age) {
		return 1;
	}
	if (((PenInfo*)e1)->age == ((PenInfo*)e2)->age) {
		return 0;
	}
}

void Sortcontact(Contact* pc) {
	assert(pc);
	int chiose;
	printf("(1.按姓名排序 2.按年龄排序):>");
	scanf("%d", &chiose);
	if (chiose == 1) {
		qsort(pc->data,pc->count,sizeof(PenInfo), Sort_by_name);
		printf("排序成功\n");
	}
	else if (chiose == 2) {
		qsort(pc->data, pc->count, sizeof(PenInfo), Sort_by_age);
		printf("排序成功\n");
	}
	else {
		printf("无效输入\n");
		return;
	}
}

11.保存联系人到相对路径“contact.txt”中,通过二进制进行输入输出,退出时保存,打开时读取。

void SaveContact(Contact* pc) {
	FILE* pfWrite = fopen("contact.txt", "wb");
	if (pfWrite == NULL) {
		perror("SaveContact");
		return;
	}
	//用二进制的形式写入文件
	for (int i = 0; i <= pc->count; i++) {
		fwrite(pc->data+i, sizeof(PenInfo), 1, pfWrite);
	}
	//关闭文件
	fclose(pfWrite);
	pfWrite = NULL;
}

void LoadContact(Contact* pc) {
	assert(pc);
	FILE* pfRead = fopen("contact.txt", "rb");
	if (pfRead == NULL) {
		//perror("LoadContact");
		return;
	}
	while (fread(&(pc->data[pc->count]), sizeof(PenInfo), 1, pfRead) == 1) {
		//判断是否空间不足
		AddCapacity(pc);
		pc->count++;
	}
	fclose(pfRead);
	pfRead = NULL;
}

12.测试代码:

#define _CRT_SECURE_NO_WARNINGS

#include "contact.h"

//创建菜单
void menu() {
	printf("------------My ContactBook------------\n");
	printf("-----------1.Add linkman  ------------\n");
	printf("-----------2.Del linkman  ------------\n");
	printf("-----------3.Show linkman ------------\n");
	printf("-----------4.Search linkman ----------\n");
	printf("-----------5.Modify linkman ----------\n");
	printf("-----------6.Sort linkman -----------\n");
	printf("-----------0.Exit menu  -------------\n");

}
int main() {    
	int input = 0;
	//创建联系人
	Contact con;
	//初始化通讯录
	Initcontact(&con);
	do {
		menu();
		printf("请选择对应功能的编号:>");
		scanf("%d", &input);
		switch (input) {
		case 1:         
			Addcontact(&con);
			break;
		case 2:
			Delcontact(&con);
			break;
		case 3:
			Showcontact(&con);
			break;
		case 4:
			Searchcontact(&con);
			break;
		case 5:
			Modifycontact(&con);
			break;
		case 6:
			Sortcontact(&con);
			break;
		case 0:
			SaveContact(&con);
			DestoryContact(&con);
			printf("退出通讯录\n");
			break;
		default :
			printf("选择错误\n");
			break;
		}
	} while (input);
	return 0;
}

测试结果:

通讯录(C语言版)_第1张图片通讯录(C语言版)_第2张图片

你可能感兴趣的:(C语言,c语言,开发语言)