引言
学会创立一个通讯录,对过往常识启动加深和坚固。
文章很长,要耐烦学完哦!
目录
引言
实战
建设文件
蕴含头文件
结构体的经常使用
通讯录
菜单
主头绪的成功
初始化函数的成功
第一个配置:参与咨询人到通讯录
第二个配置:删除咨询人的消息
第三个配置:查找指定咨询人
第四个配置:修正指定咨询人
第五个配置:打印通讯录中消息
第六个配置:排序通讯录中的内容
全体的代码成功
实战
通讯录的配置就是,记载咨询人的消息,咱们将咨询人的消息分为5个局部,区分是姓名、年龄、性别、定位器号、地址。
建设文件
咱们要将通讯录的配置成功,首先要建设1个头文件,2个源文件。
contact.h 用来申明 contact.c 中的函数, test.c 就要蕴含 contact.h ,自己的头文件如下图蕴含:
#include "contact.h"蕴含头文件
既然 test.c 蕴含自己的头文件 contact.h ,为了繁复繁难,无妨把咱们要经常使用的库函数的头文件蕴含在 contact.h 中.
contact.c 也把 contact.h 头文件蕴含,就不用再 contact.c 中再蕴含多个头文件了。
结构体的经常使用
咱们要将咨询人的5个消息贮存起来,而这5个消息的类型有不一样, 因此咱们经过结构体将它们组合在一同,
结构体的经常使用蕴含再两个源文件中, 因此咱们将结构体的定义和申明 放在contact.h头文件 中。
typedef,关键字, 影响是为一个类型创立一个新的名字。
原本上方结构体的类型是struct PeoInfo,为了将名字简化,用到了typedef关键字。
typedef struct PeoInfo {char name[100];int age;char [10];char tele[12];char addr[30]; }PeoInfo; #define MAX 100 #define MAX_NAME 20 #define MAX_SEX 10 #define MAX_TELE 12 #define MAX_ADDR 30typedef struct PeoInfo {char name[MAX_NAME];int age;char [MAX_SEX];char tele[MAX_TELE];char addr[MAX_ADDR]; }PeoInfo;通讯录
寄存在头文件contact.h
通讯录不只要蕴含上方的5个消息,5个消息蕴含在一同就是一团体的消息。创立变量count,可以记载通讯录的 操作人数,之后的打印配置,也要经常使用count来打印。
data是struct PeoInfo类型的数组。上方把struct PeoInfo简化为PeoInfo.
data是贮存每团体消息的数组,数组的每个元素代表着一团体的消息。
typedef struct Contact {PeoInfo>void 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.c
input,为键盘输入的数字,选用不同的数字代表着不同的配置。
switch语句,分支语句成功input为不同的数字,选用不同的配置,在case 前面成功这六个配置。
创立新的结构体变量要启动初始化,InitContact(&con)就是用来初始化结构体的。
之 因此用自定义函数InitContact,是为了繁复和模块化处置。
int in() {int input = 0;Contact con;//初始化通讯录:模块化初始化InitContact(&con);//只能传地址,启动修正scanf("%d",&input);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 0:printf("离申请讯录\n");break;default:printf("选用失误\n");}} while (input);return 0; }初始化函数的成功
寄存在源文件contact.c
assert用来测验pc能否为空指针,假设为空指针就会报错。 头文件<assert.h>
memset,配置是填充内存块,将num个字节的value填充到起始地址为ptr的位置。
void InitContact(Contact* pc) {assert(pc);pc->count = 0;memset(pc->data, 0, sizeof(pc->data)); }test.c要想经常使用,就要在头文件contact.h中启动申明。
void InitContact(Contact* pc);第一个配置:参与咨询人到通讯录
配置函数的成功 都会放在 contact.c 中。
assert用来测验pc能否为空指针,假设为空指针就会报错。 头文件<assert.h>
Contact* pc是传上来的struct Contact 类型的变量的地址,这里是传址调用,可以扭转原来结构体的内容。
假设count到了通讯录的最大容量,就不能参与消息了,分开函数,并收回揭示。
原始的count是0,每参与一团体的消息,count就要加1。
新的count示意的就是新咨询人的下标,经过pc->data[pc->count].name 的模式找到各个消息。
假设count曾经到达最大值,那么就间接揭示 “通讯录已满,不可参与” ,并完结函数。
函数成功
void AddContact(Contact* pc) {assert(pc);if (pc->count == MAX){printf("通讯录已满,不可参与\n");return;}printf("请输入名字:》");scanf("%s", pc->data[pc->count].name);printf("请输入年龄:》");scanf("%d", &(pc->data[pc->count].age));printf("请输入性别:>");scanf("%s", pc->data[pc->count]. );printf("请输入电话:>");scanf("%s", pc->data[pc->count].tele);printf("请输上天址:>");scanf("%s", pc->data[pc->count].addr);pc->count++; printf("参与成功\n"); }第二个配置:删除咨询人的消息
assert用来测验pc能否为空指针,假设为空指针就会报错。 头文件<assert.h>
Contact* pc是传上来的struct Contact 类型的变量的地址,这里是传址调用,可以扭转原来结构体的内容。
假设count为0,就示意通讯录外面没有内容,也就不能删除。间接揭示 "通讯录为空,没有消息可以删除" 而后分开函数。
要删除咨询人的消息,首先要查找咨询人,之后能力删除。 因此要成功查找咨询人的配置。
1.查找
2.删除
查找:FindByName函数成功
创立一个字符函数name,向name输入咱们要查找的咨询人名字,之后用name来启动对比。
首先输入要查找的咨询人名字,经过下标 i 对data启动查找,直到找到,前往 下标 ,或许前往 -1 .
名字是字符数组,用 strcmp 对启动比拟名字,库函数 strcmp 只要在相等的时刻前往0。
strcmp 的头文件: <string.h>
删除:DelContact来成功
找到要删除的咨询人的下标,咱们将它前面咨询人的消息笼罩掉要删除的咨询人的消息,就可以到达目的,而后对count减一,这样count就可以示意咨询人的个数了。
原本 最后一位的咨询人的消息不用启动操作,原本count是99,下标为99的咨询人消息笼罩到下标为98的位置,下标为99的消息不用管,count--之后,count = 98,下标为99的数据就不会被咱们经常使用到。
函数成功
static int FindByName(Contact* pc,char name[]) {assert(pc);int i = 0;for (i = 0; i < pc->count; i++){if (0 == strcmp(pc->data[i].name, name)){return i;}}return -1; } void DelContact(Contact* pc) {char name[MAX_NAME] = { 0 };assert(pc);int i = 0;if (pc->count == 0){printf("通讯录为空,没有消息可以删除\n");return;}printf("请输入要删除人的名字:>");scanf("%s", name);//删除//1.查找int pos = FindByName(pc, name);if (pos == -1){printf("要删除的人不存在\n");return;}//2.删除for (i = pos; i < pc->count; i++){pc->data[i] = pc->data[i + 1];}pc->count--; }第三个配置:查找指定咨询人
assert用来测验pc能否为空指针,假设为空指针就会报错。 头文件<assert.h>
Contact* pc是传上来的struct Contact 类型的变量的地址,这里是传址调用,可以扭转原来结构体的内容。
建设字符数组name,输入要查找的咨询人的消息。经过FindByName对name启动查找。
FindByName在上个配置成功了,当找到咨询人的消息,前往下标。没找到前往-1。
咱们用pos来对FindByName的前往值启动回收,假设pos等于-1,揭示 "要查找的人不存在"而后
函数成功
void SeachContact(Contact* pc) {assert(pc);char name[MAX_NAME] = { 0 };printf("请输入须要查找的咨询人的名字:>");scanf("%s", name);//1.查找int pos = FindByName(pc, name);if (pos == -1){printf("要查找的人不存在\n");return;}//2.打印printf("%-20s\t%-5s\t%-5s\t%-12s\t%-30s\n", "名字", "年龄", "性别", "电话", "地址");printf("%-20s\t%-5d\t%-5s\t%-12s\t%-30s\n", pc->data[pos].name,pc->data[pos].age,pc->data[pos]. ,pc->data[pos].tele,pc->data[pos].addr);}第四个配置:修正指定咨询人
assert测验空指针,name用来接纳要修正咨询人的姓名,经过 FindByName 查找咨询人,pos前往查找 结局。Contact* pc是传上来的struct Contact 类型的变量的地址,这里是传址调用,可以扭转原来结构体的内容。
找到 结局会前往下标pos,失掉下标用ps->data[pos].name就可以修正内容了。
函数成功
void ModifyContact(Contact* pc) {assert(pc);char name[MAX_NAME] = { 0 };printf("请输入须要查找的咨询人的名字:>");scanf("%s", name);//1.查找int pos = FindByName(pc, name);if (pos == -1){printf("要查找的人不存在\n");return;}printf("要修正人的消息曾经找到,接上去启动修正\n");//2.修正printf("请输入名字:》");scanf("%s", pc->data[pos].name);printf("请输入年龄:》");scanf("%d", &(pc->data[pos].age));printf("请输入性别:>");scanf("%s", pc->data[pos]. );printf("请输入电话:>");scanf("%s", pc->data[pos].tele);printf("请输上天址:>");scanf("%s", pc->data[pos].addr);printf("修正成功\n"); }第五个配置:打印通讯录中消息
assert测验空指针。为了对齐咨询人的数据,数据以最大容纳量来启动打印。
%20就是依照20个字符打印,%-20就是左对齐的意思。
函数成功
void ShowContact(const Contact* pc) {assert(pc);int i = 0;//一个汉字是两个字符printf("%-20s\t%-5s\t%-5s\t%-12s\t%-30s\n", "名字", "年龄", "性别", "电话", "地址");for (i = 0; i < pc->count; i++){printf("%-20s\t%-5d\t%-5s\t%-12s\t%-30s\n", pc->data[i].name,pc->data[i].age,pc->data[i]. ,pc->data[i].tele, pc->data[i].addr);} }第六个配置:排序通讯录中的内容
assert测验空指针。qsort是极速陈列函数。base是要排序的起始地址,pc->data示意首元素地址。num是要比拟的元素个数,通讯录有 几许团体,就比拟 几许个元素,num为pc->count。按名字排序,compar要比拟的是通讯录的名字,咱们成功cmp_peo_by_name函数,到时刻把这个函数传过去。
cmp_peo_by_name:比拟名字函数,名字是字符串,经过strcmp对字符串启动比拟。
void qsort (void* base, size_t num, size_t size,int (*compar)(const void*,const void*))函数成功
int cmp_peo_by_name(const void* e1, const void* e2) {return strcmp( ((PeoInfo*)e1)->name , ((PeoInfo*)e2)->name ); } //依照名字来排序 void SortContact(Contact* pc) {assert(pc);qsort(pc->data, pc->count, sizeof(PeoInfo), cmp_peo_by_name );printf("排序成功\n"); }全体的代码成功
test.c
#define _CRT_SECURE_NO_WARNINGS#include "contact.h"// //1.静态的版本 //2.灵活的版本 //3.文件的版本 // void 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");} int in() {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:SeachContact(&con);break;case 4:ModifyContact(&con);break;case 5:ShowContact(&con);break;case 6:SortContact(&con);break;case 0:printf("离申请讯录\n");break;default:printf("选用失误\n");}} while (input);return 0; }contact.c
#define _CRT_SECURE_NO_WARNINGS#include "contact.h" void InitContact(Contact* pc) {assert(pc);pc->count = 0;memset(pc->data, 0, sizeof(pc->data)); }void AddContact(Contact* pc) {assert(pc);if (pc->count == MAX){printf("通讯录已满,不可参与\n");return;}printf("请输入名字:》");scanf("%s", pc->data[pc->count].name);printf("请输入年龄:》");scanf("%d", &(pc->data[pc->count].age));printf("请输入性别:>");scanf("%s", pc->data[pc->count]. );printf("请输入电话:>");scanf("%s", pc->data[pc->count].tele);printf("请输上天址:>");scanf("%s", pc->data[pc->count].addr);pc->count++; printf("参与成功\n"); }void ShowContact(const Contact* pc) {assert(pc);int i = 0;//一个汉字是两个字符printf("%-20s\t%-5s\t%-5s\t%-12s\t%-30s\n", "名字", "年龄", "性别", "电话", "地址");for (i = 0; i < pc->count; i++){printf("%-20s\t%-5d\t%-5s\t%-12s\t%-30s\n", pc->data[i].name,pc->data[i].age,pc->data[i]. ,pc->data[i].tele, pc->data[i].addr);} }static int FindByName(Contact* pc,char name[]) {assert(pc);int i = 0;for (i = 0; i < pc->count; i++){if (0 == strcmp(pc->data[i].name, name)){return i;}}return -1; }void DelContact(Contact* pc) {char name[MAX_NAME] = { 0 };assert(pc);int i = 0;if (pc->count == 0){printf("通讯录为空,没有消息可以删除\n");return;}printf("请输入要删除人的名字:>");scanf("%s", name);//删除//1.查找int pos = FindByName(pc, name);if (pos == -1){printf("要删除的人不存在\n");return;}//2.删除for (i = pos; i < pc->count; i++){pc->data[i] = pc->data[i + 1];}pc->count--; }void SeachContact(Contact* pc) {assert(pc);char name[MAX_NAME] = { 0 };printf("请输入须要查找的咨询人的名字:>");scanf("%s", name);//1.查找int pos = FindByName(pc, name);if (pos == -1){printf("要查找的人不存在\n");return;}//2.打印printf("%-20s\t%-5s\t%-5s\t%-12s\t%-30s\n", "名字", "年龄", "性别", "电话", "地址");printf("%-20s\t%-5d\t%-5s\t%-12s\t%-30s\n", pc->data[pos].name,pc->data[pos].age,pc->data[pos]. ,pc->data[pos].tele,pc->data[pos].addr);}void ModifyContact(Contact* pc) {assert(pc);char name[MAX_NAME] = { 0 };printf("请输入须要查找的咨询人的名字:>");scanf("%s", name);//1.查找int pos = FindByName(pc, name);if (pos == -1){printf("要查找的人不存在\n");return;}printf("要修正人的消息曾经找到,接上去启动修正\n");//2.修正printf("请输入名字:》");scanf("%s", pc->data[pos].name);printf("请输入年龄:》");scanf("%d", &(pc->data[pos].age));printf("请输入性别:>");scanf("%s", pc->data[pos]. );printf("请输入电话:>");scanf("%s", pc->data[pos].tele);printf("请输上天址:>");scanf("%s", pc->data[pos].addr);printf("修正成功\n"); }int cmp_peo_by_name(const void* e1, const void* e2) {return strcmp( ((PeoInfo*)e1)->name , ((PeoInfo*)e2)->name ); } //依照名字来排序 void SortContact(Contact* pc) {assert(pc);qsort(pc->data, pc->count, sizeof(PeoInfo), cmp_peo_by_name );printf("排序成功\n"); }contact.h
#prag once#include <string.h> #include <stdio.h> #include <assert.h> #include <stdlib.h>#define MAX 100 #define MAX_NAME 20 #define MAX_SEX 10 #define MAX_TELE 12 #define MAX_ADDR 30//类型的申明 typedef struct PeoInfo {char name[MAX_NAME];int age;char [MAX_SEX];char tele[MAX_TELE];char addr[MAX_ADDR]; }PeoInfo;//通讯录 typedef struct Contact {PeoInfo data[MAX];int count;//记载以后通讯录中 操作人数的个数 }Contact;//初始化通讯录 void InitContact(Contact* pc);//参与咨询人到通讯录 void AddContact(Contact* pc);//打印通讯录中消息 void ShowContact(const Contact* pc);//删除咨询人的消息 void DelContact(Contact* pc);//查找指定咨询人 void SeachContact(Contact* pc);//修正指定咨询人 void ModifyContact(Contact* pc);//排序通讯录中的内容 //依照名字来排序 void SortContact(Contact* pc);