在C语言学习结束之际,谨以此篇文章来对C语言的学习告一段落。数组
纲要:ide
由于三种实现方法除了储存形式不一样,其余都基本相同,因此咱们重点论述静态版本的实现,以及它们不一样的储存方式。函数
为何叫它为静态版本呢,由于在此部分的储存是以数组来储存的,那对于各类各样的信息,咱们要拿什么数组来存放它呢?固然是结构体数组了,因此咱们来定义一个结构体来表示我的信息:学习
//采用宏的目的是方便往后修改 #define NAME_MAX 20 #define SEX_MAX 5 #define PNUM_MAX 13 #define ADDR_MAX 20 #define MAX 10 //存放我的信息的结构体 typedef struct Data { char name[NAME_MAX];//姓名 int age;//年龄 char sex[SEX_MAX];//性别 char pnum[PNUM_MAX];//电话 char addr[ADDR_MAX];//地址 } Data;
如今有了我的信息的结构体,咱们须要再来一个结构体来存放它的数组及数组内有效信息的个数,即:测试
//存放MAX个我的信息的通信录 typedef struct Contact { Data data[MAX]; int size; } Contact;
那么,准备工做作好以后,咱们就开始正式实现了,首先咱们确定是要先建立一个通信录,这时咱们再来想想,咱们就这样建立以后,咱们是否能够直接使用呢?优化
对此咱们来看一张图片:spa
咱们发现,如今它里面都放着一些随机值,因此咱们须要将其初始化一下,来方便咱们的使用:指针
void ContactInit(Contact *p) { //保证p不为NULL assert(p); //置零 memset(p->data, 0, sizeof(p->data)); p->size = 0; }
咱们再来看一下结果:调试
咱们发现,如今它内部已经被咱们置为了0;接着咱们作的就是添加联系人了,不过在此以前,咱们不妨先作一个菜单来显示咱们都有一些什么功能:code
void menu() { //打印菜单 printf("******************************************\n"); printf("****** 1.add 2.del ******\n"); printf("****** 3.search 4.modify ******\n"); printf("****** 5.show 6.sort ******\n"); printf("****** 7.help 0.exit ******\n"); printf("******************************************\n"); }
接着是咱们的帮助选项:
//打印帮助信息 void ContactHelp(Contact *p) { printf("*******************************************\n"); printf("****** add ---- 添加联系人信息 ******\n"); printf("****** del ---- 删除联系人信息 ******\n"); printf("****** search ---- 查找联系人信息 ******\n"); printf("****** modify ---- 修改联系人信息 ******\n"); printf("****** show ---- 展现联系人信息 ******\n"); printf("****** help ---- 帮助信息 ******\n"); printf("****** sort ---- 排序联系人信息 ******\n"); printf("****** exit ---- 退出通信录 ******\n"); printf("*******************************************\n"); }
以及咱们来用枚举来定义一些常量,方便在switch()结构中 来辨别它走了哪条路线:
//枚举来做为常量使得在看代码时比较清晰 enum choice { EXIT, ADD, DEL, SEARCH, MODIFY, SHOW, SORT, HELP };
以及写出咱们的选择结构:咱们采用do-while循环
void test() { Contact list;//定义一个通信录 Contact *p = &list;//赋址 //初始化 ContactInit(p); int input = 0; do { menu(); printf("请输入你的选择:> "); scanf("%d", &input); switch (input) { case ADD: ContactAdd(p); break; case DEL: ContactDel(p); break; case SEARCH: ContactSearch(p); break; case MODIFY: ContactModify(p); break; case SHOW: ContactShow(p); break; case SORT: ContactSort(p); break; case HELP: ContactHelp(p); break; case EXIT: ContactExit(p); break; default: printf("输入非法!"); } } while (input); }
这样的好处是当用户输入0时循环便本身中止,不用咱们再次去判断当用户输入0时咱们要退出的问题,接下来咱们就来填写咱们函数的内容了:
1.添加联系人
//添加联系人 void ContactAdd(Contact *p) { //断言保证p不为NULL assert(p); //若是联系人容量已经等于最大容量了 if(p->size==MAX) { printf("通信录已满,请删除一些后继续添加!\n"); return ; } Data person;//记录联系人信息 printf("请输入联系人的姓名:>"); scanf("%s", person.name); printf("请输入联系人的年龄:>"); scanf("%d", &person.age); printf("请输入联系人的性别:>"); scanf("%s", person.sex); printf("请输入联系人的电话:>"); scanf("%s", person.pnum); printf("请输入联系人的住址:>"); scanf("%s", person.addr); //将联系人信息存到通信录中 p->data[p->size] = person; p->size++; }
咱们要是观察到咱们输入的信息,最好就是把咱们所输入的信息给打印出来:
2.展现联系人
//展现联系人信息 void ContactShow(Contact *p) { if (p->size == 0) { printf("通信录中并没有一人!\n");
return ; } int i = 0; printf(" 姓名\t性别\t 年龄\t 电话\t\t地址\n"); for (i = 0; i < p->size; i++) { printf(" %-5s\t%s\t%d\t%s\t%s\n", p->data[i].name, p->data[i].sex, p->data[i].age, p->data[i].pnum, p->data[i].addr); } }
测试结果:
接下来就是删除联系人了
3.删除联系人
首先删除联系人确定须要查找信息,又由于后面的几个函数也要用到它,因此咱们单独来写一个查找模块:
//查找模块 int ContactFind(Contact *p, char *FindData) { assert(p); int i = 0; for (i = 0; i < p->size; i++) { if (strcmp(p->data[i].name, FindData) == 0) { return i;//找到就返回下标 } } return -1;//找不到就返回-1 }
删除:
//删除联系人 void ContactDel(Contact *p) { assert(p); char DelName[NAME_MAX] = {0}; printf("请输入你要删除的联系人姓名:>"); scanf("%s", DelName); int ret = ContactFind(p, DelName); if (ret == -1) { printf("通信录中并没有此人,请从新检查输入!\n"); } else { int j = 0; for (j = ret; j < p->size; j++) { //从前日后依次挪动覆盖 p->data[j] = p->data[j + 1]; } //删除完成以后,联系人个数减一 p->size--; } }
4.查找联系人信息
//查找联系人 void ContactSearch(Contact *p) { assert(p); char SearchName[NAME_MAX]; printf("请输入你要查找的联系人姓名:>\n"); scanf("%s",SearchName); //查找有无此人 int ret = ContactFind(p,SearchName); if (ret == -1) { printf("通信录中并没有此人,请从新检查输入!\n"); } else { printf("你所查找的联系人信息为:\n"); printf(" 姓名\t性别\t 年龄\t 电话\t\t地址\n"); printf(" %-5s\t%s\t%d\t%s\t%s\n", p->data[ret].name, p->data[ret].sex, p->data[ret].age, p->data[ret].pnum, p->data[ret].addr); } }
5.修改联系人信息
//修改联系人信息 void ContactModify(Contact *p) { assert(p); char ModifyName[NAME_MAX]; printf("请输入你要修改的联系人姓名:>"); scanf("%s",ModifyName); int ret = ContactFind(p,ModifyName); if (ret == -1) { printf("通信录中并没有此人,请从新检查输入!\n"); } else { Data person;//记录联系人信息 printf("请输入联系人的姓名:>"); scanf("%s", person.name); printf("请输入联系人的年龄:>"); scanf("%d", &person.age); printf("请输入联系人的性别:>"); scanf("%s", person.sex); printf("请输入联系人的电话:>"); scanf("%s", person.pnum); printf("请输入联系人的住址:>"); scanf("%s", person.addr); //将联系人信息存到通信录中 p->data[ret] = person; } }
6.排序联系人 --- 咱们使用 qsort 来排序
enum sort_by { NAME=1, SEX, AGE, PNUM, ADDR };
void sort_menu() { printf(" SORT_MENU \n"); printf("******************************\n"); printf("**** 1.name ****\n"); printf("**** 2.sex ****\n"); printf("**** 3.age ****\n"); printf("**** 4.pnum ****\n"); printf("**** 5.addr ****\n"); printf("******************************\n"); } int sort_by_name(const void *s1, const void *s2) { return strcmp(((Data *) s1)->name, ((Data *) s2)->name); } int sort_by_sex(const void *s1, const void *s2) { return strcmp(((Data *) s1)->sex, ((Data *) s2)->sex); } int sort_by_age(const void *s1, const void *s2) { return ((Data *) s1)->age - ((Data *) s2)->age; } int sort_by_pnum(const void *s1, const void *s2) { return strcmp(((Data *) s1)->pnum, ((Data *) s2)->pnum); } int sort_by_addr(const void *s1, const void *s2) { return strcmp(((Data *) s1)->addr, ((Data *) s2)->addr); } //排序联系人 void ContactSort(Contact *p) { assert(p); int choice; sort_menu(); printf("请选择排序的参考量:>"); scanf("%d", &choice); switch (choice) { case NAME: qsort(p->data, p->size, sizeof(Data), sort_by_name); break; case SEX: qsort(p->data, p->size, sizeof(Data), sort_by_sex); break; case AGE: qsort(p->data, p->size, sizeof(Data), sort_by_age); break; case PNUM: qsort(p->data, p->size, sizeof(Data), sort_by_pnum); break; case ADDR: qsort(p->data, p->size, sizeof(Data), sort_by_addr); break; default: printf("输入有误,请检查输入!\n"); } }
到这,咱们的静态通信录就完了,可是咱们仍可对用户操做优化一下,如:及时的清屏等,以及暂停:
例:
do { menu(); printf("请输入你的选择:>"); scanf("%d", &input); system("cls"); switch (input) { case QUIT: printf("退出通信录!\n"); break; case ADD: add(p); system("pause"); system("cls"); break; case DEL: del(p); system("pause"); system("cls"); break; case SEARCH: search(p); system("pause"); system("cls"); break; case MODIFY: modify(p); system("pause"); system("cls"); break; case SHOW: show(p); system("pause"); system("cls"); break; case SORT: sort(p); system("pause"); system("cls"); break; case HELP: help(); system("pause"); system("cls"); break; default: printf("非法输入,请检查输入!\n"); system("pause"); system("cls"); break; } } while (input);
这样咱们的界面看起来就干净多了,可是有没有发现,咱们为了达到这个效果,咱们写了不少重复的代码!
那这样咱们应该怎么办呢 --- 还记得咱们以前所提到的函数指针数组吗?
void test2() { Contact list;//定义一个通信录 Contact *p = &list;//赋址 //初始化 ContactInit(p); //用一个函数指针数组来存放函数指针 void (*fun[])(Contact *) ={ContactExit, ContactAdd, ContactDel, ContactSearch, ContactModify, ContactShow, ContactSort, ContactHelp}; int input = 0;//存放用户选择的信息 do{ menu(); printf("请输入你的选择:>"); scanf("%d", &input); system("cls"); if(input>=0&&input<=sizeof(fun)) { fun[input](p); system("cls"); } else { system("cls"); printf("输入非法,请检查输入!\n"); } }while(input); }
这样是否是代码就少了不少!
因此完整代码以下:
//确保文件只包含一次 #ifndef CONTACT_CONTACT_H #define CONTACT_CONTACT_H #include <stdio.h> #include <string.h> #include <errno.h> #include <stdlib.h> #include <assert.h> //采用宏的目的是方便往后修改 #define NAME_MAX 20 #define SEX_MAX 8 #define PNUM_MAX 13 #define ADDR_MAX 20 #define MAX 10 //存放我的信息的结构体 typedef struct Data { char name[NAME_MAX];//姓名 int age;//年龄 char sex[SEX_MAX];//性别 char pnum[PNUM_MAX];//电话 char addr[ADDR_MAX];//地址 } Data; //存放MAX个我的信息的通信录 typedef struct Contact { Data data[MAX]; int size; } Contact; //枚举来做为常量使得在看代码时比较清晰 enum choice { EXIT, ADD, DEL, SEARCH, MODIFY, SHOW, SORT, HELP }; enum sort_by { NAME=1, SEX, AGE, PNUM, ADDR }; //初始化通信录 void ContactInit(Contact *p); //添加联系人 void ContactAdd(Contact* p); //删除联系人 void ContactDel(Contact* p); //查找联系人 void ContactSearch(Contact* p); //修改联系人信息 void ContactModify(Contact* p); //展现联系人信息 void ContactShow(Contact* p); //排序联系人 void ContactSort(Contact* p); //打印帮助 void ContactHelp(Contact* p); //退出通信录 void ContactExit(Contact* p); #endif //CONTACT_CONTACT_H
#include "Contact.h" // 强调!!! //调试请加setbuf(stdout,NULL)!!! //查找模块 int ContactFind(Contact *p, char *FindData) { assert(p); int i = 0; for (i = 0; i < p->size; i++) { if (strcmp(p->data[i].name, FindData) == 0) { return i;//找到就返回下标 } } return -1;//找不到就返回-1 } void ContactInit(Contact *p) { //保证p不为NULL assert(p); //置零 memset(p->data, 0, sizeof(p->data)); p->size = 0; } //添加联系人 void ContactAdd(Contact *p) { //断言保证p不为NULL assert(p); //若是联系人容量已经等于最大容量了 if (p->size == MAX) { printf("通信录已满,请删除一些后继续添加!\n"); return; } Data person;//记录联系人信息 printf("请输入联系人的姓名:>"); scanf("%s", person.name); printf("请输入联系人的年龄:>"); scanf("%d", &person.age); printf("请输入联系人的性别:>"); scanf("%s", person.sex); printf("请输入联系人的电话:>"); scanf("%s", person.pnum); printf("请输入联系人的住址:>"); scanf("%s", person.addr); //将联系人信息存到通信录中 p->data[p->size] = person; p->size++; } //删除联系人 void ContactDel(Contact *p) { assert(p); char DelName[NAME_MAX] = {0}; printf("请输入你要删除的联系人姓名:>"); scanf("%s", DelName); int ret = ContactFind(p, DelName); if (ret == -1) { printf("通信录中并没有此人,请从新检查输入!\n"); } else { int j = 0; for (j = ret; j < p->size; j++) { //从前日后依次挪动覆盖 p->data[j] = p->data[j + 1]; } //删除完成以后,联系人个数减一 p->size--; } } //查找联系人 void ContactSearch(Contact *p) { assert(p); char SearchName[NAME_MAX]; printf("请输入你要查找的联系人姓名:>"); scanf("%s", SearchName); //查找有无此人 int ret = ContactFind(p, SearchName); if (ret == -1) { printf("通信录中并没有此人,请从新检查输入!\n"); } else { printf("你所查找的联系人信息为:\n"); printf(" 姓名\t性别\t 年龄\t 电话\t\t地址\n"); printf(" %-5s\t%s\t%d\t%s\t%s\n", p->data[ret].name, p->data[ret].sex, p->data[ret].age, p->data[ret].pnum, p->data[ret].addr); } } //修改联系人信息 void ContactModify(Contact *p) { assert(p); char ModifyName[NAME_MAX]; printf("请输入你要修改的联系人姓名:>"); scanf("%s", ModifyName); int ret = ContactFind(p, ModifyName); if (ret == -1) { printf("通信录中并没有此人,请从新检查输入!\n"); } else { Data person;//记录联系人信息 printf("请输入联系人的姓名:>"); scanf("%s", person.name); printf("请输入联系人的年龄:>"); scanf("%d", &person.age); printf("请输入联系人的性别:>"); scanf("%s", person.sex); printf("请输入联系人的电话:>"); scanf("%s", person.pnum); printf("请输入联系人的住址:>"); scanf("%s", person.addr); //将联系人信息存到通信录中 p->data[ret] = person; } } //展现联系人信息 void ContactShow(Contact *p) { if (p->size == 0) { printf("通信录中并没有一人!\n"); return; } int i = 0; printf(" 姓名\t性别\t 年龄\t 电话\t\t地址\n"); for (i = 0; i < p->size; i++) { printf(" %-5s\t%s\t%d\t%s\t%s\n", p->data[i].name, p->data[i].sex, p->data[i].age, p->data[i].pnum, p->data[i].addr); } } void sort_menu() { printf(" SORT_MENU \n"); printf("******************************\n"); printf("**** 1.name ****\n"); printf("**** 2.sex ****\n"); printf("**** 3.age ****\n"); printf("**** 4.pnum ****\n"); printf("**** 5.addr ****\n"); printf("******************************\n"); } int sort_by_name(const void *s1, const void *s2) { return strcmp(((Data *) s1)->name, ((Data *) s2)->name); } int sort_by_sex(const void *s1, const void *s2) { return strcmp(((Data *) s1)->sex, ((Data *) s2)->sex); } int sort_by_age(const void *s1, const void *s2) { return ((Data *) s1)->age - ((Data *) s2)->age; } int sort_by_pnum(const void *s1, const void *s2) { return strcmp(((Data *) s1)->pnum, ((Data *) s2)->pnum); } int sort_by_addr(const void *s1, const void *s2) { return strcmp(((Data *) s1)->addr, ((Data *) s2)->addr); } //排序联系人 void ContactSort(Contact *p) { assert(p); int choice; sort_menu(); printf("请选择排序的参考量:>"); scanf("%d", &choice); switch (choice) { case NAME: qsort(p->data, p->size, sizeof(Data), sort_by_name); break; case SEX: qsort(p->data, p->size, sizeof(Data), sort_by_sex); break; case AGE: qsort(p->data, p->size, sizeof(Data), sort_by_age); break; case PNUM: qsort(p->data, p->size, sizeof(Data), sort_by_pnum); break; case ADDR: qsort(p->data, p->size, sizeof(Data), sort_by_addr); break; default: printf("输入有误,请检查输入!\n"); } } //打印帮助信息 void ContactHelp(Contact *p) { printf("*******************************************\n"); printf("****** add ---- 添加联系人信息 ******\n"); printf("****** del ---- 删除联系人信息 ******\n"); printf("****** search ---- 查找联系人信息 ******\n"); printf("****** modify ---- 修改联系人信息 ******\n"); printf("****** show ---- 展现联系人信息 ******\n"); printf("****** help ---- 帮助信息 ******\n"); printf("****** sort ---- 排序联系人信息 ******\n"); printf("****** exit ---- 退出通信录 ******\n"); printf("*******************************************\n"); } //退出通信录 void ContactExit(Contact *p) { printf("exit !\n"); }
#include "Contact.h" void menu() { //打印菜单 printf("******************************************\n"); printf("****** 1.add 2.del ******\n"); printf("****** 3.search 4.modify ******\n"); printf("****** 5.show 6.sort ******\n"); printf("****** 7.help 0.exit ******\n"); printf("******************************************\n"); } void test() { Contact list;//定义一个通信录 Contact *p = &list;//赋址 //初始化 ContactInit(p); int input = 0;//存放用户选择的信息 do { menu(); printf("请输入你的选择:>"); scanf("%d", &input); switch (input) { case ADD: ContactAdd(p); break; case DEL: ContactDel(p); break; case SEARCH: ContactSearch(p); break; case MODIFY: ContactModify(p); break; case SHOW: ContactShow(p); break; case SORT: ContactSort(p); break; case HELP: ContactHelp(p); break; case EXIT: ContactExit(p); break; default: printf("输入非法!\n"); } } while (input); } void test2() { Contact list;//定义一个通信录 Contact *p = &list;//赋址 //初始化 ContactInit(p); //用一个函数指针数组来存放函数指针 void (*fun[])(Contact *) ={ContactExit, ContactAdd, ContactDel, ContactSearch, ContactModify, ContactShow, ContactSort, ContactHelp}; int input = 0;//存放用户选择的信息 do{ menu(); printf("请输入你的选择:>"); scanf("%d", &input); system("cls"); if(input>=0&&input<=sizeof(fun)) { fun[input](p); system("cls"); } else { system("cls"); printf("输入非法,请检查输入!\n"); } }while(input); } int main() { //test(); test2(); return 0; }
动态实现的问题主要在于它的容量再也不是一变不变的,而是可随着咱们的数据量来变化的,因此在咱们原来定义的Contact结构体就要微微改变一下了:
typedef struct Contact { Data* data;//存放数据 int size;//有效数据的个数 int capacity;//容量的大小 } Contact;
初始化函数也要改改:
//初始化 --- 动态 void ContactInit(Contact *p) { assert(p); p->data=NULL; p->size=0; p->capacity=1; }
那么这样,添加函数也有必定的变化:
//检查容量函数 void CheckCapacity(Contact *p) { assert(p); //若是联系人个数为0或与容量相同,就须要扩容 if (p->size == 0 || p->size == p->capacity) { //动态内存开辟 Data *ptr = (Data *) realloc(p->data, sizeof(Data) * p->capacity * 2); if (ptr == NULL)//开辟失败 { //报错 perror("CHECK CAPACITY ERROE !\n"); exit(-1); } //开辟成功,从新赋值 p->data = ptr; //扩容以后,容量也相应扩大 p->capacity *= 2; } //反之什么都不须要干 } //添加联系人 --- 动态 void ContactAdd(Contact *p) { //断言保证p不为NULL assert(p); //若是联系人个数等于容量,或联系人个数等于0,这时咱们就须要扩容了,咱们来使用一个函数来干这事 CheckCapacity(p); Data person;//记录联系人信息 printf("请输入联系人的姓名:>"); scanf("%s", person.name); printf("请输入联系人的年龄:>"); scanf("%d", &person.age); printf("请输入联系人的性别:>"); scanf("%s", person.sex); printf("请输入联系人的电话:>"); scanf("%s", person.pnum); printf("请输入联系人的住址:>"); scanf("%s", person.addr); //将联系人信息存到通信录中 p->data[p->size] = person; p->size++; }
最后咱们还要记得释放咱们开辟的内存 --- 退出
//退出通信录 --- 动态 void ContactExit(Contact *p) { //释放咱们开辟的内存 free(p->data); printf("exit !\n"); }
动态通信录的修改就只有这些:
完整代码展现:
//确保文件只包含一次 #ifndef CONTACT_CONTACT_H #define CONTACT_CONTACT_H #include <stdio.h> #include <string.h> #include <errno.h> #include <stdlib.h> #include <assert.h> //采用宏的目的是方便往后修改 #define NAME_MAX 20 #define SEX_MAX 8 #define PNUM_MAX 13 #define ADDR_MAX 20 #define MAX 10 //存放我的信息的结构体 typedef struct Data { char name[NAME_MAX];//姓名 int age;//年龄 char sex[SEX_MAX];//性别 char pnum[PNUM_MAX];//电话 char addr[ADDR_MAX];//地址 } Data; /* //存放MAX个我的信息的通信录 --- 静态 typedef struct Contact { Data data[MAX]; int size; } Contact; */ //存放MAX个我的信息的通信录 --- 动态 typedef struct Contact { Data* data;//存放数据 int size;//有效数据的个数 int capacity;//容量的大小 } Contact; //枚举来做为常量使得在看代码时比较清晰 enum choice { EXIT, ADD, DEL, SEARCH, MODIFY, SHOW, SORT, HELP }; enum sort_by { NAME=1, SEX, AGE, PNUM, ADDR }; //初始化通信录 void ContactInit(Contact *p); //添加联系人 void ContactAdd(Contact* p); //删除联系人 void ContactDel(Contact* p); //查找联系人 void ContactSearch(Contact* p); //修改联系人信息 void ContactModify(Contact* p); //展现联系人信息 void ContactShow(Contact* p); //排序联系人 void ContactSort(Contact* p); //打印帮助 void ContactHelp(Contact* p); //退出通信录 void ContactExit(Contact* p); #endif //CONTACT_CONTACT_H
#include "Contact.h" // 强调!!! //调试请加setbuf(stdout,NULL)!!! //查找模块 int ContactFind(Contact *p, char *FindData) { assert(p); int i = 0; for (i = 0; i < p->size; i++) { if (strcmp(p->data[i].name, FindData) == 0) { return i;//找到就返回下标 } } return -1;//找不到就返回-1 } /* //初始化 --- 静态 void ContactInit(Contact *p) { //保证p不为NULL assert(p); //置零 memset(p->data, 0, sizeof(p->data)); p->size = 0; } */ //初始化 --- 动态 void ContactInit(Contact *p) { assert(p); p->data = NULL; p->size = 0; p->capacity = 1; } /*//添加联系人 --- 静态 void ContactAdd(Contact *p) { //断言保证p不为NULL assert(p); //若是联系人容量已经等于最大容量了 if (p->size == MAX) { printf("通信录已满,请删除一些后继续添加!\n"); return; } Data person;//记录联系人信息 printf("请输入联系人的姓名:>"); scanf("%s", person.name); printf("请输入联系人的年龄:>"); scanf("%d", &person.age); printf("请输入联系人的性别:>"); scanf("%s", person.sex); printf("请输入联系人的电话:>"); scanf("%s", person.pnum); printf("请输入联系人的住址:>"); scanf("%s", person.addr); //将联系人信息存到通信录中 p->data[p->size] = person; p->size++; }*/ //检查容量函数 void CheckCapacity(Contact *p) { assert(p); //若是联系人个数为0或与容量相同,就须要扩容 if (p->size == 0 || p->size == p->capacity) { //动态内存开辟 Data *ptr = (Data *) realloc(p->data, sizeof(Data) * p->capacity * 2); if (ptr == NULL)//开辟失败 { //报错 perror("CHECK CAPACITY ERROE !\n"); exit(-1); } //开辟成功,从新赋值 p->data = ptr; //扩容以后,容量也相应扩大 p->capacity *= 2; } //反之什么都不须要干 } //添加联系人 --- 动态 void ContactAdd(Contact *p) { //断言保证p不为NULL assert(p); //若是联系人个数等于容量,或联系人个数等于0,这时咱们就须要扩容了,咱们来使用一个函数来干这事 CheckCapacity(p); Data person;//记录联系人信息 printf("请输入联系人的姓名:>"); scanf("%s", person.name); printf("请输入联系人的年龄:>"); scanf("%d", &person.age); printf("请输入联系人的性别:>"); scanf("%s", person.sex); printf("请输入联系人的电话:>"); scanf("%s", person.pnum); printf("请输入联系人的住址:>"); scanf("%s", person.addr); //将联系人信息存到通信录中 p->data[p->size] = person; p->size++; } //删除联系人 void ContactDel(Contact *p) { assert(p); char DelName[NAME_MAX] = {0}; printf("请输入你要删除的联系人姓名:>"); scanf("%s", DelName); int ret = ContactFind(p, DelName); if (ret == -1) { printf("通信录中并没有此人,请从新检查输入!\n"); } else { int j = 0; for (j = ret; j < p->size; j++) { //从前日后依次挪动覆盖 p->data[j] = p->data[j + 1]; } //删除完成以后,联系人个数减一 p->size--; } } //查找联系人 void ContactSearch(Contact *p) { assert(p); char SearchName[NAME_MAX]; printf("请输入你要查找的联系人姓名:>"); scanf("%s", SearchName); //查找有无此人 int ret = ContactFind(p, SearchName); if (ret == -1) { printf("通信录中并没有此人,请从新检查输入!\n"); } else { printf("你所查找的联系人信息为:\n"); printf(" 姓名\t性别\t 年龄\t 电话\t\t地址\n"); printf(" %-5s\t%s\t%d\t%s\t%s\n", p->data[ret].name, p->data[ret].sex, p->data[ret].age, p->data[ret].pnum, p->data[ret].addr); } } //修改联系人信息 void ContactModify(Contact *p) { assert(p); char ModifyName[NAME_MAX]; printf("请输入你要修改的联系人姓名:>"); scanf("%s", ModifyName); int ret = ContactFind(p, ModifyName); if (ret == -1) { printf("通信录中并没有此人,请从新检查输入!\n"); } else { Data person;//记录联系人信息 printf("请输入联系人的姓名:>"); scanf("%s", person.name); printf("请输入联系人的年龄:>"); scanf("%d", &person.age); printf("请输入联系人的性别:>"); scanf("%s", person.sex); printf("请输入联系人的电话:>"); scanf("%s", person.pnum); printf("请输入联系人的住址:>"); scanf("%s", person.addr); //将联系人信息存到通信录中 p->data[ret] = person; } } //展现联系人信息 void ContactShow(Contact *p) { if (p->size == 0) { printf("通信录中并没有一人!\n"); return; } int i = 0; printf(" 姓名\t性别\t 年龄\t 电话\t\t地址\n"); for (i = 0; i < p->size; i++) { printf(" %-5s\t%s\t%d\t%s\t%s\n", p->data[i].name, p->data[i].sex, p->data[i].age, p->data[i].pnum, p->data[i].addr); } } void sort_menu() { printf(" SORT_MENU \n"); printf("******************************\n"); printf("**** 1.name ****\n"); printf("**** 2.sex ****\n"); printf("**** 3.age ****\n"); printf("**** 4.pnum ****\n"); printf("**** 5.addr ****\n"); printf("******************************\n"); } int sort_by_name(const void *s1, const void *s2) { return strcmp(((Data *) s1)->name, ((Data *) s2)->name); } int sort_by_sex(const void *s1, const void *s2) { return strcmp(((Data *) s1)->sex, ((Data *) s2)->sex); } int sort_by_age(const void *s1, const void *s2) { return ((Data *) s1)->age - ((Data *) s2)->age; } int sort_by_pnum(const void *s1, const void *s2) { return strcmp(((Data *) s1)->pnum, ((Data *) s2)->pnum); } int sort_by_addr(const void *s1, const void *s2) { return strcmp(((Data *) s1)->addr, ((Data *) s2)->addr); } //排序联系人 void ContactSort(Contact *p) { assert(p); int choice; sort_menu(); printf("请选择排序的参考量:>"); scanf("%d", &choice); switch (choice) { case NAME: qsort(p->data, p->size, sizeof(Data), sort_by_name); break; case SEX: qsort(p->data, p->size, sizeof(Data), sort_by_sex); break; case AGE: qsort(p->data, p->size, sizeof(Data), sort_by_age); break; case PNUM: qsort(p->data, p->size, sizeof(Data), sort_by_pnum); break; case ADDR: qsort(p->data, p->size, sizeof(Data), sort_by_addr); break; default: printf("输入有误,请检查输入!\n"); } } //打印帮助信息 void ContactHelp(Contact *p) { printf("*******************************************\n"); printf("****** add ---- 添加联系人信息 ******\n"); printf("****** del ---- 删除联系人信息 ******\n"); printf("****** search ---- 查找联系人信息 ******\n"); printf("****** modify ---- 修改联系人信息 ******\n"); printf("****** show ---- 展现联系人信息 ******\n"); printf("****** help ---- 帮助信息 ******\n"); printf("****** sort ---- 排序联系人信息 ******\n"); printf("****** exit ---- 退出通信录 ******\n"); printf("*******************************************\n"); } /*//退出通信录 void ContactExit(Contact *p) { printf("exit !\n"); }*/ //退出通信录 --- 动态 void ContactExit(Contact *p) { //释放咱们开辟的内存 free(p->data); printf("exit !\n"); }
#include "Contact.h" void menu() { //打印菜单 printf("******************************************\n"); printf("****** 1.add 2.del ******\n"); printf("****** 3.search 4.modify ******\n"); printf("****** 5.show 6.sort ******\n"); printf("****** 7.help 0.exit ******\n"); printf("******************************************\n"); } void test() { Contact list;//定义一个通信录 Contact *p = &list;//赋址 //初始化 ContactInit(p); int input = 0;//存放用户选择的信息 do { menu(); printf("请输入你的选择:>"); scanf("%d", &input); switch (input) { case ADD: ContactAdd(p); break; case DEL: ContactDel(p); break; case SEARCH: ContactSearch(p); break; case MODIFY: ContactModify(p); break; case SHOW: ContactShow(p); break; case SORT: ContactSort(p); break; case HELP: ContactHelp(p); break; case EXIT: ContactExit(p); break; default: printf("输入非法!\n"); } } while (input); } void test2() { Contact list;//定义一个通信录 Contact *p = &list;//赋址 //初始化 ContactInit(p); //用一个函数指针数组来存放函数指针 void (*fun[])(Contact *) ={ContactExit, ContactAdd, ContactDel, ContactSearch, ContactModify, ContactShow, ContactSort, ContactHelp}; int input = 0;//存放用户选择的信息 do{ menu(); printf("请输入你的选择:>"); scanf("%d", &input); if(input>=0&&input<=sizeof(fun)) { //system("cls"); fun[input](p); } else { system("cls"); printf("输入非法,请检查输入!\n"); } }while(input); } int main() { //test(); test2(); return 0; } #include "Contact.h" void menu() { //打印菜单 printf("******************************************\n"); printf("****** 1.add 2.del ******\n"); printf("****** 3.search 4.modify ******\n"); printf("****** 5.show 6.sort ******\n"); printf("****** 7.help 0.exit ******\n"); printf("******************************************\n"); } void test() { Contact list;//定义一个通信录 Contact *p = &list;//赋址 //初始化 ContactInit(p); int input = 0;//存放用户选择的信息 do { menu(); printf("请输入你的选择:>"); scanf("%d", &input); switch (input) { case ADD: ContactAdd(p); break; case DEL: ContactDel(p); break; case SEARCH: ContactSearch(p); break; case MODIFY: ContactModify(p); break; case SHOW: ContactShow(p); break; case SORT: ContactSort(p); break; case HELP: ContactHelp(p); break; case EXIT: ContactExit(p); break; default: printf("输入非法!\n"); } } while (input); } void test2() { Contact list;//定义一个通信录 Contact *p = &list;//赋址 //初始化 ContactInit(p); //用一个函数指针数组来存放函数指针 void (*fun[])(Contact *) ={ContactExit, ContactAdd, ContactDel, ContactSearch, ContactModify, ContactShow, ContactSort, ContactHelp}; int input = 0;//存放用户选择的信息 do{ menu(); printf("请输入你的选择:>"); scanf("%d", &input); if(input>=0&&input<=sizeof(fun)) { //system("cls"); fun[input](p); } else { system("cls"); printf("输入非法,请检查输入!\n"); } }while(input); } int main() { //test(); test2(); return 0; }
在这个里面,咱们只需在初始化时进行文件的读取及关闭时文件的保存:
初始化:
//从文件载入信息 void Lodging(Contact *p) { assert(p); //打开一文件 FILE *fp = fopen("../Contact.dat", "ab");//若是不存在就建立,存在就追加 if (fp == NULL) { perror("FILE: Ab"); exit(-1); } fclose(fp);//关闭文件,咱们这一步只是为了确保文件存在 //打开一文件 fp=fopen("../Contact.dat","rb"); if (fp == NULL) { perror("FILE: Rb"); exit(-1); } Data temp;//将读入的信息存入temp中 while(fread(&temp, sizeof(Data),1,fp)) { //检查容量 CheckCapacity(p); //赋值 p->data[p->size]=temp; p->size++; } fclose(fp);//关闭文件 } //初始化 --- 带文件 void ContactInit(Contact *p) { assert(p); p->data = NULL; p->size = 0; p->capacity = 1; Lodging(p); }
结束时保存:
void Save(Contact* p) { assert(p); FILE* fp =fopen("../Contact.dat","wb"); int i =0; for(i=0;i<p->size;i++) { fwrite(p->data+i, sizeof(Data),1,fp); } fclose(fp); } //退出通信录 --- 带文件 void ContactExit(Contact *p) { //保存置文件 Save(p); //释放咱们开辟的内存 free(p->data); printf("exit !\n"); }
除此以外,其余都与动态通信录相同
完整代码:
//确保文件只包含一次 #ifndef CONTACT_CONTACT_H #define CONTACT_CONTACT_H #include <stdio.h> #include <string.h> #include <errno.h> #include <stdlib.h> #include <assert.h> //采用宏的目的是方便往后修改 #define NAME_MAX 20 #define SEX_MAX 8 #define PNUM_MAX 13 #define ADDR_MAX 20 #define MAX 10 //存放我的信息的结构体 typedef struct Data { char name[NAME_MAX];//姓名 int age;//年龄 char sex[SEX_MAX];//性别 char pnum[PNUM_MAX];//电话 char addr[ADDR_MAX];//地址 } Data; /* //存放MAX个我的信息的通信录 --- 静态 typedef struct Contact { Data data[MAX]; int size; } Contact; */ //存放MAX个我的信息的通信录 --- 动态 typedef struct Contact { Data* data;//存放数据 int size;//有效数据的个数 int capacity;//容量的大小 } Contact; //枚举来做为常量使得在看代码时比较清晰 enum choice { EXIT, ADD, DEL, SEARCH, MODIFY, SHOW, SORT, HELP }; enum sort_by { NAME=1, SEX, AGE, PNUM, ADDR }; //初始化通信录 void ContactInit(Contact *p); //添加联系人 void ContactAdd(Contact* p); //删除联系人 void ContactDel(Contact* p); //查找联系人 void ContactSearch(Contact* p); //修改联系人信息 void ContactModify(Contact* p); //展现联系人信息 void ContactShow(Contact* p); //排序联系人 void ContactSort(Contact* p); //打印帮助 void ContactHelp(Contact* p); //退出通信录 void ContactExit(Contact* p); //检查容量函数 void CheckCapacity(Contact *p); #endif //CONTACT_CONTACT_H
#include "Contact.h" // 强调!!! //调试请加setbuf(stdout,NULL)!!! //查找模块 int ContactFind(Contact *p, char *FindData) { assert(p); int i = 0; for (i = 0; i < p->size; i++) { if (strcmp(p->data[i].name, FindData) == 0) { return i;//找到就返回下标 } } return -1;//找不到就返回-1 } /* //初始化 --- 静态 void ContactInit(Contact *p) { //保证p不为NULL assert(p); //置零 memset(p->data, 0, sizeof(p->data)); p->size = 0; } */ /* //初始化 --- 动态 void ContactInit(Contact *p) { assert(p); p->data = NULL; p->size = 0; p->capacity = 1; } */ //从文件载入信息 void Lodging(Contact *p) { assert(p); //打开一文件 FILE *fp = fopen("../Contact.dat", "ab");//若是不存在就建立,存在就追加 if (fp == NULL) { perror("FILE: Ab"); exit(-1); } fclose(fp);//关闭文件,咱们这一步只是为了确保文件存在 //打开一文件 fp=fopen("../Contact.dat","rb"); if (fp == NULL) { perror("FILE: Rb"); exit(-1); } Data temp;//将读入的信息存入temp中 while(fread(&temp, sizeof(Data),1,fp)) { //检查容量 CheckCapacity(p); //赋值 p->data[p->size]=temp; p->size++; } fclose(fp);//关闭文件 } //初始化 --- 带文件 void ContactInit(Contact *p) { assert(p); p->data = NULL; p->size = 0; p->capacity = 1; Lodging(p); } /*//添加联系人 --- 静态 void ContactAdd(Contact *p) { //断言保证p不为NULL assert(p); //若是联系人容量已经等于最大容量了 if (p->size == MAX) { printf("通信录已满,请删除一些后继续添加!\n"); return; } Data person;//记录联系人信息 printf("请输入联系人的姓名:>"); scanf("%s", person.name); printf("请输入联系人的年龄:>"); scanf("%d", &person.age); printf("请输入联系人的性别:>"); scanf("%s", person.sex); printf("请输入联系人的电话:>"); scanf("%s", person.pnum); printf("请输入联系人的住址:>"); scanf("%s", person.addr); //将联系人信息存到通信录中 p->data[p->size] = person; p->size++; }*/ //检查容量函数 void CheckCapacity(Contact *p) { assert(p); //若是联系人个数为0或与容量相同,就须要扩容 if (p->size == 0 || p->size == p->capacity) { //动态内存开辟 Data *ptr = (Data *) realloc(p->data, sizeof(Data) * p->capacity * 2); if (ptr == NULL)//开辟失败 { //报错 perror("CHECK CAPACITY ERROE !\n"); exit(-1); } //开辟成功,从新赋值 p->data = ptr; //扩容以后,容量也相应扩大 p->capacity *= 2; } //反之什么都不须要干 } //添加联系人 --- 动态 void ContactAdd(Contact *p) { //断言保证p不为NULL assert(p); //若是联系人个数等于容量,或联系人个数等于0,这时咱们就须要扩容了,咱们来使用一个函数来干这事 CheckCapacity(p); Data person;//记录联系人信息 printf("请输入联系人的姓名:>"); scanf("%s", person.name); printf("请输入联系人的年龄:>"); scanf("%d", &person.age); printf("请输入联系人的性别:>"); scanf("%s", person.sex); printf("请输入联系人的电话:>"); scanf("%s", person.pnum); printf("请输入联系人的住址:>"); scanf("%s", person.addr); //将联系人信息存到通信录中 p->data[p->size] = person; p->size++; } //删除联系人 void ContactDel(Contact *p) { assert(p); char DelName[NAME_MAX] = {0}; printf("请输入你要删除的联系人姓名:>"); scanf("%s", DelName); int ret = ContactFind(p, DelName); if (ret == -1) { printf("通信录中并没有此人,请从新检查输入!\n"); } else { int j = 0; for (j = ret; j < p->size; j++) { //从前日后依次挪动覆盖 p->data[j] = p->data[j + 1]; } //删除完成以后,联系人个数减一 p->size--; } } //查找联系人 void ContactSearch(Contact *p) { assert(p); char SearchName[NAME_MAX]; printf("请输入你要查找的联系人姓名:>"); scanf("%s", SearchName); //查找有无此人 int ret = ContactFind(p, SearchName); if (ret == -1) { printf("通信录中并没有此人,请从新检查输入!\n"); } else { printf("你所查找的联系人信息为:\n"); printf(" 姓名\t性别\t 年龄\t 电话\t\t地址\n"); printf(" %-5s\t%s\t%d\t%s\t%s\n", p->data[ret].name, p->data[ret].sex, p->data[ret].age, p->data[ret].pnum, p->data[ret].addr); } } //修改联系人信息 void ContactModify(Contact *p) { assert(p); char ModifyName[NAME_MAX]; printf("请输入你要修改的联系人姓名:>"); scanf("%s", ModifyName); int ret = ContactFind(p, ModifyName); if (ret == -1) { printf("通信录中并没有此人,请从新检查输入!\n"); } else { Data person;//记录联系人信息 printf("请输入联系人的姓名:>"); scanf("%s", person.name); printf("请输入联系人的年龄:>"); scanf("%d", &person.age); printf("请输入联系人的性别:>"); scanf("%s", person.sex); printf("请输入联系人的电话:>"); scanf("%s", person.pnum); printf("请输入联系人的住址:>"); scanf("%s", person.addr); //将联系人信息存到通信录中 p->data[ret] = person; } } //展现联系人信息 void ContactShow(Contact *p) { assert(p); if (p->size == 0) { printf("通信录中并没有一人!\n"); return; } int i = 0; printf(" 姓名\t性别\t 年龄\t 电话\t\t地址\n"); for (i = 0; i < p->size; i++) { printf(" %-5s\t%s\t%d\t%s\t%s\n", p->data[i].name, p->data[i].sex, p->data[i].age, p->data[i].pnum, p->data[i].addr); } } void sort_menu() { printf(" SORT_MENU \n"); printf("******************************\n"); printf("**** 1.name ****\n"); printf("**** 2.sex ****\n"); printf("**** 3.age ****\n"); printf("**** 4.pnum ****\n"); printf("**** 5.addr ****\n"); printf("******************************\n"); } int sort_by_name(const void *s1, const void *s2) { return strcmp(((Data *) s1)->name, ((Data *) s2)->name); } int sort_by_sex(const void *s1, const void *s2) { return strcmp(((Data *) s1)->sex, ((Data *) s2)->sex); } int sort_by_age(const void *s1, const void *s2) { return ((Data *) s1)->age - ((Data *) s2)->age; } int sort_by_pnum(const void *s1, const void *s2) { return strcmp(((Data *) s1)->pnum, ((Data *) s2)->pnum); } int sort_by_addr(const void *s1, const void *s2) { return strcmp(((Data *) s1)->addr, ((Data *) s2)->addr); } //排序联系人 void ContactSort(Contact *p) { assert(p); int choice; sort_menu(); printf("请选择排序的参考量:>"); scanf("%d", &choice); switch (choice) { case NAME: qsort(p->data, p->size, sizeof(Data), sort_by_name); break; case SEX: qsort(p->data, p->size, sizeof(Data), sort_by_sex); break; case AGE: qsort(p->data, p->size, sizeof(Data), sort_by_age); break; case PNUM: qsort(p->data, p->size, sizeof(Data), sort_by_pnum); break; case ADDR: qsort(p->data, p->size, sizeof(Data), sort_by_addr); break; default: printf("输入有误,请检查输入!\n"); } } //打印帮助信息 void ContactHelp(Contact *p) { printf("*******************************************\n"); printf("****** add ---- 添加联系人信息 ******\n"); printf("****** del ---- 删除联系人信息 ******\n"); printf("****** search ---- 查找联系人信息 ******\n"); printf("****** modify ---- 修改联系人信息 ******\n"); printf("****** show ---- 展现联系人信息 ******\n"); printf("****** help ---- 帮助信息 ******\n"); printf("****** sort ---- 排序联系人信息 ******\n"); printf("****** exit ---- 退出通信录 ******\n"); printf("*******************************************\n"); } /*//退出通信录 void ContactExit(Contact *p) { printf("exit !\n"); }*/ /* //退出通信录 --- 动态 void ContactExit(Contact *p) { //释放咱们开辟的内存 free(p->data); printf("exit !\n"); }*/ void Save(Contact* p) { assert(p); FILE* fp =fopen("../Contact.dat","wb"); int i =0; for(i=0;i<p->size;i++) { fwrite(p->data+i, sizeof(Data),1,fp); } fclose(fp); } //退出通信录 --- 带文件 void ContactExit(Contact *p) { //保存置文件 Save(p); //释放咱们开辟的内存 free(p->data); printf("exit !\n"); }
#include "Contact.h" void menu() { //打印菜单 printf("******************************************\n"); printf("****** 1.add 2.del ******\n"); printf("****** 3.search 4.modify ******\n"); printf("****** 5.show 6.sort ******\n"); printf("****** 7.help 0.exit ******\n"); printf("******************************************\n"); } void test() { Contact list;//定义一个通信录 Contact *p = &list;//赋址 //初始化 ContactInit(p); int input = 0;//存放用户选择的信息 do { menu(); printf("请输入你的选择:>"); scanf("%d", &input); switch (input) { case ADD: ContactAdd(p); break; case DEL: ContactDel(p); break; case SEARCH: ContactSearch(p); break; case MODIFY: ContactModify(p); break; case SHOW: ContactShow(p); break; case SORT: ContactSort(p); break; case HELP: ContactHelp(p); break; case EXIT: ContactExit(p); break; default: printf("输入非法!\n"); } } while (input); } void test2() { Contact list;//定义一个通信录 Contact *p = &list;//赋址 //初始化 ContactInit(p); //用一个函数指针数组来存放函数指针 void (*fun[])(Contact *) ={ContactExit, ContactAdd, ContactDel, ContactSearch, ContactModify, ContactShow, ContactSort, ContactHelp}; int input = 0;//存放用户选择的信息 do{ menu(); printf("请输入你的选择:>"); scanf("%d", &input); if(input>=0&&input<=sizeof(fun)) { //system("cls"); fun[input](p); } else { system("cls"); printf("输入非法,请检查输入!\n"); } }while(input); } int main() { //test(); test2(); return 0; }
|---------------------------------------------------------------------------------------------------
到此,咱们的C语言也就告一段落了!
之后的路咱们依然任重而道远!