C语言实现进阶通讯录2.0

146 阅读16分钟

持续创作,加速成长!这是我参与「掘金日新计划 · 10 月更文挑战」的第N天,点击查看活动详情 C语言实现通讯录(进阶版 - 动态内存管理)

上次我们实现了一个可以存储1000个人信息的静态版本的通讯录,那就会衍生出两个情况。 1.如果联系人信息很少的话,会造成很大的内存浪费 2.如果联系人超过1000个人,就无法进行存储 所以,我们需要把通讯录改成动态版本 提供方法: 1.添加联系人信息 2.删除指定联系人信息 3.查找指定联系人信息 4.修改指定联系人信息 5.显示所有联系人信息 6.清空所有联系人 7.以名字排序所有联系人 0.退出通讯录

通讯录实现 前言 一、通讯录菜单的实现 二、main函数实现 三、枚举选项 四、定义通讯录内容以及联系人内容 五、对全局变量进行声明 六、通讯录功能的实现 1.初始化通讯录 2.实现新增联系人(1.add) 3.实现删除联系人(2.del) 4.实现查找联系人(3.seek) 4.1.编写一个查找函数 4.2实现查找联系人 5.实现修改联系人(4.mod) 6.实现展示联系人(5.show) 7.实现清空联系人(6.empty) 8.实现排序联系人信息(7.sort) 9.代码总览 9.1 function.h 9.2 main.c 9.3 function.c 前言 这次写的会比较简略,可以对通讯录1.0版本进行参考 通讯录1.0

正文开始

一、通讯录菜单的实现 程序与用户的交互,需要一个菜单来进行引导,所以我们第一步先实现菜单 需要把菜单的功能列举出来让用户可以进行下一步操作

void mean()//菜单的实现 { printf("*********\n"); printf("***** 1.add 2.del **\n"); printf(" 3.seek 4.mod **\n"); printf(" 5.show 6.empty \n"); printf(" 7.sort 0.exit \n"); printf("\n"); } 1 2 3 4 5 6 7 8 9 二、main函数实现 第二步我们对主函数进行实现

int main() { int input = 0; content ab; //定义通讯录变量ab Initcontact(&ab); //初始化通讯录函数 do { mean(); printf("请选择->"); scanf("%d",&input); switch (input) { case EXIT: printf("退出通讯录\n"); break; case ADD: addcontact(&ab); //增加联系人信息函数 break; case DEL: delcontact(&ab); //删除联系人信息函数 break; case SEEK: seekcontact(&ab); //寻找联系人信息函数 break; case MOD: modcontact(&ab); //修改联系人信息函数 break; case SHOW: showcontact(&ab); //展示联系人信息函数 break; case EMPTY: emptycontact(&ab); //清空联系人信息函数 case SORT: sortcontact(&ab); //排序联系人信息函数 break; } } while (input); return 0;

}

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 将所有需要实现的情况都放在main,方便自己可以逻辑清晰的编写代码

三、枚举选项 一开始我们就用数字来编辑了菜单的选项,在这里需要用到枚举来实现菜单的选项,与主函数中的case进行对应

