C语言实现通讯录程序

目录

程序效果

主页​

新建​

打印

​搜索

​删除

​修改

​排序

​错误

文件保存

代码实现

头文件

contact.h

源文件

contact.c

test.c

代码详解

test.c

主页&main函数

枚举输入内容

contact.h

库函数头文件

参数定义

枚举类型

结构体

功能函数

主体函数

contact.c

等待回车

初始化

新增联系人

展示通讯录

搜索联系人

删除联系人

修改联系人信息

排序

保存

退出

个人感悟


程序效果

主页d677355204974f0ca8b9eff334d2cb11.png

新建a94c9b68ae4649bab0f6ff609cf5307c.png

打印

72ecdf4cec3e453f944cf5fa84268184.png搜索

76f15b5ad7694581a7bb6e3774468449.png删除

4b730b797134499eacbf38e731ef66bd.png修改

257f46c35033445e86397fdad56ee849.png排序

feab4c3543104f208fc96db343e3f9e8.pngc22a9ec4f52a4d7f9a035e9b592c945d.png错误

487f3c56596a444f9187eeadd93142c7.pngc70951d0ef354357bbccef211cb1db5d.png

文件保存

aa04bcc192e0496185536365cf9db504.png

代码实现

头文件

contact.h

#pragma once

#define _CRT_SECURE_NO_WARNINGS 1  //使scanf()、fscanf()函数适用于VS平台

#define MAX_NAME 20//名字最大长度
#define MAX_TELE_NUM 15//电话号码最大长度
#define MAX_ADDR 30//地址最大长度
#define MAX_SEX 5 //性别字符最大长度

#define DEFAULT_CAP 100 //初始空间分配容量
#define INC_CAP 10 //空间不足时增加的单位容量


#include <stdio.h>
#include <string.h>
#include <Windows.h>
#include <stdlib.h>


enum search_type {
	name = 1,
	tele_num,
	addr
};
//搜索类型

enum modify_type {
	name_m = 1,
	sex_m,
	age_m,
	tele_num_m,
	addr_m
};
//修改类型

enum sort_type {
	name_s = 1,
	age_s,
	tele_num_s,
	addr_s
};
//排序类型


typedef struct PeoInfo {
	char name[MAX_NAME];
	int age;
	char sex[MAX_SEX];
	char tele_num[MAX_TELE_NUM];
	char addr[MAX_ADDR];
}PeoInfo;
//通讯录个人信息

typedef struct Contact {
	PeoInfo* data;//数据总体的指针(数组),可变大小
    size_t size;//当前通讯录长度
    size_t capacity;//当前通讯录容量
}Contact;
//通讯录总体结构


void getchar_clean();//清理缓冲区
void wait_enter();//等待输入回车
void InitContact(    Contact* main_con
);//初始化通讯录

void add(		     Contact* main_con
);//增加联系人

void del(		     Contact* main_con
);//删除联系人
void del_m(		     Contact* main_con, 
				     size_t code_m
);//删除联系人算法

void search(	     const Contact* main_con
);//搜索联系人
int search_m(	     const Contact* main_con, 
				     enum search_type search_t, 
			         const char* content
);//搜索联系人算法

void modify(	     Contact* main_con
);//修改联系人信息
void modify_m(	     Contact* main_con, 
				     enum modify_type modify_t, 
				     const char* content, 
				     size_t i
);//修改联系人信息算法

void sort(		     Contact* main_con
);//排序

void print(		     const Contact* main_con
);//展示通讯录
void print_m(	     const Contact* main_con
);//展示通讯录算法

void exit_m(         Contact* main_con
);//回收动态内存空间,指针赋空值

void SaveContact(    Contact* main_con
);//保存通讯录信息于文件中

/*代码缺陷:无法避免信息(名字、电话号码)重复问题,
且当重复时(名字、电话号码、地址)使用搜索功能只能找到唯一对象*/

源文件

contact.c

#include "contact.h"

void getchar_clean() {
	while (getchar() != '\n');
}

void wait_enter() {
	printf("\n\n点击回车以继续...\n");
	getchar_clean();
	while (getchar() != '\n');//等待回车
	system("cls");
}

void InitContact(Contact* main_con) {
	
	FILE* pfile_info = fopen("coninfo.dat", "r");//打开文件
	
	if (pfile_info == NULL) { //第一次使用程序
		main_con->size = 0;
		main_con->capacity = DEFAULT_CAP;
	}
	else//第n次使用,继承size和capacity数据
		fscanf(pfile_info, "%zd %zd", &(main_con->size), &(main_con->capacity));

	//calloc函数分配动态空间
	PeoInfo* ptr = (PeoInfo*)calloc(main_con->capacity, sizeof(PeoInfo));
	if (ptr != NULL)
		main_con->data = ptr;//分配动态内存空间
	else
		perror("InitContact");//空间不足时报错
	
	if (pfile_info == NULL)
		return;//第一次使用程序,函数直接结束

	FILE* pfile_data = fopen("condata.dat", "r");
	for (size_t i = 0; i < main_con->size; i++)
		fread(main_con->data + i, sizeof(PeoInfo), 1, pfile_data);
	//第n次使用,将data的数据拷贝
}


