用c语言实现一个通讯录
功能:.添加、删除、查找、更改、显示、排序联系人
内存存储方式:结构体数组
1.打印菜单,各个功能分别用函数实现,将函数声明放在头文件中。
2.定义联系人信息,将联系人信息与count(用来记录当前通讯录人数),capacity(记录最大容量)。一起定义到结构体中,完成联系人的创建:
- //定义联系人
- typedef struct PenInfo {
- char name[20];
- int age;
- char sex[10];
- char tele[12];
- char addr[30];
- }PenInfo;
-
- typedef struct Contact {
- PenInfo* data;
- int count;
- int capacity;//设置我通讯录的最大容量
- }Contact;
3.创建联系人,并用malloc或calloc函数向内存堆区开辟内存,在退出时记得释放内存,将count初始化为0:
- int Initcontact(Contact* pc) {
- assert(pc);
- pc->data =(PenInfo*) calloc(3,3 * sizeof(PenInfo));//为data开辟三个空间
- if (pc->data == NULL) {
- printf("%s", strerror(errno));
- return 1;
- }
- pc->count = 0;
- pc->capacity = 3;//设置最大容量为3
-
- //从文件中读取联系人内容
- LoadContact(pc);
- return 0;
- }
4.添加联系人,当联系人容量达到最大容量时,增容,然后进行联系人的信息输入:
- void AddCapacity(Contact *pc) {
- assert(pc);
- if (pc->count == pc->capacity) {
- PenInfo*str=(PenInfo*)realloc(pc->data, (pc->capacity + 2) * sizeof(PenInfo));
- if (str == NULL) {
- perror("空间不足\n");
- return;
- }
- pc->capacity +=2;
- pc->data = str;
-
- //printf("增容成功\n");
- }
- return;
- }
-
-
- void Addcontact(Contact* pc){
- assert(pc);
- //增容
- AddCapacity(pc);
- //添加联系人
- printf("请输入联系人名字:>");
- scanf("%s", pc->data[pc->count].name);
- printf("请输入联系人年龄:>");
- scanf("%d", &(pc->data[pc->count].age));
- printf("请输入联系人性别:>");
- scanf("%s", pc->data[pc->count].sex);
- printf("请输入联系人电话:>");
- scanf("%s", pc->data[pc->count].tele);
- printf("请输入联系人地址:>");
- scanf("%s", pc->data[pc->count].addr);
-
- pc->count++;
-
- printf("添加成功\n");
- }
5. 显示联系人(记得格式化),通过for循环标准输出:
- void Showcontact(const Contact* pc) {
- assert(pc);
- if (pc->count == 0) {
- printf("还没添加联系人\n");
- return;
- }
- printf("%-20s\t%-3s\t%-10s\t%-12s\t%-30s\n", "名字", "年龄", "性别", "电话", "地址");
- printf("-----------------------------------------------------------------------------\n");
- for (int i = 0; i < pc->count; i++) {
-
- printf("%-20s\t%-5d\t%-10s\t%-12s\t%-30s", pc->data[i].name,
- pc->data[i].age,
- pc->data[i].sex,
- pc->data[i].tele,
- pc->data[i].addr);
- printf("\n");
- printf("-----------------------------------------------------------------------------\n");
- }
- }
6.当查找、删除、更改时都需要进行查找,所以直接封装一个查找函数(找到了返回下标):
- //查找联系人
- static int Findcontact(Contact* pc, char* name) {
- assert(pc);
- for (int i = 0; i < pc->count; i++) {
- if (strcmp(name, pc->data[i].name) == 0) {
- return i;
- }
- }
- return -1;
- }
7.查找联系人:
- void Searchcontact(Contact* pc) {
- assert(pc);
- char name[20] = { 0 };
- printf("请输入要查找的联系人名字:>");
- scanf("%s", name);
- //查找
- int pos = Findcontact(pc, name);
- //删除
- if (pos == -1) {
- printf("没有该联系人\n");
- return;
- }
- else {
- printf("找到了\n");
- printf("%-20s\t%-3s\t%-10s\t%-12s\t%-30s\n", "名字", "年龄", "性别", "电话", "地址");
- printf("-----------------------------------------------------------------------------\n");
-
- printf("%-20s\t%-5d\t%-10s\t%-12s\t%-30s", pc->data[pos].name,
- pc->data[pos].age,
- pc->data[pos].sex,
- pc->data[pos].tele,
- pc->data[pos].addr);
- printf("\n");
- printf("-----------------------------------------------------------------------------\n");
- }
-
- }
8.删除联系人,删除后,由于是顺序表存储,将后面的数据向前一个结点覆盖,且count--:
- void Delcontact(Contact* pc) {
- assert(pc);
- char name[20] = { 0 };
- printf("请输入要删除的联系人名字:>");
- scanf("%s", name);
- //查找
- int pos = Findcontact(pc, name);
- //删除
- if (pos == -1) {
- printf("没有该联系人\n");
- return;
- }
- for (int i = pos; i < pc->count + 1; i++) {//count+1防止溢出
- pc->data[i] = pc->data[i + 1];
- }
- pc->count--;
- printf("删除成功\n");
-
- }
9.修改联系人,将信息覆盖即可:
- void Modifycontact(Contact* pc) {
- assert(pc);
- char name[20] = { 0 };
- printf("请输入要修改的联系人的名字:>");
- scanf("%s", name);
- //查找
- int pos = Findcontact(pc, name);
- //删除
- if (pos == -1) {
- printf("没有该联系人\n");
- return;
- }else {
- printf("修改后联系人名字:>");
- scanf("%s", pc->data[pos].name);
- printf("修改后联系人年龄:>");
- scanf("%d", &(pc->data[pos].age));
- printf("修改后联系人性别:>");
- scanf("%s", pc->data[pos].sex);
- printf("修改后联系人电话:>");
- scanf("%s", pc->data[pos].tele);
- printf("修改后联系人地址:>");
- scanf("%s", pc->data[pos].addr);
- printf("\n");
- printf("修改成功\n");
- }
- }
10.排序,分为年龄和姓名,都用库函数qsort(默认升序)实现,年龄进行时稍微复杂,细节如下:
- //按姓名排序函数
- int Sort_by_name(const void* e1, const void* e2) {
- return strcmp(((PenInfo*)e1)->name, ((PenInfo*)e2)->name);
- }
- //按年龄排序
- int Sort_by_age(const void* e1, const void* e2) {
- if (((PenInfo*)e1)->age < ((PenInfo*)e2)->age) {
- return -1;
- }
- if (((PenInfo*)e1)->age > ((PenInfo*)e2)->age) {
- return 1;
- }
- if (((PenInfo*)e1)->age == ((PenInfo*)e2)->age) {
- return 0;
- }
- }
-
- void Sortcontact(Contact* pc) {
- assert(pc);
- int chiose;
- printf("(1.按姓名排序 2.按年龄排序):>");
- scanf("%d", &chiose);
- if (chiose == 1) {
- qsort(pc->data,pc->count,sizeof(PenInfo), Sort_by_name);
- printf("排序成功\n");
- }
- else if (chiose == 2) {
- qsort(pc->data, pc->count, sizeof(PenInfo), Sort_by_age);
- printf("排序成功\n");
- }
- else {
- printf("无效输入\n");
- return;
- }
- }
11.保存联系人到相对路径“contact.txt”中,通过二进制进行输入输出,退出时保存,打开时读取。
- void SaveContact(Contact* pc) {
- FILE* pfWrite = fopen("contact.txt", "wb");
- if (pfWrite == NULL) {
- perror("SaveContact");
- return;
- }
- //用二进制的形式写入文件
- for (int i = 0; i <= pc->count; i++) {
- fwrite(pc->data+i, sizeof(PenInfo), 1, pfWrite);
- }
- //关闭文件
- fclose(pfWrite);
- pfWrite = NULL;
- }
-
- void LoadContact(Contact* pc) {
- assert(pc);
- FILE* pfRead = fopen("contact.txt", "rb");
- if (pfRead == NULL) {
- //perror("LoadContact");
- return;
- }
- while (fread(&(pc->data[pc->count]), sizeof(PenInfo), 1, pfRead) == 1) {
- //判断是否空间不足
- AddCapacity(pc);
- pc->count++;
- }
- fclose(pfRead);
- pfRead = NULL;
- }
12.测试代码:
- #define _CRT_SECURE_NO_WARNINGS
-
- #include "contact.h"
-
- //创建菜单
- void menu() {
- printf("------------My ContactBook------------\n");
- printf("-----------1.Add linkman ------------\n");
- printf("-----------2.Del linkman ------------\n");
- printf("-----------3.Show linkman ------------\n");
- printf("-----------4.Search linkman ----------\n");
- printf("-----------5.Modify linkman ----------\n");
- printf("-----------6.Sort linkman -----------\n");
- printf("-----------0.Exit menu -------------\n");
-
- }
- int main() {
- int input = 0;
- //创建联系人
- Contact con;
- //初始化通讯录
- Initcontact(&con);
- do {
- menu();
- printf("请选择对应功能的编号:>");
- scanf("%d", &input);
- switch (input) {
- case 1:
- Addcontact(&con);
- break;
- case 2:
- Delcontact(&con);
- break;
- case 3:
- Showcontact(&con);
- break;
- case 4:
- Searchcontact(&con);
- break;
- case 5:
- Modifycontact(&con);
- break;
- case 6:
- Sortcontact(&con);
- break;
- case 0:
- SaveContact(&con);
- DestoryContact(&con);
- printf("退出通讯录\n");
- break;
- default :
- printf("选择错误\n");
- break;
- }
- } while (input);
- return 0;
- }
测试结果:

