C语言程序设计—通讯录实现

本篇文章主要是实现一个简易的通讯录:

功能如下:

  1. 添加用户
  2. 修改用户
  3. 删除用户
  4. 查找用户(可重名)
  5. 按名字或年龄排序
  6. 显示用户
  7. 保存通讯录
  8. 日志追加

 有如下知识点:

  1. 动态数组
  2. 结构体
  3. 枚举
  4. 自定义标识符和宏
  5. 文件打开与存储
  6. 函数
  7. 指针
  8. 循环 
  9. 排序

简述特点:

  1. 将人员信息放在一个PeoInf的结构体中,再创建一个结构体List,用于存放peoinf这个结构体的指针,和容量与目前通讯录人员数量。
  2. 再用realloc动态开辟以结构体peoinf为大小的内存,用于实现动态内存开辟。
  3. 程序运行后,初始化这段空间,并查询是否有“contact.txt”的文件存在,如果存在,则读取文件里的内容,并放到peoinf的结构体“数组”中,并实时监控是否需要扩容。如果不存在就创建文件。
  4. 随后就可以添加、修改、查找、删除用户,每一次增删改查都会被记录到一个“contact_log.txt”的文件里,这里使用了时间戳。
  5. 用qsort进行名字或年龄进行排序
  6. 程序会知道本次是否进行修改,如果修改后就退出会提示是否需要保存,当然也可以自己手动保存。
  7. 程序以“rb”和“wb”进行文件的读写。
  8. 程序实现了重名查找,在有重名的情况下会进行选择。
  9. (代码可直接运行,复制到编译器vs2019即可)