void add(Contact* main_con) {
	system("cls");

	if (main_con->size == main_con->capacity - 1) {  
        //-1保证有缓冲空间,利于del_m函数稳定实现
	    PeoInfo* ptr = realloc(main_con->data, (main_con->capacity += INC_CAP) * sizeof(PeoInfo));
        //realloc函数调整
	    if (ptr != NULL)
		    main_con->data = ptr;
	    else{ 
		    perror("add"); 
		    printf("\n     _______________________________________\n\n");
		    printf("                    警告\n\n\t通讯录空间不足,无法增加联系人!\n\n");
		    printf("     _______________________________________\n");
		    wait_enter();
		    return;
	    }
    }
    //空间不足时微调


	printf("         新建联系人\n_____________________________\n");

	printf("\n姓名:");
	scanf("%s", main_con->data[main_con->size].name);

	printf("\n年龄:");
	scanf("%d", &(main_con->data[main_con->size].age));

	printf("\n性别:");
	scanf("%s", main_con->data[main_con->size].sex);

	printf("\n电话号码:");
	scanf("%s", main_con->data[main_con->size].tele_num);

	printf("\n地址:");
	scanf("%s", main_con->data[main_con->size].addr);

	main_con->size++;

	printf("\n\n新建联系人成功!\n");

	wait_enter();
}


void del_m(Contact* main_con, size_t code_m) {
	for (size_t i = code_m; i < main_con->size; i++) {
		main_con->data[i] = main_con->data[i + 1];
	}
	main_con->size--;//size数值减一
}

void del(Contact* main_con) {
	system("cls");

	if (main_con->size == 0) {
		printf("     _______________________________________\n\n");
		printf("                    警告\n\n\t通讯录内容空白,无法删除联系人!\n\n");
		printf("     _______________________________________\n");
		wait_enter();
		return;
	}

	printf("         删除联系人\n_____________________________\n");
	printf("请输入要删除联系人的姓名:");

	char search_name[MAX_NAME];
	scanf("%s", search_name);
	int ret = search_m(main_con, name, search_name);

	if (ret == -1) {
		printf("\n\n未查找到指定联系人!\n");
		wait_enter();
		return;
	}
	
	system("cls");
	printf("\n已找到指定联系人\n\n");
	printf("%-20s\t%-5s\t%-5s\t%-20s\t%-30s\n", "姓名", "性别", "年龄", "电话号码", "地址");
	printf("%-20s\t%-5s\t%-5d\t%-20s\t%-30s\n",
		main_con->data[ret].name,
		main_con->data[ret].sex,
		main_con->data[ret].age,
		main_con->data[ret].tele_num,
		main_con->data[ret].addr);
	
	printf("\n请确认是否将其删除(1:确认/2:取消)\n");
	int input;
	scanf("%d", &input);

	if (input == 1) {
		del_m(main_con, ret);
		printf("\n\n删除成功!\n");
	}
	else 
		printf("\n\n已取消删除\n");

	wait_enter();
}


int search_m(const Contact* main_con, enum search_type search_t, const char* content) {
	size_t i = 0;

	switch (search_t) {
	case name:
		for (i = 0; i < main_con->size; i++) {
			if (strcmp(content, main_con->data[i].name) == 0)
				return (int)i;
		}
		return -1;
		break;
	case tele_num:
		for (i = 0; i < main_con->size; i++) {
			if (strcmp(content, main_con->data[i].tele_num) == 0)
				return (int)i;
		}
		return -1;
		break;
	case addr:
		for (i = 0; i < main_con->size; i++) {
			if (strcmp(content, main_con->data[i].addr) == 0) 
				return (int)i;
		}
		return -1;
		break;
	default:
		return -2;
		break;
	}
}

void search(const Contact* main_con) {
	system("cls");
	if (main_con->size == 0) {
		printf("     _______________________________________\n\n");
		printf("                    警告\n\n\t通讯录内容空白,无法搜索联系人!\n\n");
		printf("     _______________________________________\n");
		wait_enter();
		return;
	}
	//空白

	printf("   \t\t\t搜索联系人\n________________________________________________________\n");
	printf("请选择搜索联系人的方式(1:姓名  2:电话号码  3:地址):\n");
	int input;
	scanf("%d", &input);

	if (input != 1 && input != 2 && input != 3) {
		printf("\n\n输入错误\n");
		wait_enter();
		return;
	}
	//输入

	printf("请输入查找内容:");
	char src[MAX_ADDR];
	scanf("%s", src);
	int ret = search_m(main_con, (enum search_type)input, src);

	if (ret == -1) {
		printf("\n\n未查找到指定联系人!\n");
		wait_enter();
		return;
	}

	system("cls");
	printf("\n已找到指定联系人\n\n");
	printf("%-20s\t%-5s\t%-5s\t%-20s\t%-30s\n", "姓名", "性别", "年龄", "电话号码", "地址");
	printf("%-20s\t%-5s\t%-5d\t%-20s\t%-30s\n",
		main_con->data[ret].name,
		main_con->data[ret].sex,
		main_con->data[ret].age,
		main_con->data[ret].tele_num,
		main_con->data[ret].addr);

	wait_enter();
}


void modify_m(Contact* main_con, enum modify_type modify_t, const char* content, size_t i) {
	switch (modify_t) {
	case name_m:
		strcpy(main_con->data[i].name, content);
		break;
	case sex_m:
		strcpy(main_con->data[i].sex, content);
		break;
	case tele_num_m:
		strcpy(main_con->data[i].tele_num, content);
		break;
	case addr_m:
		strcpy(main_con->data[i].addr, content);
		break;
	default:
		break;
	}
}

void modify(Contact* main_con) {
	system("cls");
	if (main_con->size == 0) {
		printf("     _______________________________________\n\n");
		printf("                    警告\n\n\t通讯录内容空白,无法修改联系人信息!\n\n");
		printf("     _______________________________________\n");
		wait_enter();
		return;
	}
	//空白

	printf("         修改联系人信息\n_____________________________\n");
	printf("请输入要修改联系人的电话号码:");
	char search_tele[MAX_TELE_NUM];
	scanf("%s", search_tele);
	int ret = search_m(main_con, tele_num, search_tele);
	//输入

	if (ret == -1) {
		printf("\n\n未查找到指定联系人!\n");
		wait_enter();
		return;
	}

	system("cls");
	printf("\n已找到指定联系人\n\n");
	printf("%-20s\t%-5s\t%-5s\t%-20s\t%-30s\n", "姓名", "性别", "年龄", "电话号码", "地址");
	printf("%-20s\t%-5s\t%-5d\t%-20s\t%-30s\n",
		main_con->data[ret].name,
		main_con->data[ret].sex,
		main_con->data[ret].age,
		main_con->data[ret].tele_num,
		main_con->data[ret].addr);

	printf("\n请输入修改类型(1.姓名  2.性别  3.年龄  4.电话号码  5.地址):\n");
	int input;
	scanf("%d", &input);

	if (input != 1 && input != 2 && input != 3  && input != 4 && input != 5) {
		printf("\n\n输入错误\n");
		wait_enter();
		return;
	}

	(enum modify_type)input;
	if (input == age_m) {
		printf("请输入修改的值:");
		scanf("%d", &(main_con->data[ret].age));
	}
	else {
		printf("请输入修改内容:");
		char src[MAX_ADDR];
		scanf("%s", src);
		modify_m(main_con, input, src, ret);
	}

	system("cls");
	printf("\n修改成功!\n\n");
	printf("%-20s\t%-5s\t%-5s\t%-20s\t%-30s\n", "姓名", "性别", "年龄", "电话号码", "地址");
	printf("%-20s\t%-5s\t%-5d\t%-20s\t%-30s\n",
		main_con->data[ret].name,
		main_con->data[ret].sex,
		main_con->data[ret].age,
		main_con->data[ret].tele_num,
		main_con->data[ret].addr);

	wait_enter();
}


static int sort_by_name(const void* p1, const void* p2) {
	return strcmp(((PeoInfo*)p1)->name, ((PeoInfo*)p2)->name);
}

static int sort_by_age(const void* p1, const void* p2) {
	return ((PeoInfo*)p1)->age - ((PeoInfo*)p2)->age;
}

static int sort_by_tele(const void* p1, const void* p2) {
	return strcmp(((PeoInfo*)p1)->tele_num, ((PeoInfo*)p2)->tele_num);
}

static int sort_by_addr(const void* p1, const void* p2) {
	return strcmp(((PeoInfo*)p1)->addr, ((PeoInfo*)p2)->addr);
}

