1. 前言
在前面我们学习了自定义类型,其中包括结构体,位段,枚举,联合体,其中最有意思的是他们的内存对齐,想要学习的小伙伴们可以点击https://blog.csdn.net/Infernal_Puppet/article/details/133720624
进行学习,今天我们就来实现一下通讯录,后期我们还会讲动态通讯录,利用文件存储通讯录信息。通讯录包括 通讯录的增删查改排序,接下来让我们感受一下通讯录的实现把。
2.主函数
enum nums { 退出, 增加, 查找, 删除, 修改, 排序 }; void menu() { printf("*************************\n"); printf("*** 1.增加 2.查找 ***\n"); printf("*** 3.删除 4.修改 ***\n"); printf("*** 5.排序 0.退出 ***\n"); printf("*************************\n"); } void init_adderstbook(Struct *pc) { memset(pc->arr, 0, sizeof(pc->arr)); pc->i = 0; } void print(Struct* pc) { int i; printf("%-20s%-15s%-3s\n", "姓名", "电话", "年龄"); for (i = 0; i <pc->i; i++) { printf("%-20s%-15s%-3d\n", pc->arr [i].name , pc->arr[i].phone , pc->arr[i].age ); } } int main() { Struct s; init_adderstbook(&s); while(1) { menu(); int num; printf("请输入你想选择的序号:"); scanf("%d", &num); int ret; switch (num) { case 增加: add(&s); print(&s); break; case 查找: finds(&s); break; case 删除: del(&s); print(&s); break; case 修改: mod(&s); print(&s); break; case 排序: qsort(s.arr, s.i, sizeof(s.arr[0]), mysort); print(&s); break; case 退出: return 0; } } return 0; }
这里面包括菜单函数,打印函数,结构体的初始化,还有一个枚举的定义,枚举主要用于switch case语句,由于我们要写的函数较多,容易忘记函数是什么,顺序是什么,我们就可以利用枚举进行定义。
3.增加函数
void add(Struct *pc) { assert(pc); if (pc->i + 1 == Max_Size) { printf("通讯录满了\n"); return; } printf("请输入联系人的姓名:"); scanf("%s", pc->arr[pc->i].name); printf("请输入联系人的电话;"); scanf("%s", pc->arr[pc->i].phone); printf("请输入联系人的年龄:"); scanf("%d", &pc->arr[pc->i].age); pc->i++; }
由于我们要传结构体,分为传值和传址,我们利用传址进行函数的传参,主要原因是这样更高效,由于是指针,我们用assert判断是不是空指针,再判断通讯录是不是满了,然后进行数据的输入。
4.位置查找函数
int find(Struct *pc,char name[]) { assert(pc); int i = 0; for (i = 0; i <= pc->i; i++) { if (strcmp(name, pc->arr[i].name) == 0) { return i; } } return -1; }
在这里我们创建了一个位置查找函数,这个函数主要是用于查找到name的位置,如果没有找到返回-1,找到返回所在的位置,这个函数主要用于删除函数和查找函数以及修改函数。
5.删除函数
void del(Struct* pc) { assert(pc); char name[50]; printf("请输入你想删除人的名字\n"); scanf("%s", name); int ret = find(pc, name); int i; if (ret != -1) { for (i = ret; i < pc->i; i++) { pc->arr[i] = pc->arr[i + 1]; } pc->i--; } }
同样我们先判断是不是指针是不是空指针,然后进行想要查找的名字,利用find函数找到这个名字的位置,如果不是-1进行删除操作,也就是从这个位置开始,进行覆盖操作(前一个等于后一个直到结束),通讯录的人数减少一个,
6.查找函数
void finds(Struct* pc) { assert(pc); char name[50]; scanf("%s", name); int ret = find(pc, name); if (ret != -1) { printf("%-20s%-15s%-3s\n", "姓名", "电话", "年龄"); printf("%-20s%-15s%-3d\n", pc->arr[ret].name, pc->arr[ret].phone, pc->arr[ret].age); } else printf("没找到\n"); }
先进行指针是不是空的判断,输入要查找的人的名字,利用find函数进行查找,如果有进行打印,没有则打印没有找到。
7. 修改函数
void mod(Struct* pc) { assert(pc); char name[50]; printf("请输入你想修改的名字:"); scanf("%s", name); int ret = find(pc, name); if (ret != -1) { printf("请输入你修改后的信息\n"); printf("请输入联系人的姓名:"); scanf("%s", pc->arr[ret].name); printf("请输入联系人的电话;"); scanf("%s", pc->arr[ret].phone); printf("请输入联系人的年龄:"); scanf("%d", &pc->arr[ret].age); } else printf("没有此人\n"); }
先进行指针是不是空的判断,输入想要修改的人的名字,利用find函数进行查找,找到后对其进行修改,没有找到则返回没找到。
8.排序函数
在这个函数中我们用到了qsort函数,qsort函数的参数是要排序的数组,排序几个元素,每个元素占几个字节,排序方式函数,想要学习的可点击qsort函数详细讲解以及利用冒泡排序模拟实现qsort函数-CSDN博客,进行查看。
9.头文件的展示
由于我们是分文件写的,分为主函数文件,函数文件,函数声明文件,其中函数文件和主函数文件是.c文件,函数声明文件是.h文件,具体代码如下:
#pragma once #define Max_Size 50 #include <stdio.h> #include <assert.h> #include <string.h> struct xinxi { char name[50]; char phone[13]; int age; }; typedef struct adderstbook { struct xinxi arr[Max_Size]; int i; }Struct; void add (Struct *pc); int find(Struct* pc,char name[]); void del(Struct* pc); void finds(Struct* pc); void mod(Struct* pc); int mysort(const void* e1, const void* e2);
今天的内容就结束了,欢迎大家来三连;