🦄个人主页:-雷阵雨-
⚙️操作环境:Visual Studio 2019
目录
一:前言
本文章将使用C语言实现通讯录的系统,并且储存个人的信息 电话 性别 年龄 电话 地址。并且对通讯录进行增删查改 排序 打印操作。
二:通讯录的实现
1:通讯录的准备
(1):菜单的实现
首先建立一个通讯录,建立一个菜单很重要,菜单能便于用户对通讯录进行操作。
代码如下:
menu() { printf("***************************\n"); printf("******1.add 2.del*******\n");//增加 删除 printf("******3.search 4.modify****\n");//查 改 printf("******5.show 6.sort******\n");//显示所有 排序 printf("******0.exit ******\n");//退出 printf("***************************\n"); }
(2):通讯录所建立的结构体
在这里我们需要利用结构体来实现前言中通讯录功能以及联系人的信息,我们需要使用两个结构体。
代码如下:
typedef struct PeoInfo { char name[namemax]; int age; char sex[sexmax]; char tele[telemax]; char addr[addrmax]; }PeoInfo; //通讯录 typedef struct Contact { PeoInfo data[max]; int sz; }Contact;
第一个结构体 PeoInnfo 是个人信息的存储。
第二个结构体中 PeoInfo data[max] 是用来作为第一个结构体为类型的数组,sz是记录这个结构体存放联系人的个数。
(3):菜单里面功能的实现
用户需要选择菜单里面的选项来对通讯录进行一系列功能,我们在菜单里面的对功能的编号为0到6,所以我选择使用枚举的方法,将操作变成数字,然后利用switch选择语句来实现功能。
tips:在这里我也犯了个错误,因为枚举是库函数,还有宏,他们需要大写,不然后面会出现重定义。
代码如下:
enum select { EXIT, add, del, search, modify, show, sort }; test() { int input = 0; //首先要有通讯录存放的位置; Contact con; initContact(&con); do { menu(); printf("请选择:> "); scanf("%d", &input); switch(input) { case add: addContact(&con);//在data中输入 所以传con的地址 break; case del: delContact(&con); break; case search: searchContact(&con); break; case modify: modifyContact(&con); break; case show: showContact(&con); break; case sort: sortContact(&con); break; case EXIT: printf("退出通讯录\n"); break; default: printf("输入错误,请重新输入\n"); break; } } while (input); } int main() { test(); return 0; }
(4):全局变量的定义
为了后期方便我们处理数组的大小,我们可以利用宏来实现
代码如下:
#define max 100 #define namemax 20 #define sexmax 5 #define telemax 20 #define addrmax 30
2:通讯录功能的实现
(1):通讯录的初始化
刚开始我们建立了通讯录的结构体,但里面存放的是我们不需要的变量,我们需要把这个结构体初始化,以便我们操作。
初始化:我们可以使用memset函数,来进行初始化,然后sz的初始值为0,memset的头文件<string.h>。
代码如下:
void initContact(Contact* pc) { memset(pc->data, 0, sizeof(pc->data)); pc->sz = 0; }
我在通讯录菜单的时候,将结构体的命名为con,然后我们取的con的地址,然后指针接收就行。
(2):增加联系人
第一步增加联系人,我们直接创建一个关于增加联系人的函数,然后我们访问通讯录结构体里面的数组的每个元素然后输入对应的值就可以。
代码如下:
void addContact(Contact* pc) { assert(pc); if (pc->sz == max) { printf("通讯录已满,无法添加"); return; } printf("请输入名字:>"); scanf("%s", pc->data[pc->sz].name);//name 就是数组,数组名就是地址,不用地址符号 printf("请输入年龄:>"); scanf("%d", &(pc->data[pc->sz].age));//age变量 加地址符号 printf("请输入性别:>"); scanf("%s", pc->data[pc->sz].sex); printf("请输入电话:>"); scanf("%s", pc->data[pc->sz].tele); printf("请输入地址:>"); scanf("%s", pc->data[pc->sz].addr); pc->sz++; printf("成功增加联系人\n"); }
这里考虑通讯录如果已满,我们直接退出。
(3):打印通讯录
我们输入联系人的值之后就可以打印它,打印直接for循环就可以。
void showContact(const Contact* pc) { int i = 0; //打印列标题 printf("%-10s\t%-4s\t%-3s\t%-12s\t%-30s\n", "名字", "年龄", "性别", "电话", "地址"); for (i = 0; i < pc->sz; i++) { //打印数据 printf("%-10s\t%-4d\t%-3s\t%-12s\t%-30s\n",//无符号是右对齐,如果想左对齐在数字前面加-, pc->data[i].name, pc->data[i].age, pc->data[i].sex, pc->data[i].tele, pc->data[i].addr); } }
为了美观我们可以加个表名,然后宽度要和输出的一直,不然很丑哈哈哈。
(4):查找联系人
查找联系人我们也直接建立个函数就可以,因为建立的通讯录是数组,我们直接找下表就可以,然后返回下表,输出就可以,如果不是返回-1 return就可以。
代码如下:
void searchContact(const Contact* pc) { assert(pc); char name[namemax] = { 0 }; printf("请输入要查找人的名字:>"); scanf("%s", name); int pos = FindbyContact(pc, name); if (pos == -1) { printf("要查找的人不存在\n"); } else { printf("%-10s\t%-4s\t%-5s\t%-12s\t%-30s\n", "名字", "年龄", "性别", "电话", "地址"); printf("%-10s\t%-4d\t%-3s\t%-12s\t%-30s\n",//无符号是右对齐,如果想左对齐在数字前面加-, pc->data[pos].name, pc->data[pos].age, pc->data[pos].sex, pc->data[pos].tele, pc->data[pos].addr); } }
这里我重新建立一个查找函数,在后面删除 修改操作都需要查找,所以我直接建立一个查找函数,以便后续操作。
代码如下:
int FindbyContact(Contact* pc, char name[]) { int i = 0; for (i = 0; i < pc->sz; i++) { if (strcmp(pc->data[i].name, name) == 0) { return i; } } return -1; }
因为字符不可以直接比较,所以我们使用strcmo函数 如果相同返回值为零,然后返回下标值。
(5):修改联系人
修改函数我们也直接建立一个修改函数,然后利用前面写的查找函数,找到需要修改的下标,然后进行修改,。
代码如下:void modifyContact(Contact* pc) { assert(pc); char name[namemax] = { 0 }; printf("请输入修改的名字:>"); scanf("%s",name); int pos = FindbyContact(pc, name); if (pos == -1) { printf("需要修改的人不存在"); } else { printf("请输入名字:>"); scanf("%s", pc->data[pos].name);//name 就是数组,数组名就是地址,不用地址符号 printf("请输入年龄:>"); scanf("%d", &(pc->data[pos].age));//age变量 加地址符号 printf("请输入性别:>"); scanf("%s", pc->data[pos].sex); printf("请输入电话:>"); scanf("%s", pc->data[pos].tele); printf("请输入地址:>"); scanf("%s", pc->data[pos].addr); printf("成功修改联系人\n"); } }
(6):删除联系人
套路还是一样,建立删除函数,利用查找函数,找到下标,因为这个删除函数涉及到删除一个联系人,下一个联系人还需要向前移动,然后sz还需要--。
代码如下:
void delContact(Contact* pc) { if (pc->sz == 0) { printf("通讯录为空,无法删除"); return; } char name[namemax] = { 0 }; assert(pc); printf("请输入要删除人的名字:>"); scanf("%s", name); //找到要删除的人 //int i = 0; //int pos;//位置 //int flage = 0; //for (i = 0; i < pc->sz; i++) //{ // if (strcmp(pc->data[i].name, name) == 0) // { // pos = i;//删除人的下标 // flage = 1; // break; // } //} //if (flage == 0) //{ // printf("要删除的人不存在"); // return; //} int del = FindbyContact(pc, name); if (del == -1) { printf("要删除的人不存在\n"); return; } //删除坐标为del 的联系人 int i = 0; for (i = del; i < pc->sz - 1; i++)// { pc->data[i] = pc->data[i + 1]; } pc->sz--; printf("成功删除联系人\n"); }
(7):排序通讯录
排序我们将name的字母排序,我们可以使用qsort函数进行排序,上一篇文章讲过,可以参考。
代码如下:
int cmp_by_name(const char* e1, const char* e2) { return strcmp(((PeoInfo*)e1)->name, ((PeoInfo*)e2)->name); } void sortContact(Contact* pc) { assert(pc); qsort(pc->data, pc->sz, sizeof(pc->data[0]), cmp_by_name); printf("排序完成"); }
三:总结
这个通讯录主要就是结构体的一些访问,还有创建,最后我放上所有代码 供大家参考
我创建了三个工程 test. c contact.c contact.h.
test.c:
#define _CRT_SECURE_NO_WARNINGS #include "contact.h" menu() { printf("***************************\n"); printf("******1.add 2.del*******\n");//增加 删除 printf("******3.search 4.modify****\n");//查 改 printf("******5.show 6.sort******\n");//显示所有 排序 printf("******0.exit ******\n");//退出 printf("***************************\n"); } test() { int input = 0; //首先要有通讯录存放的位置; Contact con; initContact(&con); do { menu(); printf("请选择:> "); scanf("%d", &input); switch(input) { case add: addContact(&con);//在data中输入 所以传con的地址 break; case del: delContact(&con); break; case search: searchContact(&con); break; case modify: modifyContact(&con); break; case show: showContact(&con); break; case sort: sortContact(&con); break; case EXIT: printf("退出通讯录\n"); break; default: printf("输入错误,请重新输入\n"); break; } } while (input); } int main() { test(); return 0; }
contact.c:
#include"contact.h" void initContact(Contact* pc) { memset(pc->data, 0, sizeof(pc->data)); pc->sz = 0; } void addContact(Contact* pc) { assert(pc); if (pc->sz == max) { printf("通讯录已满,无法添加"); return; } printf("请输入名字:>"); scanf("%s", pc->data[pc->sz].name);//name 就是数组,数组名就是地址,不用地址符号 printf("请输入年龄:>"); scanf("%d", &(pc->data[pc->sz].age));//age变量 加地址符号 printf("请输入性别:>"); scanf("%s", pc->data[pc->sz].sex); printf("请输入电话:>"); scanf("%s", pc->data[pc->sz].tele); printf("请输入地址:>"); scanf("%s", pc->data[pc->sz].addr); pc->sz++; printf("成功增加联系人\n"); } void showContact(const Contact* pc) { int i = 0; //打印列标题 printf("%-10s\t%-4s\t%-3s\t%-12s\t%-30s\n", "名字", "年龄", "性别", "电话", "地址"); for (i = 0; i < pc->sz; i++) { //打印数据 printf("%-10s\t%-4d\t%-3s\t%-12s\t%-30s\n",//无符号是右对齐,如果想左对齐在数字前面加-, pc->data[i].name, pc->data[i].age, pc->data[i].sex, pc->data[i].tele, pc->data[i].addr); } } int FindbyContact(Contact* pc, char name[]) { int i = 0; for (i = 0; i < pc->sz; i++) { if (strcmp(pc->data[i].name, name) == 0) { return i; } } return -1; } void delContact(Contact* pc) { if (pc->sz == 0) { printf("通讯录为空,无法删除"); return; } char name[namemax] = { 0 }; assert(pc); printf("请输入要删除人的名字:>"); scanf("%s", name); //找到要删除的人 //int i = 0; //int pos;//位置 //int flage = 0; //for (i = 0; i < pc->sz; i++) //{ // if (strcmp(pc->data[i].name, name) == 0) // { // pos = i;//删除人的下标 // flage = 1; // break; // } //} //if (flage == 0) //{ // printf("要删除的人不存在"); // return; //} int del = FindbyContact(pc, name); if (del == -1) { printf("要删除的人不存在\n"); return; } //删除坐标为del 的联系人 int i = 0; for (i = del; i < pc->sz - 1; i++)// { pc->data[i] = pc->data[i + 1]; } pc->sz--; printf("成功删除联系人\n"); } void searchContact(const Contact* pc) { assert(pc); char name[namemax] = { 0 }; printf("请输入要查找人的名字:>"); scanf("%s", name); int pos = FindbyContact(pc, name); if (pos == -1) { printf("要查找的人不存在\n"); } else { printf("%-10s\t%-4s\t%-5s\t%-12s\t%-30s\n", "名字", "年龄", "性别", "电话", "地址"); printf("%-10s\t%-4d\t%-3s\t%-12s\t%-30s\n",//无符号是右对齐,如果想左对齐在数字前面加-, pc->data[pos].name, pc->data[pos].age, pc->data[pos].sex, pc->data[pos].tele, pc->data[pos].addr); } } void modifyContact(Contact* pc) { assert(pc); char name[namemax] = { 0 }; printf("请输入修改的名字:>"); scanf("%s",name); int pos = FindbyContact(pc, name); if (pos == -1) { printf("需要修改的人不存在"); } else { printf("请输入名字:>"); scanf("%s", pc->data[pos].name);//name 就是数组,数组名就是地址,不用地址符号 printf("请输入年龄:>"); scanf("%d", &(pc->data[pos].age));//age变量 加地址符号 printf("请输入性别:>"); scanf("%s", pc->data[pos].sex); printf("请输入电话:>"); scanf("%s", pc->data[pos].tele); printf("请输入地址:>"); scanf("%s", pc->data[pos].addr); printf("成功修改联系人\n"); } } int cmp_by_name(const char* e1, const char* e2) { return strcmp(((PeoInfo*)e1)->name, ((PeoInfo*)e2)->name); } void sortContact(Contact* pc) { assert(pc); qsort(pc->data, pc->sz, sizeof(pc->data[0]), cmp_by_name); printf("排序完成"); }
contact.h:
#define _CRT_SECURE_NO_WARNINGS #include<stdio.h> #include<string.h> #include<assert.h> #include<stdlib.h> #define max 100 #define namemax 20 #define sexmax 5 #define telemax 20 #define addrmax 30 enum select { EXIT, add, del, search, modify, show, sort }; typedef struct PeoInfo { char name[namemax]; int age; char sex[sexmax]; char tele[telemax]; char addr[addrmax]; }PeoInfo; //通讯录 typedef struct Contact { PeoInfo data[max]; int sz; }Contact; void initContact(Contact* pc);//初始化 void addContact(Contact* pc);//增加联系人 void showContact(const Contact* pc);//显示联系人信息 但不修改信息 可以加const void delContact(Contact* pc);//删除联系人 void searchContact(const Contact* pc);//查 void modifyContact(Contact* pc); void sortContact(Contact* pc);