void sort(Contact* main_con) {
	system("cls");
	if (main_con->size == 0) {
		printf("     _______________________________________\n\n");
		printf("                    警告\n\n\t通讯录内容空白,无法修改联系人信息!\n\n");
		printf("     _______________________________________\n");
		wait_enter();
		return;
	}
	//空白

	printf("\n请输入排序标准(1.姓名  2.年龄  3.电话号码  4.地址):\n");
	int input;
	scanf("%d", &input);

	if (input != 1 && input != 2 && input != 3 && input != 4) {
		printf("\n\n输入错误\n");
		wait_enter();
		return;
	}

	(enum sort_type)input;
	int (*sort_func)(const void* p1, const void* p2) = NULL;//比较函数指针变量

	if (input == name_s)
		sort_func = sort_by_name;
	else if (input == age_s)
		sort_func = sort_by_age;
	else if (input == tele_num_s)
		sort_func = sort_by_tele;
	else if (input == addr_s)
		sort_func = sort_by_addr;

	qsort((void*)main_con->data, main_con->size, sizeof(main_con->data[0]), sort_func);

	system("cls");
	printf("排序成功!\n\n");
	print_m((const Contact*)main_con);

	wait_enter();
}


void print_m(const Contact* main_con) {
	printf("%-20s\t%-5s\t%-5s\t%-20s\t%-30s\n", "姓名", "性别", "年龄", "电话号码", "地址");
	for (size_t i = 0; i < main_con->size; i++) {
		printf("%-20s\t%-5s\t%-5d\t%-20s\t%-30s\n",
			main_con->data[i].name,
			main_con->data[i].sex,
			main_con->data[i].age,
			main_con->data[i].tele_num,
			main_con->data[i].addr);
	}
}

void print(const Contact* main_con) {
	system("cls");
	printf("                               通讯录列表\n\n");
	print_m(main_con);

	wait_enter();
}

void exit_m(Contact* main_con) {
	free(main_con->data);
	main_con->data = NULL;
}

void SaveContact(Contact* main_con) {
	FILE* pfile_data = fopen("condata.dat", "w");
	FILE* pfile_info = fopen("coninfo.dat", "w");//打开文件
	if (pfile_data == NULL) {
		perror("File Open");
		return;
	}
	if (pfile_info == NULL) {
		perror("File Open");
		return;
	}//错误情况

	for (size_t i = 0; i < main_con->size; i++)
		fwrite(main_con->data + i, sizeof(PeoInfo), 1, pfile_data);
	//写data文件
	fprintf(pfile_info, "%zd %zd", main_con->size, main_con->capacity);
	//写info文件

	//关闭文件
	fclose(pfile_data);
	pfile_data = NULL;
	fclose(pfile_info);
	pfile_info = NULL;

	printf("\n\n通讯录保存成功!程序已退出\n");
	wait_enter();
}

test.c

#include "contact.h"

enum choice {
	Exit,
	Add,
	Del,
	Search,
	Modify,
	Sort,
	Print
};
//操作选项

void menu() {
	printf("                   主页                  \n\n");
	printf("          1.新建           2.删除        \n");
	printf("          3.搜索           4.修改        \n");
	printf("          5.排序           6.打印        \n");
	printf("          0.退出                         \n");
	printf("\n请选择:");
}
//菜单主页

int main() {
	Contact con;
	InitContact(&con);
	//初始化通讯录
	int input = 0;
	do {
		menu();
        again:
		scanf("%d", &input);

		switch ((enum choice)input) {
		case Add:
			add(&con);
			break;
		case Del:
			del(&con);
			break;
		case Search:
			search(&con);
			break;
		case Modify:
			modify(&con);
			break;
		case Sort:
			sort(&con);
			break;
		case Print:
			print(&con);
			break;
        case Exit:
            SaveContact(&con);
	        exit_m(&con);
	        break;
		default:
            printf("输入错误,请重新输入:\n");
            goto again;
			break;
		}
	} while (input);
	return 0;
}
//程序入口

代码详解

test.c

主页&main函数

void menu() {
	printf("                   主页                  \n\n");
	printf("          1.新建           2.删除        \n");
	printf("          3.搜索           4.修改        \n");
	printf("          5.排序           6.打印        \n");
	printf("          0.退出                         \n");
	printf("\n请选择:");
}
//菜单主页
int main() {
	Contact con;
	//main函数首先通过通讯录结构体Contact创建con变量,通讯录主体对象

    InitContact(&con);
    //通过该函数对con初始化,第二次使用则导入文件信息

	int input = 0;//接收用户输入内容的变量
	do {
		menu();//菜单主页
        again://输入错误时重新输入

		scanf("%d", &input);//用户输入
        
        //switch判断用户输入内容,调用不同的函数程序
		switch ((enum choice)input) {
		case Add://新建
			add(&con);
			break;
		case Del://删除
			del(&con);
			break;
		case Search://搜索
			search(&con);
			break;
		case Modify://修改
			modify(&con);
			break;
		case Sort://排序
			sort(&con);
			break;
		case Print://展示
			print(&con);
			break;
        case Exit://退出
            SaveContact(&con);//保存
	        exit_m(&con);
	        break;
		default:
            printf("输入错误,请重新输入:\n");
            goto again;//输入错误时重新输入
			break;
		}
	} while (input);//do_while循环保证程序持续运行

	return 0;
}