代码部分

  1. contact.h

    #pragma once
    #include 
    #include 
    #include 
    #include 
    #include 
    #include 
    #include 
    
    #define MAX_10 10
    #define MAX_20 20
    //#define LOG_PRINT(x) fprintf(pf, "In %s %s ,user %s name calling %s\n",__DATE__,__TIME__,(x),(list->pl+num)->name)
    typedef struct PeoInf
    {
    	char name[MAX_20];
    	int age;
    	char sex[5];
    	char tel[12];
    	char addr[30];
    }PeoInf;
    //定义通讯录结构体,嵌套PeoInf
    typedef struct List
    {
    	//动态内存分配
    	PeoInf* pl;
    	int count;
    	int capacity;//容量
    }List;
    //定义一个枚举变量,用于存储菜单所有选择
    enum select_all
    {
    	EXIT,//0
    	ADD,
    	DEL,
    	SELECT,
    	MODIFY,
    	SORT,
    	SHOW,
    	SAVE
    };
    //菜单函数
    void menu();
    //定义初始化list函数
    void initialise_list(List* list);
    //定义添加信息函数
    void add_peoinf(List* list);
    //定义显示函数
    void show_list(List* list);
    //定义删除函数
    void del_peoinf(List* list);
    //定义通过找名字查找人的函数(已实现重名查找)
    int find_byname(const List* list);
    //定义查找人
    void sele_peoinf(const List* list);
    //定义修改人信息函数
    void modify_peoinf(List* list);
    //定义删除和修改已找到下标的信息函数
    void del_havefond(List* list, int position);
    void modify_havefond(List* list, int position);
    //定义排序函数
    void sort_peoinf(List* list);
    //定义文件保存函数
    void file_save(List* list);
    //定义扩容函数
    void expand_list(List* list);
  2. actualize.c

    #include "contact.h"
    //实现菜单函数
    void menu(){
    	printf("----------------------------------------\n");
    	printf("--------1. add      2. del--------------\n");
    	printf("--------3. select   4. modify-----------\n");
    	printf("--------5. sort     6. show-------------\n");
    	printf("--------------7. save-------------------\n");
    	printf("--------------0. exit-------------------\n");
    	printf("----------------------------------------\n");
    }
    //实现初始化list函数
    void initialise_list(List* list){
    	PeoInf* ptr = (PeoInf*)calloc(3, sizeof(PeoInf));//默认开辟三个人的存储空间
    	if (ptr == NULL) {
    		printf("%s", strerror(errno));
    		return ;
    	}
    	list->pl = ptr;
    	list->count = 0;
    	list->capacity = 3;
    	FILE* pf = NULL;
    	struct stat buffer;//判断文件是否存在
    	if (stat("contact.txt", &buffer) != 0) {//不存在就创建文件
    		pf = fopen("contact.txt", "wb");
    		fclose(pf);
    		pf = NULL;
    		return;
    	}
    	pf = fopen("contact.txt", "rb");
    	if (pf != NULL) {
    		for (int i = 0; fread(list->pl + i, sizeof(PeoInf), 1, pf) != 0; i++) {
    			if (list->count == list->capacity - 1) {
    				expand_list(list);
    			}
    			list->count++;
    		}
    		fclose(pf);
    	}
    	pf = NULL;
    }
    //扩容函数
    void expand_list(List* list) {
    	PeoInf* ptr =(PeoInf*) realloc(list->pl, (list->capacity + 2)*sizeof(PeoInf));//每次增加两个
    	if (ptr == NULL) {
    		printf("%s", strerror(errno));
    		return;
    	}
    	list->pl = ptr;
    	list->capacity += 2;
    }
    //实现添加日志功能
    /*
    * return 0 失败
    * return 1 成功
    */
    int add_log(List* list,char* moving,int num) {
    	//打开文件
    	FILE* pf=NULL;
    	//判断写入模式是否要追加
    	if (list->count == 0) {
    		pf = fopen("contact_log.txt", "w");
    	}
    	else {
    		pf = fopen("contact_log.txt", "a");
    	}
    	//如果打开失败,报错
    	if (pf == NULL) {
    		perror("fopen:");
    		return 0;
    	}
    	//获取时间戳
    	time_t rawtime;
    	struct tm* timeinfo;
    	time(&rawtime);
    	timeinfo = localtime(&rawtime);
    	fprintf(pf, "In %s \tuser %s name calling %s.\n", asctime(timeinfo), moving, (list->pl + num)->name);
    	fclose(pf);
    	pf = NULL;
    	return 1;
    }
    //实现添加信息功能
    void add_peoinf(List* list) {
    	assert(list);//断言
    	//判断是否需要扩容
    	if (list->count == list->capacity) {
    		expand_list(list);//内部函数,不必去头文件里定义
    		printf("Automatic capacity expansion is successful,\n and the current address book capacity is %d\n", list->capacity);
    	}
    	printf("Please enter the name\n->");
    	scanf("%s", (list->pl+list->count)->name);
    	printf("Please enter age\n->");
    	scanf("%d", &(list->pl + list->count)->age);
    	printf("Please enter sex\n->");
    	scanf("%s", (list->pl + list->count)->sex);
    	printf("Please enter the telephone\n->");
    	scanf("%s", (list->pl + list->count)->tel);
    	printf("Please enter the address\n->");
    	scanf("%s", (list->pl + list->count)->addr);
    	//添加日志log功能
    	if (!add_log(list,"add",list->count)) {
    		printf("log fail,please find excause.\n");
    	}
    	list->count++;
    	printf("succeed!\n");
    }
    //实现显示函数
    void show_list(List* list) {
    	assert(list);
    	printf("name\tage\tsex\ttelephone\taddr\n");
    	for (int i = 0; i < (list->count); i++) {
    		printf("%s\t%d\t%s\t%s\t\t%s\n", (list->pl + i)->name,
    			(list->pl + i)->age, (list->pl + i)->sex, (list->pl + i)->tel, (list->pl + i)->addr);
    	}
    }
    //实现通过寻找名字,找到这个人
    //重名默认存放数组为10,如需变大可改为动态扩容实现
    int find_byname(const List* list) {
    	char s_name[MAX_20] = { 0 };
    	int count = 0;
    	int find_result[MAX_10] = { 0 };
    	printf("Please enter the name that you want \n->");
    	scanf("%s", s_name);
    	for (int i = 0; i < list->count; i++) {
    		if (strcmp((list->pl + i)->name, s_name)==0) {
    			//找到了
    			if (count == 0) {
    				printf("Find the information, please confirm\n");
    				printf("number\tname\tage\tsex\ttelephone\taddr\n");
    			}
    			printf("%d\t%s\t%d\t%s\t%s\t\t%s\n", count+1,(list->pl + i)->name,
    				(list->pl + i)->age, (list->pl + i)->sex, (list->pl + i)->tel, (list->pl + i)->addr);
    			find_result[count] = i;//将找到的坐标存入数组中
    			count++;//判断是否有重复
    		}
    	}
    	if (count == 0) {
    		//找不到
    		printf("Check no such person, please confirm after the input!\n");
    		return -1;
    	}
    	else if (count == 1) {
    		return find_result[0];
    	}
    	else {//两个以上
    		int select_num = 0;
    		while (1) {
    			printf("Please select the object serial number that you want to operate on\n->");
    			scanf("%d", &select_num);
    			if (select_num >= 1 && select_num <= count) {//输入正确序号,方可返回
    				return find_result[select_num - 1];
    			}
    			else {
    				printf("error,please reenter\n");
    			}
    		}
    	}
    }
    //实现删除函数
    void del_peoinf(List* list) {
    	assert(list);
    	int del_num = find_byname(list);
    	if (del_num < 0) return;//查找失败
    	for (int i = 0; i < list->count - del_num - 1; i++) {
    		*(list->pl + del_num + i) = *(list->pl + del_num + 1 + i);
    	}
    	list->count--;
    	printf("delet successfully\n");
    	if (!add_log(list, "delet", del_num)) {
    		printf("log fail,please find excause.\n");
    	}
    }
    void del_havefond(List* list,int position) {
    	assert(list);
    	for (int i = 0; i < list->count - position - 1; i++) {
    		*(list->pl + position + i) = *(list->pl + position + 1 + i);
    	}
    	list->count--;
    	printf("delet successfully\n");
    	if (!add_log(list, "delet", position)) {
    		printf("log fail,please find excause.\n");
    	}
    }
    //实现查找信息功能
    void sele_peoinf(const List* list) {
    	assert(list);
    	int find_num = find_byname(list);
    	if (find_num < 0) return;//查找失败
    	printf("The information is as follows\n");
    	printf("name\tage\tsex\ttelephone\taddr\n");
    	printf("%s\t%d\t%s\t%s\t\t%s\n", (list->pl + find_num)->name,
    		(list->pl + find_num)->age, (list->pl + find_num)->sex, (list->pl + find_num)->tel, (list->pl + find_num)->addr);
    	int input_find = 0;
    	do {
    		printf("--------------------------------\n");
    		printf("--------------------------------\n");
    		printf("-----1. del-------2. modif------\n");
    		printf("------------0. exit-------------\n");
    		printf("--------------------------------\n");
    		printf("--------------------------------\n");
    		printf("please enter what you want\n->");
    		scanf("%d", &input_find);
    		if (input_find == 1) {
    			del_havefond(list, find_num);
    			return;
    		}
    		else if (input_find == 2) {
    			modify_havefond(list, find_num);
    			return;
    		}
    		else if (input_find != 0) {
    			printf("Input is wrong, please reagain\n");
    		}
    	} while (input_find);
    
    }
    void modify_havefond(List* list,int position) {
    	assert(list);
    	printf("Please enter the new name\n->");
    	scanf("%s", (list->pl + position)->name);
    	printf("Please enter new age\n->");
    	scanf("%d", &(list->pl + position)->age);
    	printf("Please enter new sex\n->");
    	scanf("%s", (list->pl + position)->sex);
    	printf("Please enter the new telephone\n->");
    	scanf("%s", (list->pl + position)->tel);
    	printf("Please enter the new address\n->");
    	scanf("%s", (list->pl + position)->addr);
    	printf("Modified successfully\n");
    	if (!add_log(list, "modify", position)) {
    		printf("log fail,please find excause.\n");
    	}
    }
    //实现修改信息
    void modify_peoinf(List* list) {
    	assert(list);
    	int mod_num = find_byname(list);
    	if (mod_num < 0) return;//查找失败
    	printf("Please enter the new name\n->");
    	scanf("%s", (list->pl + mod_num)->name);
    	printf("Please enter new age\n->");
    	scanf("%d", &(list->pl + mod_num)->age);
    	printf("Please enter new sex\n->");
    	scanf("%s", (list->pl + mod_num)->sex);
    	printf("Please enter the new telephone\n->");
    	scanf("%s", (list->pl + mod_num)->tel);
    	printf("Please enter the new address\n->");
    	scanf("%s", (list->pl + mod_num)->addr);
    	printf("Modified successfully\n");
    	if (!add_log(list, "modify",mod_num)) {
    		printf("log fail,please find excause.\n");
    	}
    }
    //qsort的比较函数
    int compare_name(const void* e1,const void* e2) {
    	return strcmp(((PeoInf*)e1)->name, ((PeoInf*)e2)->name);
    
    }
    int compare_age(const void* e1, const void* e2) {
    	return ((PeoInf*)e1)->age - ((PeoInf*)e2)->age;
    
    }
    //实现排序函数
    void sort_peoinf(List* list) {
    	int sort_input = 0;
    	do {
    		printf("--------------------------------\n");
    		printf("--------------------------------\n");
    		printf("-----1. name-------2. age------\n");
    		printf("------------0. exit-------------\n");
    		printf("--------------------------------\n");
    		printf("--------------------------------\n");
    		printf("please enter you want sort by\n->");
    		scanf("%d", &sort_input);
    		if (sort_input == 1) {
    			qsort(list->pl, list->count, sizeof(PeoInf), compare_name);
    			printf("sort by name successfully\n");
    			return;
    		}
    		else if (sort_input == 2) {
    			qsort(list->pl, list->count, sizeof(PeoInf), compare_age);
    			printf("sort by age successfully\n");
    			return;
    		}
    	} while (sort_input);
    	
    }
    void file_save(List *list) {
    	FILE* pf = fopen("contact.txt", "wb");//二进制写入
    	if (pf == NULL) {
    		perror("fopen:");
    		return;
    	}
    	//写数据
    	for (int i = 0; i < list->count; i++) {
    		fwrite(list->pl+i, sizeof(PeoInf), 1, pf);
    	}
    	fclose(pf);
    	pf = NULL;
    }
  3. test.c

    #include "contact.h"
    int main()
    {
    	int input = 0;
    	List list;
    	initialise_list(&list);//动态内存开辟,记得用完销毁
    	int modify_num = 0;//修改数量记录
    	do{
    		menu();
    		printf("Please choose!\n->");
    		scanf("%d", &input);
    		switch (input)
    		{
    		case ADD: 
    		{
    			add_peoinf(&list);
    			modify_num++;
    		}break;
    		case DEL:
    		{
    			del_peoinf(&list);
    			modify_num++;
    		}break;
    		case SELECT:
    		{
    			sele_peoinf(&list);
    		}break;
    		case MODIFY:
    		{
    			modify_peoinf(&list);
    			modify_num++;
    		}break;
    		case SORT:
    		{
    			sort_peoinf(&list);
    		}break;
    		case SHOW:
    		{
    			show_list(&list);
    		}break;
    		case SAVE:
    		{
    			file_save(&list);
    			printf("save in file sucessfully\n");
    			modify_num = 0;
    		}break;
    		case EXIT:
    		{
    			if (modify_num != 0) {
    				int save_select = 0;
    				printf("=========1.save   2.no=============\n");
    				printf("The modified data is not saved, whether it needs to be saved\n->");
    				scanf("%d", &save_select);
    				if (save_select == 1) {
    					file_save(&list);
    					printf("save in file sucessfully\n");
    				}
    			}
    			printf("Ok,have a nice day! Bye~");
    		}break;
    		default:
    			printf("Input is wrong,please reagain!\n");
    			break;
    		}
    	} while (input);
    	//销毁动态内存
    	free(list.pl);
    	list.pl = NULL;
    }

希望对大家有帮助!

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