通讯录,一种用于记录通讯地址的书本,在手机,电脑等电子设备中也拥有这种功能,它里面涵盖多种内容,如:姓名、年龄、性别、地址、电话等等,本文就用C语言带大家去实现静态通讯录。我们有几次实现游戏的经验,如扫雷、三子棋,这次同样是分成三个模块,一个用于实现功能,一个用于调用我们实现的功能,一个用于声明。
一.功能实现
1.打印开始菜单
和三子棋扫雷一样,我们都需要有一个开始菜单,告诉使用者有那些功能,对于我们的通讯录来说,无非就是添加联系人、删除联系人、查找联系人、修改联系人等等,那和三子棋扫雷一样,我们先将这些制作到菜单当中,让使用者选择。
void menu() { printf("************************************\n"); printf("***** 1.添加 2.删除 *****\n"); printf("***** 3.查找 4.修改 *****\n"); printf("***** 5.显示 6.清空 *****\n"); printf("***** 7.排序 0.退出 *****\n"); printf("************************************\n"); }
2.实现选择
选择选择也于扫雷三子棋大同小异,利用dowhile语句来实现多次循环,因为这次选择的功能很多,所以我们采用switch语句。
int input = 0; do { menu(); printf("请选择:>"); scanf("%d", &input); switch(input) { case 1: break; case 2: break; case 3: break; case 4: break; case 5: break; case 6:; break; case 7: break; case 0: printf("退出通讯录\n"); break; default: printf("选择错误,请重新选择\n"); break; } } while (input);
3.初始化通讯录
我们要实现一个通讯录,那我们这些数据要放在哪里?这里就用到了我们的结构体,我们需要一个结构体,代表一个人的信息,名字,性别,地址这些,那我们还需要确定的是,我们这个通讯录能存多少个人的信息,那我们就假设我们通讯里可以存放一百个人的,那这一百个人,我们去存放的时候怎么知道我们存了多少个人了信息了呢?那这里我们就可以在用一个结构体,里面放我们存放信息的结构体数组,然后一个整型类型的变量,每次存放就加加,删除就减减。
struct addbook { char name[20]; int age; char gen[5]; char loc[20]; char ph[12]; }; typedef struct addbooks { struct addbook s[100]; int sz; }addb;
那有了这些东西,在没有初始化之前,这些变量和数组里面存放的东西都是未知的,那就需要我们去初始化数组,我们可以直接用第二个结构体类型定义一个变量然后等于0,全初始化成0,我们也可以用一个函数menset来进行我们的初始化,将我们存放信息的数组内的初始化成我们想要的数值。
//初始化通讯录 void init_addbook(addb* ab) { assert(ab); ab->sz= 0; memset(ab->s, 0, sizeof(ab->s)); }
4.添加、删除等功能实现
(1)添加联系人
添加联系人,这个函数实现逻辑很简单,我们每次添加之前,先确定我们的通讯录是有位置的,所以我们可以先对sz进行一个判断,如果它等于100,就告诉我们通讯录已满,如果没有,就将下标为sz的位置替换成我们想要输入的信息,然后sz加加。
//添加联系人 void add_book(addb* ab) { assert(ab); if (ab->sz == MAX) { printf("通讯录已满"); return; } printf("请输入姓名:>"); scanf("%s", ab->s[ab->sz].name); printf("请输入年龄:>"); scanf("%d", &(ab->s[ab->sz].age)); printf("请输入性别:>"); scanf("%s", ab->s[ab->sz].gen); printf("请输入地址:>"); scanf("%s", ab->s[ab->sz].loc); printf("请输入电话:>"); scanf("%s", ab->s[ab->sz].ph); printf("联系人添加成功\n"); ab->sz++; }
(2)删除联系人
删除联系人,我们可以采用输入名字,然后删除的方式,所以我们可以输入一个名字,然后开始对比数组内的每一个名字,相等就进去,跳出循环,然后开始让后面的信息往前面覆盖,最后让sz减减,这里我们要注意,我们后续实现的内容很多都要用到我们的查找,那我们就可以将查找部分分装成一个函数,返回一个整数,如果找不到,就返回-1,找到了,返回此时的下标位置。
//查找 int find_book(addb* ab) { assert(ab); char ch[NAME_MAX] = { 0 }; printf("请输入联系人姓名:>"); scanf("%s", ch); int i = 0; for (; i < ab->sz; i++) { if (!strcmp(ab->s[i].name , ch)) { return i; } } return -1; } //删除联系人 void del_book(addb* ab) { assert(ab); int find = find_book(ab); if (-1==find) { printf("没有找到此人\n"); } else { for (; find < ab->sz - 1; find++) { ab->s[find] = ab->s[find + 1]; } ab->sz--; } }
(3)查找联系人
查找就和我们的删除思路大概一样了,同样调用我们的查找函数,找不到返回-1,告诉我们没有这个人,然后跳出函数,但是后面找到就与删除不一样了,我们将返回下标对应的内容打印出来,就找到了,这里找到联系人之后,信息打印在屏幕上,但是没有提示,对于我们来说可能就有点难确定哪个是哪个,所以这里我们加一个表头,对应每个信息。
//查找联系人 void seek_book(addb* ab) { assert(ab); int i = find_book(ab); if (i == -1) { printf("没有找到此联系人\n"); } else { printf("%-20s\t%-4s\t%-5s\t%-20s\t%-12s\n", "姓名", "年龄", "性别", "地址", "电话"); printf("%-20s\t%-4d\t%-5s\t%-20s\t%-12s\n", ab->s[i].name, ab->s[i].age, ab->s[i].gen, ab->s[i].loc, ab->s[i].ph); } }
(4)修改联系人
修改也是用我们的查找函数,查找不到就告诉我们没有,然后跳出,查找到了就修改。
//修改联系人 void amend_book(addb* ab) { assert(ab); int i = find_book(ab); if (i == -1) { printf("没有找到此联系人\n"); } else { printf("请输入姓名:>"); scanf("%s", ab->s[i].name); printf("请输入年龄:>"); scanf("%d", &(ab->s[i].age)); printf("请输入性别:>"); scanf("%s", ab->s[i].gen); printf("请输入地址:>"); scanf("%s", ab->s[i].loc); printf("请输入电话:>"); scanf("%s", ab->s[i].ph); printf("联系人修改成功\n"); } }
(5)显示所有联系人
我们要显示所有联系人,只用打印出我们数组的所有内容就可以,为了方便我们查看,也打印上表头。
//显示全部联系人 void show_book(addb* ab) { assert(ab); printf("%-20s\t%-4s\t%-5s\t%-20s\t%-12s\n", "姓名", "年龄", "性别", "地址", "电话"); int i = 0; for (; i < ab->sz; i++) { printf("%-20s\t%-4d\t%-5s\t%-20s\t%-12s\n", ab->s[i].name, ab->s[i].age, ab->s[i].gen, ab->s[i].loc, ab->s[i].ph); } }
(6)清空联系人
清空联系人,也就是和我们的初始化一样,讲数组内容清空。
//初始化通讯录 void init_addbook(addb* ab) { assert(ab); ab->sz= 0; memset(ab->s, 0, sizeof(ab->s)); } (7)排序联系人 排序,我们可以用qsort,进行排序,用名字来进行排序。 //qsort int name_sort(const void* s1, const void* s2) { assert(s1 && s2); return strcmp((char*)s1, (char*)s2); }
二.模块调用
对于我们的通讯录来说,不需要什么逻辑,我们只需要在选择对应的数字的时候,实行对应的功能即可。
源码
addbook.h
#pragma once #include<stdio.h> #include<string.h> #include<stdlib.h> #include<assert.h> #define MAX 100 #define NAME_MAX 20 #define GEM_MAX 5 #define LOC_MAX 20 #define PH_MAX 12 struct addbook { char name[NAME_MAX]; int age; char gen[GEM_MAX]; char loc[LOC_MAX]; char ph[PH_MAX]; }; typedef struct addbooks { struct addbook s[MAX]; int sz; }addb; //功能实现 void init_addbook(addb* ab);//初始化通讯录 void add_book(addb* ab);//添加联系人 void del_book(addb* ab);//删除联系人 int find_book(addb* ab);//查找 void seek_book(addb* ab);//查找联系人 void amend_book(addb* ab);//修改联系人 void show_book(addb* ad);//显示全部联系人 int name_sort(const void* s1, const void* s2);//qsort
addbook.c
#include"addbook.h" //初始化通讯录 void init_addbook(addb* ab) { assert(ab); ab->sz= 0; memset(ab->s, 0, sizeof(ab->s)); } //添加联系人 void add_book(addb* ab) { assert(ab); if (ab->sz == MAX) { printf("通讯录已满"); return; } printf("请输入姓名:>"); scanf("%s", ab->s[ab->sz].name); printf("请输入年龄:>"); scanf("%d", &(ab->s[ab->sz].age)); printf("请输入性别:>"); scanf("%s", ab->s[ab->sz].gen); printf("请输入地址:>"); scanf("%s", ab->s[ab->sz].loc); printf("请输入电话:>"); scanf("%s", ab->s[ab->sz].ph); printf("联系人添加成功\n"); ab->sz++; } //查找 int find_book(addb* ab) { assert(ab); char ch[NAME_MAX] = { 0 }; printf("请输入联系人姓名:>"); scanf("%s", ch); int i = 0; for (; i < ab->sz; i++) { if (!strcmp(ab->s[i].name , ch)) { return i; } } return -1; } //删除联系人 void del_book(addb* ab) { assert(ab); int find = find_book(ab); if (-1==find) { printf("没有找到此人\n"); } else { for (; find < ab->sz - 1; find++) { ab->s[find] = ab->s[find + 1]; } ab->sz--; } } //查找联系人 void seek_book(addb* ab) { assert(ab); int i = find_book(ab); if (i == -1) { printf("没有找到此联系人\n"); } else { printf("%-20s\t%-4s\t%-5s\t%-20s\t%-12s\n", "姓名", "年龄", "性别", "地址", "电话"); printf("%-20s\t%-4d\t%-5s\t%-20s\t%-12s\n", ab->s[i].name, ab->s[i].age, ab->s[i].gen, ab->s[i].loc, ab->s[i].ph); } } //修改联系人 void amend_book(addb* ab) { assert(ab); int i = find_book(ab); if (i == -1) { printf("没有找到此联系人\n"); } else { printf("请输入姓名:>"); scanf("%s", ab->s[i].name); printf("请输入年龄:>"); scanf("%d", &(ab->s[i].age)); printf("请输入性别:>"); scanf("%s", ab->s[i].gen); printf("请输入地址:>"); scanf("%s", ab->s[i].loc); printf("请输入电话:>"); scanf("%s", ab->s[i].ph); printf("联系人修改成功\n"); } } //显示全部联系人 void show_book(addb* ab) { assert(ab); printf("%-20s\t%-4s\t%-5s\t%-20s\t%-12s\n", "姓名", "年龄", "性别", "地址", "电话"); int i = 0; for (; i < ab->sz; i++) { printf("%-20s\t%-4d\t%-5s\t%-20s\t%-12s\n", ab->s[i].name, ab->s[i].age, ab->s[i].gen, ab->s[i].loc, ab->s[i].ph); } } //qsort int name_sort(const void* s1, const void* s2) { assert(s1 && s2); return strcmp((char*)s1, (char*)s2); }
test.c
#include"addbook.h" void menu() { printf("************************************\n"); printf("***** 1.添加 2.删除 *****\n"); printf("***** 3.查找 4.修改 *****\n"); printf("***** 5.显示 6.清空 *****\n"); printf("***** 7.排序 0.退出 *****\n"); printf("************************************\n"); } int main() { int input = 0; addb ab; init_addbook(&ab); do { menu(); printf("请选择:>"); scanf("%d", &input); switch(input) { case 1: add_book(&ab); break; case 2: del_book(&ab); break; case 3: seek_book(&ab); break; case 4: amend_book(&ab); break; case 5: show_book(&ab); break; case 6: init_addbook(&ab); break; case 7: qsort(&ab, ab.sz, sizeof(ab.s[0]),name_sort); break; case 0: printf("退出通讯录\n"); break; default: printf("选择错误,请重新选择\n"); break; } } while (input); return 0; }