枚举输入内容

enum choice {
	Exit,
	Add,
	Del,
	Search,
	Modify,
	Sort,
	Print
};
//操作选项

contact.h

库函数头文件

#include <stdio.h>
#include <string.h>
#include <Windows.h>
#include <stdlib.h>

参数定义

#define MAX_NAME 20//名字最大长度
#define MAX_TELE_NUM 15//电话号码最大长度
#define MAX_ADDR 30//地址最大长度
#define MAX_SEX 5 //性别字符最大长度

#define DEFAULT_CAP 100 //初始空间分配容量
#define INC_CAP 10 //空间不足时增加的单位容量

枚举类型

enum search_type {
	name = 1,
	tele_num,
	addr
};
//搜索类型

enum modify_type {
	name_m = 1,
	sex_m,
	age_m,
	tele_num_m,
	addr_m
};
//修改类型

enum sort_type {
	name_s = 1,
	age_s,
	tele_num_s,
	addr_s
};
//排序类型

结构体

typedef struct PeoInfo {
	char name[MAX_NAME];
	int age;
	char sex[MAX_SEX];
	char tele_num[MAX_TELE_NUM];
	char addr[MAX_ADDR];
}PeoInfo;
//通讯录个人信息

typedef struct Contact {
	PeoInfo* data;//数据总体的指针(数组),可变大小
	size_t size;//当前通讯录长度
	size_t capacity;//当前通讯录容量
}Contact;
//通讯录总体结构

功能函数

void getchar_clean();//清理缓冲区
void wait_enter();//等待输入回车
void InitContact(Contact* main_con);//初始化通讯录

主体函数

void add(		    Contact* main_con//通讯录主体
);//增加联系人

void del(		    Contact* main_con
);//删除联系人
void del_m(		    Contact* main_con, 
				    size_t code_m//删除元素下标
);//删除联系人算法

void search(	    const Contact* main_con//const修饰防止通讯录主体被改变
);//搜索联系人
int search_m(	    const Contact* main_con, 
				    enum search_type search_t, //搜索方式
				    const char* content//搜索内容
);//搜索联系人算法

void modify(	    Contact* main_con
);//修改联系人信息
void modify_m(	    Contact* main_con, 
				    enum modify_type modify_t, //修改类型
				    const char* content, //修改内容
				    size_t i//修改元素下标
);//修改联系人信息算法

void sort(		    Contact* main_con
);//排序

void print(		    const Contact* main_con
);//展示通讯录
void print_m(	    const Contact* main_con
);//展示通讯录算法

void exit_m(        Contact* main_con
);//回收动态内存空间,指针赋空值
void SaveContact(    Contact* main_con
);//保存通讯录信息于文件中

contact.c

等待回车

void getchar_clean() {
	while (getchar() != '\n');
}

void wait_enter() {
	printf("\n\n点击回车以继续...\n");
	getchar_clean();//清理缓冲区
	while (getchar() != '\n');//等待回车
	system("cls");//清屏(Windows.h)
}

初始化

void InitContact(Contact* main_con) {
    //“初始化”建议与“保存”结合阅读
	FILE* pfile_info = fopen("coninfo.dat", "r");//打开info文件
	
	if (pfile_info == NULL) { //第一次使用程序
		main_con->size = 0;//初始大小为0
		main_con->capacity = DEFAULT_CAP;//默认容量
	}
	else//第n次使用,继承size和capacity数据
		fscanf(pfile_info, "%zd %zd", &(main_con->size), &(main_con->capacity));
        //%zd读取size_t类型数据
	//calloc函数在堆区分配动态内存空间
	PeoInfo* ptr = (PeoInfo*)calloc(main_con->capacity, sizeof(PeoInfo));
	if (ptr != NULL)
		main_con->data = ptr;//分配动态内存空间
	else
		perror("InitContact");//空间不足时使用perror函数报错
	

	if (pfile_info == NULL)
		return;//第一次使用程序,函数直接结束

	FILE* pfile_data = fopen("condata.dat", "r");//打开data文件
	for (size_t i = 0; i < main_con->size; i++)
		fread(main_con->data + i, sizeof(PeoInfo), 1, pfile_data);
	//第n次使用,将data的数据读取
}

