
- #pragma once
- // 包含头文件
- #include
- #include
- #include
- #include
-
-
- // 使用枚举常量定义功能
- enum Function
- {
- quit, // 注意这是逗号,不是分号
- save,
- addition,
- delete,
- search,
- revise,
- sort,
- show // 最后一个没有逗号
- };
-
- // 人的信息
- #define NAME_MAX 20
- #define SEX_MAX 5
- #define TELE_MAX 12
- #define ADDR_MAX 30
- typedef struct People_Information
- {
- char name[NAME_MAX];
- int age;
- char sex[SEX_MAX];
- char tele[TELE_MAX];
- char addr[ADDR_MAX];
- }People; // 通过typedef将struct People_Informtion定义为了People
-
- // 通讯录
- #define DATA_MAX 1000
- typedef struct Contact
- {
- People data[DATA_MAX]; // data数组里面存放的是每个人的信息
- int sz; // 用于记录通讯录中有几个人的信息
- }Contact; // 通过typedef将struct Contact定义为了Contact
-
-
- // 函数声明
- // 初始化通讯录
- void InitContact(Contact* contact);
- // 增加个人信息
- void AddContact(Contact* contact);
- // 显示通讯录
- void ShowContact(const Contact* contact);
- // 删除指定信息
- void DelContact(Contact* contact);
- // 查找指定信息
- void SeaContact(const Contact* contact);
- // 修改指定联系人
- void RevContact(Contact* contact);
- // 排序通讯录
- void SorContact(Contact* contact);
- #define _CRT_SECURE_NO_WARNINGS
- #include "contact.h"
- void menu()
- {
- printf("..............................\n");
- printf("....0:quit........1:save......\n");
- printf("....2:addition....3:delete....\n");
- printf("....4:search......5:revise....\n");
- printf("....6:sort........7:show......\n");
- printf("..............................\n");
- }
- int main()
- {
-
- // 利用do{}while();循环和switch语句进行多次选择
- int input;
-
- // 进入main函数就要创建通讯录
- Contact contact; // contact就是一个通讯录
-
- // 初始化通讯录
- InitContact(&contact); // 将通讯录的地址传过去,不仅节省地址,而且可以通过形参改变实参
-
- do
- {
- // 有哪些功能
- // 通过菜单将功能展现出来
- menu();
-
- printf("请输入功能序号:");
- scanf("%d", &input);
- switch (input)
- {
- // 通过枚举常量定义会更直观
- case quit:
- printf("退出通讯录!\n");
- break;
- case save:
- break;
- case addition:
- AddContact(&contact);
- break;
- case delete:
- DelContact(&contact);
- break;
- case search:
- SeaContact(&contact);
- break;
- case revise:
- RevContact(&contact);
- break;
- case sort:
- SorContact(&contact);
- break;
- case show:
- ShowContact(&contact);
- break;
- default:
- printf("无此序号,请重新输入。\n");
- }
- } while (input);
- return 0;
- }
- #define _CRT_SECURE_NO_WARNINGS
- #include "contact.h"
-
- // 初始化通讯录
- void InitContact(Contact* contact)
- {
- assert(contact);
- // contact->data = 0; // contact->data表示的是首元素地址
- // 初始化一块连续的内存空间可以使用memset
- memset(contact->data, 0, sizeof(contact->data));
- contact->sz = 0;
- }
-
- // 增加个人信息
- void AddContact(Contact* contact)
- {
- assert(contact);
-
- // 进入函数进行判断
- if (contact->sz == DATA_MAX)
- {
- printf("通讯录已满,无法增加个人信息!\n");
- return;
- }
- // 没有满则进行增加个人信息
- printf("请输入姓名:");
- scanf("%s", &(contact->data[contact->sz].name));
- printf("请输入年龄:");
- scanf("%d", &(contact->data[contact->sz].age));
- printf("请输入性别:");
- scanf("%s", &(contact->data[contact->sz].sex));
- printf("请输入电话:");
- scanf("%s", &(contact->data[contact->sz].tele));
- printf("请输入地址:");
- scanf("%s", &(contact->data[contact->sz].addr));
-
- // 增加完一条信息后sz要加1
- contact->sz++;
- printf("增加成功!\n");
- }
-
- // 显示通讯录
- void ShowContact(const Contact* contact)
- {
- assert(contact);
-
- // 进入函数进行判断
- if (contact->sz == 0)
- {
- printf("通讯录为空!\n");
- return;
- }
- // 显示信息
- // 标题
- printf("%-10s %-5s %-5s %-12s %-30s\n", "姓名", "年龄", "性别", "电话", "住址");
- for (int i = 0; i < contact->sz; i++)
- {
- printf("%-10s %-5d %-5s %-12s %-30s\n",
- contact->data[i].name,
- contact->data[i].age,
- contact->data[i].sex,
- contact->data[i].tele,
- contact->data[i].addr
- );
- }
- }
-
- // 通过名字查找联系人下标
- int FindByName(const Contact* contact, char* name)
- {
- assert(contact);
- for (int i = 0; i < contact->sz; i++)
- {
- if (strcmp(contact->data[i].name, name) == 0)
- {
- // 找到返回数组下标
-
- return i;
- }
- }
- return -1;
- }
-
- // 删除指定信息
- void DelContact(Contact* contact)
- {
- assert(contact);
-
- char name[NAME_MAX];
- if (contact->sz == 0)
- {
- printf("通讯录为空!\n");
- return;
- }
- // 通过名字查找
- printf("请输入要删除人的姓名:");
- scanf("%s", name);
- int ret = FindByName(contact, name);
-
- // 没找到
- if (ret == -1)
- {
- printf("要删除的人不存在!\n");
- }
- // 找到了
- // 删除这个人(其实是覆盖)
- for (int i = ret; i < contact->sz - 2; i++) // 减2这里不是很懂
- {
- contact->data[i] = contact->data[i + 1];
- }
- contact->sz--;
- printf("删除成功!\n");
- // 最后一个直接覆盖当前这个
- // 结构体类型相同可以直接赋值
- /*contact->data[ret] = contact->data[contact->sz];
- contact->sz--;*/
- }
-
- // 查找指定信息
- void SeaContact(const Contact* contact)
- {
- assert(contact);
-
- char name[NAME_MAX];
- if (contact->sz == 0)
- {
- printf("通讯录为空!\n");
- return;
- }
- // 通过名字查找
- printf("请输入要修改人的姓名:");
- scanf("%s", name);
- int ret = FindByName(contact, name);
- // 没找到
- if (ret == -1)
- {
- printf("要查找的人不存在!\n");
- }
- // 找到了
- // 显示出来
- printf("%-10s %-5s %-5s %-12s %-30s\n", "姓名", "年龄", "性别", "电话", "住址");
- printf("%-10s %-5d %-5s %-12s %-30s\n",
- contact->data[ret].name,
- contact->data[ret].age,
- contact->data[ret].sex,
- contact->data[ret].tele,
- contact->data[ret].addr
- );
- }
-
- // 修改指定联系人
- void RevContact(Contact* contact)
- {
- assert(contact);
-
- char name[NAME_MAX];
- if (contact->sz == 0)
- {
- printf("通讯录为空!\n");
- return;
- }
- // 通过名字修改
- printf("请输入要修改人的姓名:");
- scanf("%s", name);
- int ret = FindByName(contact, name);
- // 没找到
- if (ret == -1)
- {
- printf("要修改的人不存在!\n");
- }
- // 找到了
- // 修改
- printf("请输入姓名:");
- scanf("%s", &(contact->data[contact->sz].name));
- printf("请输入年龄:");
- scanf("%d", &(contact->data[contact->sz].age));
- printf("请输入性别:");
- scanf("%s", &(contact->data[contact->sz].sex));
- printf("请输入电话:");
- scanf("%s", &(contact->data[contact->sz].tele));
- printf("请输入地址:");
- scanf("%s", &(contact->data[contact->sz].addr));
-
- printf("修改成功!\n");
- }
-
-
- int compare_name(const void* x, const void* y)
- {
- return strcmp((char*)x, (char*)y);
- }
-
- // 排序通讯录
- void SorContact(Contact* contact)
- {
- assert(contact);
-
- if (contact->sz == 0)
- {
- printf("通讯录为空!\n");
- return;
- }
- // 排序通讯录
- qsort(contact, contact->sz, sizeof(contact->data[0]), compare_name);
- // 显示信息
- // 标题
- printf("%-10s %-5s %-5s %-12s %-30s\n", "姓名", "年龄", "性别", "电话", "住址");
- for (int i = 0; i < contact->sz; i++)
- {
- printf("%-10s %-5d %-5s %-12s %-30s\n",
- contact->data[i].name,
- contact->data[i].age,
- contact->data[i].sex,
- contact->data[i].tele,
- contact->data[i].addr
- );
- }
- }
通讯录初始化涉及到传递参数,那我们到底是传址还是传值呢?
InitContact(&contact); // 传递的是地址
// 传址:因为更节省内存空间(地址只占4/8个字节),而且可以通过形参来改变实参;
// 传值:所需的内存空间更大,并且改变形参并不会影响实参;
// 这里使用的是memset初始化数组,也可以通过循环将数组一个一个制成0;


初始设计的通讯录所存在的缺陷
1、录入的信息,只要一退出程序,数据就会丢失,因为数据是存放在内存中的;
解决方案就是:文件存储、数据存储
2、通讯录开辟的空间是固定的,如果存放的信息多空间就小了;如果存放的信息少空间就大了;
解决方案就是:动态内存管理