本篇文章主要是实现一个简易的通讯录:
功能如下:
- 添加用户
- 修改用户
- 删除用户
- 查找用户(可重名)
- 按名字或年龄排序
- 显示用户
- 保存通讯录
- 日志追加
有如下知识点:
- 动态数组
- 结构体
- 枚举
- 自定义标识符和宏
- 文件打开与存储
- 函数
- 指针
- 循环
- 排序
简述特点:
- 将人员信息放在一个PeoInf的结构体中,再创建一个结构体List,用于存放peoinf这个结构体的指针,和容量与目前通讯录人员数量。
- 再用realloc动态开辟以结构体peoinf为大小的内存,用于实现动态内存开辟。
- 程序运行后,初始化这段空间,并查询是否有“contact.txt”的文件存在,如果存在,则读取文件里的内容,并放到peoinf的结构体“数组”中,并实时监控是否需要扩容。如果不存在就创建文件。
- 随后就可以添加、修改、查找、删除用户,每一次增删改查都会被记录到一个“contact_log.txt”的文件里,这里使用了时间戳。
- 用qsort进行名字或年龄进行排序
- 程序会知道本次是否进行修改,如果修改后就退出会提示是否需要保存,当然也可以自己手动保存。
- 程序以“rb”和“wb”进行文件的读写。
- 程序实现了重名查找,在有重名的情况下会进行选择。
- (代码可直接运行,复制到编译器vs2019即可)
代码部分
-
contact.h
#pragma once #include <stdio.h> #include <string.h> #include <stdlib.h> #include <errno.h> #include <assert.h> #include <time.h> #include <sys/stat.h>#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,//0ADD,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);
-
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; }
-
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; }
希望对大家有帮助!