新增联系人

void add(Contact* main_con) {
	system("cls");//清屏

	if (main_con->size == main_con->capacity - 1) {  
        //空间不足情况,-1保证有缓冲空间,利于del_m函数稳定实现
	    PeoInfo* ptr = realloc(main_con->data, (main_con->capacity += INC_CAP) * sizeof(PeoInfo));
        //realloc函数调整空间大小
	    if (ptr != NULL)
		    main_con->data = ptr;
	    else{ 
		    perror("add"); 
		    printf("\n     _______________________________________\n\n");
		    printf("                    警告\n\n\t通讯录空间不足,无法增加联系人!\n\n");
		    printf("     _______________________________________\n");
		    wait_enter();
		    return;
	    }
    }
    //空间不足时微调

	printf("         新建联系人\n_____________________________\n");

	printf("\n姓名:");
	scanf("%s", main_con->data[main_con->size].name);

	printf("\n年龄:");
	scanf("%d", &(main_con->data[main_con->size].age));

	printf("\n性别:");
	scanf("%s", main_con->data[main_con->size].sex);

	printf("\n电话号码:");
	scanf("%s", main_con->data[main_con->size].tele_num);

	printf("\n地址:");
	scanf("%s", main_con->data[main_con->size].addr);
    //输入内容

	main_con->size++;//空间大小+1

	printf("\n\n新建联系人成功!\n");

	wait_enter();
}

展示通讯录

void print_m(const Contact* main_con) {
	printf("%-20s\t%-5s\t%-5s\t%-20s\t%-30s\n", "姓名", "性别", "年龄", "电话号码", "地址");
    //目录栏
	for (size_t i = 0; i < main_con->size; i++) {
		printf("%-20s\t%-5s\t%-5d\t%-20s\t%-30s\n",
			main_con->data[i].name,
			main_con->data[i].sex,
			main_con->data[i].age,
			main_con->data[i].tele_num,
			main_con->data[i].addr);
	}
    //每行打印
}

void print(const Contact* main_con) {
	system("cls");//清屏
	printf("                               通讯录列表\n\n");//标题
	print_m(main_con);

	wait_enter();
}

搜索联系人

//搜索算法实现
int search_m(const Contact* main_con, enum search_type search_t, const char* content) {
	size_t i = 0;//循环变量

	switch (search_t) {
	case name:
		for (i = 0; i < main_con->size; i++) {
			if (strcmp(content, main_con->data[i].name) == 0)//strcmp函数判断字符串是否相同
				return (int)i;
		}
		return -1;
		break;
	case tele_num:
		for (i = 0; i < main_con->size; i++) {
			if (strcmp(content, main_con->data[i].tele_num) == 0)
				return (int)i;
		}
		return -1;
		break;
	case addr:
		for (i = 0; i < main_con->size; i++) {
			if (strcmp(content, main_con->data[i].addr) == 0) 
				return (int)i;
		}
		return -1;
		break;
	default:
		return -2;
		break;
	}
}

void search(const Contact* main_con) {
	system("cls");//清屏

	if (main_con->size == 0) {
		printf("     _______________________________________\n\n");
		printf("                    警告\n\n\t通讯录内容空白,无法搜索联系人!\n\n");
		printf("     _______________________________________\n");
		wait_enter();
		return;
	}
	//空白情况

	printf("   \t\t\t搜索联系人\n________________________________________________________\n");
	printf("请选择搜索联系人的方式(1:姓名  2:电话号码  3:地址):\n");
	int input;
	scanf("%d", &input);

	if (input != 1 && input != 2 && input != 3) {
		printf("\n\n输入错误\n");
		wait_enter();
		return;
	}
	//输入错误情况

	printf("请输入查找内容:");
	char src[MAX_ADDR];//接收用户输入内容
	scanf("%s", src);
	int ret = search_m(main_con, (enum search_type)input, src);//搜索算法

	if (ret == -1) {
		printf("\n\n未查找到指定联系人!\n");
		wait_enter();
		return;
	}

	system("cls");
	printf("\n已找到指定联系人\n\n");
	printf("%-20s\t%-5s\t%-5s\t%-20s\t%-30s\n", "姓名", "性别", "年龄", "电话号码", "地址");
	printf("%-20s\t%-5s\t%-5d\t%-20s\t%-30s\n",
		main_con->data[ret].name,
		main_con->data[ret].sex,
		main_con->data[ret].age,
		main_con->data[ret].tele_num,
		main_con->data[ret].addr);
    //打印对应信息
	wait_enter();
}

删除联系人

