本篇文章主要是实现一个简易的通讯录:
功能如下:
- 添加用户
- 修改用户
- 删除用户
- 查找用户(可重名)
- 按名字或年龄排序
- 显示用户
- 保存通讯录
- 日志追加
有如下知识点:
- 动态数组
- 结构体
- 枚举
- 自定义标识符和宏
- 文件打开与存储
- 函数
- 指针
- 循环
- 排序
简述特点:
- 将人员信息放在一个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,//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);
-
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; }
希望对大家有帮助!文章来源地址https://www.toymoban.com/news/detail-704606.html
文章来源:https://www.toymoban.com/news/detail-704606.html
到了这里,关于C语言程序设计—通讯录实现的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!