enum mean { EXIT,//0 ADD,//1 DEL,//2 SEEK,//3 MOD,//4 SHOW,//5 EMPTY,//6 SORT//7 }; 1 2 3 4 5 6 7 8 9 10 11 运用枚举是为了让代码逻辑更加简洁易懂,提高代码的可维护性

四、定义通讯录内容以及联系人内容 这是个动态增长的版本,需要记录存放的数据,有效数据个数,默认数据个数

typedef struct message { char name[MIN_NAME]; char sex[MIN_SEX]; int age; char number[MIN_NUMBER]; char address[MIN_ADDRESS]; }message; typedef struct data { message* data; //用来保存通讯录存放的数据 int sz; //用来记录通讯录中有效数据的个数 int capcity; //用来记录通讯录默认数据个数 }content; 1 2 3 4 5 6 7 8 9 10 11 12 13 14 五、对全局变量进行声明 我们需要对通讯录内的数据做一定的限制,这里需要对全局变量做一些声明

#define MIN_NAME 15 //设置姓名数组中字符的个数 #define MIN_SEX 5 //设置性别数组中字符的个数 #define MIN_NUMBER 20 //设置号码数组中字符的个数 #define MIN_ADDRESS 18 //设置地址数组中字符的个数 #define FRINUM 3 //设置通讯录默认起始数据 1 2 3 4 5 六、通讯录功能的实现 我们已经拥有一个简易的通讯录了,现在需要对前文列举的功能进行一一实现

1.初始化通讯录 首先我们需要实现通讯录的保存功能,我们需要实现通讯录的初始化功能

//初始化通讯录函数 void Initcontact(content* ab) { assert(ab); ab->sz = 0; ab->capcity = FRINUM; message* tmp = (message*)malloc(FRINUM*sizeof(message)); //判断tmp是否为空指针 if (tmp == NULL) { printf("Initcontact::%s\n",strerror(errno)); return; } ab->data = tmp; //动态的为指针ab开辟内存 return; }

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 2.实现新增联系人(1.add) //增加联系人函数 void addcontact(content* ab) { assert(ab); capcityadd(ab); //增加通讯录的容量 printf("请输入联系人的姓名->"); scanf("%s",ab->data[ab->sz].name); printf("请输入联系人的性别->"); scanf("%s",ab->data[ab->sz].sex); printf("请输入联系人的年龄->"); scanf("%d",&(ab->data[ab->sz].age)); printf("请输入联系人的电话->"); scanf("%s",ab->data[ab->sz].number); printf("请输入联系人的住址->"); scanf("%s",ab->data[ab->sz].address); printf("增加联系人成功\n"); ab->sz++; }

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 3.实现删除联系人(2.del) //删除联系人函数 void delcontact(content* ab) { assert(ab); char name[MIN_NAME] = {0}; printf("请输入要删除联系人的姓名->"); scanf("%s", name); int ret = seekname(name,ab); //查找姓名函数 if (ret == -1) printf("没有该联系人\n"); else { for (i = ret; i < ab->sz; i++) { ab->data[i] = ab->data[i + 1]; } printf("删除指定联系人成功\n"); ab->sz--; //注意这一一定要执行这一步,删除一个联系人以后通讯录中有效个数就应该减少1 } return; }

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 4.实现查找联系人(3.seek) 4.1.编写一个查找函数 为了使代码的可读性更高,功能更加齐全,我们需要编写一个通过姓名可以查找的功能

//查找姓名函数 int seekname(char* name, content* ab) { for (i = 0; i < ab->sz; i++) { if ((strcmp(name, ab->data[i].name)) == 0) return i; } return -1; } 1 2 3 4 5 6 7 8 9 10 4.2实现查找联系人 //寻找联系人函数 void seekcontact(content* ab) { assert(ab); char name[MIN_NAME] = { 0 }; printf("请输入要查找联系人的姓名->"); scanf("%s", name); int ret = seekname(name, ab); //查找姓名函数 if (ret == -1) { printf("没有该联系人\n"); return; } else { printf("%-7s\t%-5s\t%-5s\t%-15s\t%-20s\n", "姓名", "性别", "年龄", "电话", "住址"); printf("%-7s\t%-5s\t%-5d\t%-15s\t%-20s\n", ab->data[ret].name, ab->data[ret].sex, ab->data[ret].age, ab->data[ret].number, ab->data[ret].address); } return; }

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 5.实现修改联系人(4.mod) //修改联系人信息函数 void modcontact(content* ab) { assert(ab); char name[MIN_NAME] = { 0 }; printf("请输入要查找联系人的姓名->"); scanf("%s", name); int ret = seekname(name, ab); //查找姓名函数 if (ret == -1) { printf("没有该联系人\n"); return; } else { printf("%-7s\t%-5s\t%-5s\t%-15s\t%-20s\n", "姓名", "性别", "年龄", "电话", "住址"); printf("%-7s\t%-5s\t%-5d\t%-15s\t%-20s\n", ab->data[ret].name, ab->data[ret].sex, ab->data[ret].age, ab->data[ret].number, ab->data[ret].address); } printf("请输入修改信息\n"); printf("请输入联系人的姓名->"); scanf("%s", ab->data[ret].name); printf("请输入联系人的性别->"); scanf("%s", ab->data[ret].sex); printf("请输入联系人的年龄->"); scanf("%d", &(ab->data[ret].age)); printf("请输入联系人的电话->"); scanf("%s", ab->data[ret].number); printf("请输入联系人的住址->"); scanf("%s", ab->data[ret].address); printf("修改成功\n"); return; }

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 6.实现展示联系人(5.show) //展示联系人函数 void showcontact(content* ab) { //姓名、性别、年龄、电话、住址 assert(ab); printf("%-7s\t%-5s\t%-5s\t%-15s\t%-20s\n","姓名","性别", "年龄", "电话", "住址"); for (i = 0; i < ab->sz; i++) { printf("%-7s\t%-5s\t%-5d\t%-15s\t%-20s\n", ab->data[i].name, ab->data[i].sex, ab->data[i].age, ab->data[i].number, ab->data[i].address); } return; } 1 2 3 4 5 6 7 8 9 10 11 12 13 7.实现清空联系人(6.empty) //清空联系人信息函数 void emptycontact(content* ab) { assert(ab); printf("请确认是否要清空通讯录(Y/N):"); char str = 0; while ((str = getchar()) != '\n') { ; } scanf("%c", &str); if (str == 'Y') { ab->data = 0; ab->capcity = 0; ab->sz = 0; printf("全部清除成功\n"); } return; }

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 8.实现排序联系人信息(7.sort) //排序联系人信息函数 void sortcontact(content* ab) { assert(ab); qsort(ab->data,ab->sz,sizeof(ab->data[0]),compare); printf("%-7s\t%-5s\t%-5s\t%-15s\t%-20s\n", "姓名", "性别", "年龄", "电话", "住址"); for (i = 0; i < ab->sz; i++) { printf("%-7s\t%-5s\t%-5d\t%-15s\t%-20s\n", ab->data[i].name, ab->data[i].sex, ab->data[i].age, ab->data[i].number, ab->data[i].address); } return; }

1 2 3 4 5 6 7 8 9 10 11 12 13 14 9.代码总览 到这里进阶通讯录2.0已经全部完成了,下面就是程序的源代码

9.1 function.h #include <stdio.h> #include <assert.h> #include <stdlib.h> #include <string.h> #include <errno.h>

#define _CRT_SECURE_NO_WARNINGS #define MIN_NAME 15 //设置姓名数组中字符的个数 #define MIN_SEX 5 //设置性别数组中字符的个数 #define MIN_NUMBER 20 //设置号码数组中字符的个数 #define MIN_ADDRESS 18 //设置地址数组中字符的个数 #define FRINUM 3 //设置通讯录默认起始数据

typedef struct message { char name[MIN_NAME]; char sex[MIN_SEX]; int age; char number[MIN_NUMBER]; char address[MIN_ADDRESS]; }message; typedef struct data { message* data; //用来保存通讯录存放的数据 int sz; //用来记录通讯录中有效数据的个数 int capcity; //用来记录通讯录默认数据个数 }content;

void Initcontact(content* ab); //初始化通讯录函数声明 void addcontact(content* ab); //增加联系人信息函数声明 void delcontact(content* ab); //删除联系人信息函数声明 void seekcontact(content* ab); //寻找联系人信息函数声明 void modcontact(content* ab); //修改联系人信息函数声明 void emptycontact(content* ab); //清空联系人信息函数声明 void showcontact(content* ab); //展示联系人信息函数声明 void sortcontact(content* ab); //排序联系人信息函数声明

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 9.2 main.c #include "function.h" //实现通讯录:通讯录可以用来存储1000个人的信息,每个人的信息包括:姓名、性别、年龄、电话、住址 //1.添加联系人信息 //2.删除指定联系人信息 //3.查找指定联系人信息 //4.修改指定联系人信息 //5.显示所有联系人信息 //6.清空所有联系人 //7.以名字排序所有联系人 enum number { EXIT, ADD, DEL, SEEK, MOD, SHOW, EMPTY, SORT }; void mean() { printf("*********\n"); printf("***** 1.add 2.del **\n"); printf(" 3.seek 4.mod **\n"); printf(" 5.show 6.empty \n"); printf(" 7.sort 0.exit \n"); printf("\n"); } int main() { int input = 0; content ab; //定义通讯录变量ab Initcontact(&ab); //初始化通讯录函数 do { mean(); printf("请选择->"); scanf("%d",&input); switch (input) { case EXIT: printf("退出通讯录\n"); break; case ADD: addcontact(&ab); //增加联系人信息函数 break; case DEL: delcontact(&ab); //删除联系人信息函数 break; case SEEK: seekcontact(&ab); //寻找联系人信息函数 break; case MOD: modcontact(&ab); //修改联系人信息函数 break; case SHOW: showcontact(&ab); //展示联系人信息函数 break; case EMPTY: emptycontact(&ab); //清空联系人信息函数 case SORT: sortcontact(&ab); //排序联系人信息函数 break; } } while (input); return 0;

}

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 9.3 function.c #include "function.h"

int i = 0; //全局变量i //排序里面的比较函数 int compare(const void* e1, const void* e2) { return strcmp(((message*)e1)->name, ((message*)e2)->name); }

//增加通讯录容量函数 void capcityadd(content* ab) { if (ab->sz == ab->capcity) { message* tmp = (message*)realloc(ab->data, (ab->capcity + 2) * sizeof(message)); //注意这里的结构体,不要引错了 if (tmp != NULL) { ab->data = tmp; ab->capcity += 2; printf("增加容量成功\n"); } else { printf("addcontact::%s\n", strerror(errno)); } } }

//查找姓名函数 int seekname(char* name, content* ab) { for (i = 0; i < ab->sz; i++) { if ((strcmp(name, ab->data[i].name)) == 0) return i; } return -1; }

//初始化通讯录函数 void Initcontact(content* ab) { assert(ab); ab->sz = 0; ab->capcity = FRINUM; message* tmp = (message*)malloc(FRINUM*sizeof(message)); //判断tmp是否为空指针 if (tmp == NULL) { printf("Initcontact::%s\n",strerror(errno)); return; } ab->data = tmp; //动态的为指针ab开辟内存 return; }

//增加联系人函数 void addcontact(content* ab) { assert(ab); capcityadd(ab); //增加通讯录的容量 printf("请输入联系人的姓名->"); scanf("%s",ab->data[ab->sz].name); printf("请输入联系人的性别->"); scanf("%s",ab->data[ab->sz].sex); printf("请输入联系人的年龄->"); scanf("%d",&(ab->data[ab->sz].age)); printf("请输入联系人的电话->"); scanf("%s",ab->data[ab->sz].number); printf("请输入联系人的住址->"); scanf("%s",ab->data[ab->sz].address); printf("增加联系人成功\n"); ab->sz++; }

//删除联系人函数 void delcontact(content* ab) { assert(ab); char name[MIN_NAME] = {0}; printf("请输入要删除联系人的姓名->"); scanf("%s", name); int ret = seekname(name,ab); //查找姓名函数 if (ret == -1) printf("没有该联系人\n"); else { for (i = ret; i < ab->sz; i++) { ab->data[i] = ab->data[i + 1]; } printf("删除指定联系人成功\n"); ab->sz--; //注意这一一定要执行这一步,删除一个联系人以后通讯录中有效个数就应该减少1 } return; }

//寻找联系人函数 void seekcontact(content* ab) { assert(ab); char name[MIN_NAME] = { 0 }; printf("请输入要查找联系人的姓名->"); scanf("%s", name); int ret = seekname(name, ab); //查找姓名函数 if (ret == -1) { printf("没有该联系人\n"); return; } else { printf("%-7s\t%-5s\t%-5s\t%-15s\t%-20s\n", "姓名", "性别", "年龄", "电话", "住址"); printf("%-7s\t%-5s\t%-5d\t%-15s\t%-20s\n", ab->data[ret].name, ab->data[ret].sex, ab->data[ret].age, ab->data[ret].number, ab->data[ret].address); } return; }

//修改联系人信息函数 void modcontact(content* ab) { assert(ab); char name[MIN_NAME] = { 0 }; printf("请输入要查找联系人的姓名->"); scanf("%s", name); int ret = seekname(name, ab); //查找姓名函数 if (ret == -1) { printf("没有该联系人\n"); return; } else { printf("%-7s\t%-5s\t%-5s\t%-15s\t%-20s\n", "姓名", "性别", "年龄", "电话", "住址"); printf("%-7s\t%-5s\t%-5d\t%-15s\t%-20s\n", ab->data[ret].name, ab->data[ret].sex, ab->data[ret].age, ab->data[ret].number, ab->data[ret].address); } printf("请输入修改信息\n"); printf("请输入联系人的姓名->"); scanf("%s", ab->data[ret].name); printf("请输入联系人的性别->"); scanf("%s", ab->data[ret].sex); printf("请输入联系人的年龄->"); scanf("%d", &(ab->data[ret].age)); printf("请输入联系人的电话->"); scanf("%s", ab->data[ret].number); printf("请输入联系人的住址->"); scanf("%s", ab->data[ret].address); printf("修改成功\n"); return; }

//清空联系人信息函数 void emptycontact(content* ab) { assert(ab); printf("请确认是否要清空通讯录(Y/N):"); char str = 0; while ((str = getchar()) != '\n') { ; } scanf("%c", &str); if (str == 'Y') { ab->data = 0; ab->capcity = 0; ab->sz = 0; printf("全部清除成功\n"); } return; }

//展示联系人函数 void showcontact(content* ab) { //姓名、性别、年龄、电话、住址 assert(ab); printf("%-7s\t%-5s\t%-5s\t%-15s\t%-20s\n","姓名","性别", "年龄", "电话", "住址"); for (i = 0; i < ab->sz; i++) { printf("%-7s\t%-5s\t%-5d\t%-15s\t%-20s\n", ab->data[i].name, ab->data[i].sex, ab->data[i].age, ab->data[i].number, ab->data[i].address); } return; }

//排序联系人信息函数 void sortcontact(content* ab) { assert(ab); qsort(ab->data,ab->sz,sizeof(ab->data[0]),compare); printf("%-7s\t%-5s\t%-5s\t%-15s\t%-20s\n", "姓名", "性别", "年龄", "电话", "住址"); for (i = 0; i < ab->sz; i++) { printf("%-7s\t%-5s\t%-5d\t%-15s\t%-20s\n", ab->data[i].name, ab->data[i].sex, ab->data[i].age, ab->data[i].number, ab->data[i].address); } return; }

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203