//删除算法
void del_m(Contact* main_con, size_t code_m) {    //code_m为删除元素下标
	for (size_t i = code_m; i < main_con->size; i++) {
		main_con->data[i] = main_con->data[i + 1];//向前紧排
	}
	main_con->size--;//size数值减一
}

void del(Contact* main_con) {
	system("cls");//清屏

	if (main_con->size == 0) {
		printf("     _______________________________________\n\n");
		printf("                    警告\n\n\t通讯录内容空白,无法删除联系人!\n\n");
		printf("     _______________________________________\n");
		//printf("\n\n点击回车以继续...\n");
		wait_enter();
		return;
	}
    //空白情况

	printf("         删除联系人\n_____________________________\n");
	printf("请输入要删除联系人的姓名:");

	char search_name[MAX_NAME];//接收输入内容
	scanf("%s", search_name);
	int ret = search_m(main_con, name, search_name);//调用search_m进行查找

	if (ret == -1) {
		printf("\n\n未查找到指定联系人!\n");
		wait_enter();
		return;
	}
	
	system("cls");
	printf("\n已找到指定联系人\n\n");
	printf("%-20s\t%-5s\t%-5s\t%-20s\t%-30s\n", "姓名", "性别", "年龄", "电话号码", "地址");
	printf("%-20s\t%-5s\t%-5d\t%-20s\t%-30s\n",
		main_con->data[ret].name,
		main_con->data[ret].sex,
		main_con->data[ret].age,
		main_con->data[ret].tele_num,
		main_con->data[ret].addr);
    //打印信息	

	printf("\n请确认是否将其删除(1:确认/2:取消)\n");
	int input;
	scanf("%d", &input);
    //确认过程

	if (input == 1) {
		del_m(main_con, ret);//删除算法实现
		printf("\n\n删除成功!\n");
	}
	else 
		printf("\n\n已取消删除\n");

	wait_enter();
}

修改联系人信息

//修改算法
void modify_m(Contact* main_con, enum modify_type modify_t, const char* content, size_t i) {
	switch (modify_t) {
	case name_m:
		strcpy(main_con->data[i].name, content);//使用strcpy函数对字符串修改
		break;
	case sex_m:
		strcpy(main_con->data[i].sex, content);
		break;
	case tele_num_m:
		strcpy(main_con->data[i].tele_num, content);
		break;
	case addr_m:
		strcpy(main_con->data[i].addr, content);
		break;
	default:
		break;
	}
}

void modify(Contact* main_con) {
	system("cls");//清屏
	if (main_con->size == 0) {
		printf("     _______________________________________\n\n");
		printf("                    警告\n\n\t通讯录内容空白,无法修改联系人信息!\n\n");
		printf("     _______________________________________\n");
		wait_enter();
		return;
	}
	//空白情况

	printf("         修改联系人信息\n_____________________________\n");
	printf("请输入要修改联系人的电话号码:");
	char search_tele[MAX_TELE_NUM];
	scanf("%s", search_tele);
	int ret = search_m(main_con, tele_num, search_tele);
	//接收用户输入

	if (ret == -1) {
		printf("\n\n未查找到指定联系人!\n");
		wait_enter();
		return;
	}
    //查找失败

	system("cls");
	printf("\n已找到指定联系人\n\n");
	printf("%-20s\t%-5s\t%-5s\t%-20s\t%-30s\n", "姓名", "性别", "年龄", "电话号码", "地址");
	printf("%-20s\t%-5s\t%-5d\t%-20s\t%-30s\n",
		main_con->data[ret].name,
		main_con->data[ret].sex,
		main_con->data[ret].age,
		main_con->data[ret].tele_num,
		main_con->data[ret].addr);
    //打印相关信息

	printf("\n请输入修改类型(1.姓名  2.性别  3.年龄  4.电话号码  5.地址):\n");
	int input;
	scanf("%d", &input);//修改类型

	if (input != 1 && input != 2 && input != 3  && input != 4 && input != 5) {
		printf("\n\n输入错误\n");
		wait_enter();
		return;
	}//输入错误

	(enum modify_type)input;
	if (input == age_m) {
		printf("请输入修改的值:");
		scanf("%d", &(main_con->data[ret].age));//age用scanf函数直接修改
	}
	else {
		printf("请输入修改内容:");
		char src[MAX_ADDR];
		scanf("%s", src);
		modify_m(main_con, input, src, ret);//string类型变量调用修改算法
	}

	system("cls");
	printf("\n修改成功!\n\n");
	printf("%-20s\t%-5s\t%-5s\t%-20s\t%-30s\n", "姓名", "性别", "年龄", "电话号码", "地址");
	printf("%-20s\t%-5s\t%-5d\t%-20s\t%-30s\n",
		main_con->data[ret].name,
		main_con->data[ret].sex,
		main_con->data[ret].age,
		main_con->data[ret].tele_num,
		main_con->data[ret].addr);
    //打印修改结果
	wait_enter();
}

排序

//静态函数,规定不同方式排序的比较标准
//返回值<0为顺序,反之倒序
static int sort_by_name(const void* p1, const void* p2) {
	return strcmp(((PeoInfo*)p1)->name, ((PeoInfo*)p2)->name);//strcmp比较字符串大小
}

static int sort_by_age(const void* p1, const void* p2) {
	return ((PeoInfo*)p1)->age - ((PeoInfo*)p2)->age;
}

static int sort_by_tele(const void* p1, const void* p2) {
	return strcmp(((PeoInfo*)p1)->tele_num, ((PeoInfo*)p2)->tele_num);
}

static int sort_by_addr(const void* p1, const void* p2) {
	return strcmp(((PeoInfo*)p1)->addr, ((PeoInfo*)p2)->addr);
}

void sort(Contact* main_con) {
	system("cls");
	if (main_con->size == 0) {
		printf("     _______________________________________\n\n");
		printf("                    警告\n\n\t通讯录内容空白,无法修改联系人信息!\n\n");
		printf("     _______________________________________\n");
		wait_enter();
		return;
	}
	//空白情况

	printf("\n请输入排序标准(1.姓名  2.年龄  3.电话号码  4.地址):\n");
	int input;
	scanf("%d", &input);

	if (input != 1 && input != 2 && input != 3 && input != 4) {
		printf("\n\n输入错误\n");
		wait_enter();
		return;
	}
    //用户输入
    
	(enum sort_type)input;
	int (*sort_func)(const void* p1, const void* p2) = NULL;//比较函数的指针变量

	if (input == name_s)
		sort_func = sort_by_name;
	else if (input == age_s)
		sort_func = sort_by_age;
	else if (input == tele_num_s)
		sort_func = sort_by_tele;
	else if (input == addr_s)
		sort_func = sort_by_addr;
    //根据用户输入,sort_func储存不同函数的指针

	qsort((void*)main_con->data, main_con->size, sizeof(main_con->data[0]), sort_func);
    //qsort函数(stdilib.h)————快速排序
    //1.参数1(void*)为排序数组首元素地址
    //2.参数2(size_t)为参与排序数组元素的个数
    //3.参数3(size_t)为每个数组元素的字节大小
    //4.参数4( int (*)(const void*, const void*) )实现比较算法的函数的指针

	system("cls");
	printf("排序成功!\n\n");
	print_m((const Contact*)main_con);//打印排序结果

	wait_enter();
}

保存

void SaveContact(Contact* main_con) {
	FILE* pfile_data = fopen("condata.dat", "w");//打开(创建)data文件
	FILE* pfile_info = fopen("coninfo.dat", "w");//打开(创建)info文件
	if (pfile_data == NULL) {
		perror("File Open");
		return;
	}
	if (pfile_info == NULL) {
		perror("File Open");
		return;
	}//错误情况

	
	for (size_t i = 0; i < main_con->size; i++)
		fwrite(main_con->data + i, sizeof(PeoInfo), 1, pfile_data);
	//保存data数据于data文件
	
	fprintf(pfile_info, "%zd %zd", main_con->size, main_con->capacity);
	//保存size和capacity数据于info文件

	fclose(pfile_data);
	pfile_data = NULL;
	fclose(pfile_info);
	pfile_info = NULL;
    //关闭文件

	printf("\n\n通讯录保存成功!程序已退出\n");
	wait_enter();
}

退出

void exit_m(Contact* main_con) {
	free(main_con->data);//释放动态内存空间
	main_con->data = NULL;//防止野指针出现,data赋为空指针
}

个人感悟

本人为C语言新手,在B站自学过程中了解了这个项目,于是想自己尝试实现。该程序至少50%以上的设计思路都是自己独立思考并实现的,所有代码都由自己亲手敲出来。

该程序采取了分模块的方式,由一个头文件和两个源文件组成;且在很多细节上有所处理,比如size_t类型的使用、enum枚举的应用、结构体的运用、const、static等关键字的使用等等;同时程序还采用了堆区动态内存分配的方式,使程序的空间使用更为灵活;以及使用了文件操作,可本地保存用户数据,使程序具有更强的实用性。

该程序涉及较多的指针内容,以及部分文件操作的内容,还使用了较多的库函数,需要读者有较强的C语言基础和一定的综合能力。

代码必然在很多方面存在不足,望谅解;文章内容有任何错误,还望指正。感兴趣的读者也可以自行尝试优化。

Github上也有相应的源码和应用程序:Github源码

感谢你的阅读!

  • 5
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值