只是先说明main函数主体的构造,里面包含的函数在后面会一一说明
void menu()
{
printf("************************************\n");
printf("******* 1. add 2. del ******\n");
printf("******* 3. search 4. modify ******\n");
printf("******* 5.sort 6. print ******\n");
printf("******* 0.exit ******\n");
printf("************************************\n");
}
void Setting()
{
int input = 0;
Contact con;
InitContact(&con);
do
{
menu();
printf("请输入你的选择\n");
scanf("%d", &input);
switch (input)
{
case ADD:
AddContact(&con);
break;
case DEL:
DelContact(&con);
break;
case SEACH:
SeachContact(&con);
break;
case MODIFY:
ModifyContact(&con);
break;
case SORT:
SortContact(&con);
break;
case PRINT:
PrintContact(&con);
break;
case EXIT:
SaveContact(&con);
DestroyContact(&con);
printf("退出通讯录\n");
break;
default:
printf("输入错误,请重新输入\n");
break;
}
} while (input);
}
int main()
{
Setting();
return 0;
}
void menu()
{
printf("************************************\n");
printf("******* 1. add 2. del ******\n");
printf("******* 3. search 4. modify ******\n");
printf("******* 5.sort 6. print ******\n");
printf("******* 0.exit ******\n");
printf("************************************\n");
}
#define NAME_MAX 20
#define SEX_MAX 5
#define TELE_MAX 14
#define ADDR_MAX 20
#define DEFAULT_MAX 3
typedef struct Peoinfo
{
char name[NAME_MAX];
char sex[SEX_MAX];
int age;
char tele[TELE_MAX];
char addr[ADDR_MAX];
}Peoinfo;
typedef struct Contact
{
Peoinfo* data;
int sz;
int capacity;
}Contact;
enum option
{
EXIT,
ADD,
DEL,
SEACH,
MODIFY,
SORT,
PRINT
};
将包含接收联系人信息和计数变量的结构体变量的地址作为参数传给函数。
对函数进行声明,这使得我们在其他两个文件中都可以使用这个函数,如果对该结构体的内容不做改变,函数的形参前可以加上const。
void InitContact(Contact* pc)
{
assert(pc); //记得加上断言
pc->capacity = DEFAULT_MAX;
pc->data = (Peoinfo*)malloc(pc->capacity * sizeof(Peoinfo));
pc->sz = 0;
if (pc->data == NULL) //当初始化失败时显示失败信息
{
perror("InitContact::malloc");
return;
}
memset(pc->data, 0, pc->capacity * sizeof(Peoinfo));
LoadContact(pc);
}
void LoadContact(Contact* pc)
{
FILE* pf = fopen("Contact.dat", "rb");
if (pf == NULL)
{
perror("LoadContact::fopen");
return;
}
Peoinfo tmp = { 0 };
while (fread(&tmp, sizeof(Peoinfo), 1, pf))
{
CheckCapacity(pc);
pc->data[pc->sz] = tmp;
pc->sz++;
}
fclose(pf);
pf = NULL;
}
void CheckCapacity(Contact* pc)
{
if (pc->sz == pc->capacity)
{
Peoinfo* tmp = (Peoinfo*)realloc(pc->data, (pc->capacity + 2) * sizeof(Peoinfo));
if (tmp != NULL)
{
pc->data = tmp;
pc->capacity += 2;
printf("扩容成功\n");
}
else
{
perror("CheckCapacity::realloc"); //显示扩容失败的信息
return;
}
}
}
void AddContact(Contact* pc)
{
assert(pc);
CheckCapacity(pc);
printf("请输入欲增加联系人的姓名:\n");
scanf("%s", pc->data[pc->sz].name);
printf("请输入欲增加联系人的性别:\n");
scanf("%s", pc->data[pc->sz].sex);
printf("请输入欲增加联系人的年龄:\n");
scanf("%d", &(pc->data[pc->sz].age)); //年龄是int型,不要用%s打印
printf("请输入欲增加联系人的电话号码:\n");
scanf("%s", pc->data[pc->sz].tele);
printf("请输入欲增加联系人的地址:\n");
scanf("%s", pc->data[pc->sz].addr);
pc->sz++;
printf("添加联系人成功\n"); //输出提示语句
}
void PrintContact(const Contact* pc) //只打印不修改,可加const
{
assert(pc);
printf("%-20s %-5s %-5s %-14s %-20s\n", "姓名", "性别", "年龄", "电话号码", "地址");
for (int i = 0; i < pc->sz; ++i)
{
printf("%-20s %-5s %-5d %-14s %-20s\n", pc->data[i].name, pc->data[i].sex,
pc->data[i].age, pc->data[i].tele, pc->data[i].addr);
}
}
void DelContact(Contact* pc)
{
assert(pc);
if (pc->sz == 0)
{
printf("通讯录为空,无法删除\n");
return;
}
char name[NAME_MAX] = { 0 }; //可使用NAME_MAX,而不是数字
printf("请输入欲删除人的姓名\n");
scanf("%s", name);
int pos = FindByName(pc, name);
if (pos == -1)
{
printf("通讯录中无此人的信息,删除失败\n");
return;
}
for (int i = pos; i < pc->sz - 1; ++i)
{
pc->data[i] = pc->data[i + 1];
}
pc->sz--;
printf("删除成功\n");
}
int FindByName(Contact* pc, char* name)
{
assert(pc); //记得加上断言
for (int i = 0; i < pc->sz; ++i)
{
if (strcmp(pc->data[i].name, name) == 0)
return i; //找到返回下标
}
return -1; //找不到返回-1
}
void SeachContact(const Contact* pc)
{
assert(pc);
if (pc->sz == 0)
{
printf("通讯录为空,无法查找\n");
return;
}
char name[NAME_MAX] = { 0 }; //可使用NAME_MAX,而不是数字
printf("请输入欲查找人的姓名:\n");
scanf("%s", name);
int pos = FindByName(pc, name);
if (pos == -1)
{
printf("通讯录中无此人的信息\n");
return;
}
printf("%-20s %-5s %-5s %-14s %-20s\n", "姓名", "性别", "年龄", "电话号码", "地址");
printf("%-20s %-5s %-5d %-14s %-20s\n", pc->data[pos].name, pc->data[pos].sex,
pc->data[pos].age, pc->data[pos].tele, pc->data[pos].addr);
}
void ModifyContact(Contact* pc)
{
assert(pc);
if (pc->sz == 0)
{
printf("通讯录为空,无法修改\n");
return;
}
char name[NAME_MAX] = { 0 };
printf("请输入欲修改人的姓名:\n");
scanf("%s", name);
int pos = FindByName(pc, name);
if (pos == -1)
{
printf("通讯录中无此人的信息,无法修改\n");
return;
}
printf("请输入修改后的联系人姓名:\n");
scanf("%s", pc->data[pos].name);
printf("请输入修改后的联系人性别:\n");
scanf("%s", pc->data[pos].sex);
printf("请输入修改后的联系人年龄:\n");
scanf("%d", &(pc->data[pos].age));
printf("请输入修改后的联系人电话号码:\n");
scanf("%s", pc->data[pos].tele);
printf("请输入修改后的联系人地址:\n");
scanf("%s", pc->data[pos].addr);
}
void SortContact(Contact* pc)
{
assert(pc);
if (pc->sz == 0)
{
printf("通讯录为空,无法排序\n");
return;
}
Peoinfo tmp = { 0 };
for (int i = 0; i < pc->sz; ++i)
{
for (int j = 0; j < pc->sz - 1 - i; ++j)
{
//if(strcmp(pc->data+j,pc->data+j+1)>0) //比较的是名字,而不是整体,不能用这种
if (strcmp(pc->data[j].name, pc->data[j + 1].name) > 0)
{
tmp = pc->data[j];
pc->data[j] = pc->data[j + 1];
pc->data[j + 1] = tmp;
}
}
}
printf("排序成功\n");
}
void SaveContact(const Contact* pc)
{
FILE* pf = fopen("Contact.dat", "wb");
if (pf == NULL)
{
perror("SaveContact::fopen");
return;
}
for (int i = 0; i < pc->sz; ++i)
{
//fwrite(pc->data[i], sizeof(Peoinfo), 1, pf); //这种方式不可以
fwrite(pc->data + i, sizeof(Peoinfo), 1, pf);
}
fclose(pf);
pf = NULL;
}
void DestroyContact(Contact* pc)
{
free(pc->data);
pc->data = NULL;
pc->sz = 0;
pc->capacity = 0;
printf("销毁通讯录成功\n");
}
#include"Contact.h"
void menu()
{
printf("************************************\n");
printf("******* 1. add 2. del ******\n");
printf("******* 3. search 4. modify ******\n");
printf("******* 5.sort 6. print ******\n");
printf("******* 0.exit ******\n");
printf("************************************\n");
}
void Setting()
{
int input = 0;
Contact con;
InitContact(&con);
do
{
menu();
printf("请输入你的选择\n");
scanf("%d", &input);
switch (input)
{
case ADD:
AddContact(&con);
break;
case DEL:
DelContact(&con);
break;
case SEACH:
SeachContact(&con);
break;
case MODIFY:
ModifyContact(&con);
break;
case SORT:
SortContact(&con);
break;
case PRINT:
PrintContact(&con);
break;
case EXIT:
SaveContact(&con);
DestroyContact(&con);
printf("退出通讯录\n");
break;
default:
printf("输入错误,请重新输入\n");
break;
}
} while (input);
}
int main()
{
Setting();
return 0;
}
#pragma once
#define _CRT_SECURE_NO_WARNINGS
//头文件包含
#include
#include
#include
#include
//#define MAX 100 //通讯录的最大人数(静态版本需要)
#define NAME_MAX 20
#define SEX_MAX 5
#define TELE_MAX 14
#define ADDR_MAX 20
//通讯录初始时的最大容量
#define DEFAULT_MAX 3
//定义每个人的信息
typedef struct Peoinfo
{
char name[NAME_MAX];
char sex[SEX_MAX];
int age;
char tele[TELE_MAX];
char addr[ADDR_MAX];
}Peoinfo;
typedef struct Contact
{
Peoinfo* data;
int sz; //记录通讯录保存的人数
int capacity; //初始时的通讯录最大人数
}Contact;
//枚举,使选择项更具可读性
enum option
{
EXIT,
ADD,
DEL,
SEACH,
MODIFY,
SORT,
PRINT
};
//初始化通讯录
void InitContact(Contact* pc);
//增加联系人
void AddContact(Contact* pc);
//输出通讯录中人的信息
void PrintContact(const Contact* pc);
//删除通讯录中人的信息
void DelContact(Contact* pc);
//查找通讯录中指定人的信息
void SeachContact(const Contact* pc);
//修改通讯录中指定人的信息
void ModifyContact(Contact* pc);
//销毁通讯录
void DestroyContact(Contact* pc);
//保存通讯录数据
void SaveContact(const Contact* pc);
//对通讯录进行排序
void SortContact(Contact* pc);
#include"Contact.h"
//检查容量是否已满并扩容
void CheckCapacity(Contact* pc)
{
if (pc->sz == pc->capacity)
{
Peoinfo* tmp = (Peoinfo*)realloc(pc->data, (pc->capacity + 2) * sizeof(Peoinfo));
//分支判断语句需写在if语句内,否则当跳出if语句,tmp变量将是未定义的变量
if (tmp != NULL)
{
pc->data = tmp;
pc->capacity += 2;
printf("扩容成功\n");
}
else
{
perror("CheckCapacity::realloc"); //显示扩容失败的信息
return;
}
}
}
// //动态版本
// //初始化通讯录
//void InitContact(Contact* pc)
//{
// assert(pc); //记得加上断言
// pc->capacity = DEFAULT_MAX;
// pc->data = (Peoinfo*)malloc(pc->capacity * sizeof(Peoinfo));
// //memset(pc, 0, sizeof(pc->data));
// pc->sz = 0;
// if (pc->data == NULL) //当初始化失败时显示失败信息
// {
// perror("InitContact::malloc");
// return;
// }
//}
//加载通讯录
void LoadContact(Contact* pc)
{
FILE* pf = fopen("Contact.dat", "rb");
if (pf == NULL)
{
perror("LoadContact::fopen");
return;
}
Peoinfo tmp = { 0 };
while (fread(&tmp, sizeof(Peoinfo), 1, pf))
{
CheckCapacity(pc); //记得加上此语句,否则会出现空间不够的情况
pc->data[pc->sz] = tmp;
pc->sz++;
}
//while (fread(pc->data + pc->sz, sizeof(Peoinfo), 1, pf))
//{
// CheckCapacity(pc); //记得加上此语句,否则会出现空间不够的情况
// pc->sz++;
//}
// //不可以用这种方式加载通讯录,因为此时sz为0
//for (int i = 0; i < pc->sz; ++i)
//{
// CheckCapacity(pc);
// fread(pc->data[i], sizeof(Peoinfo), 1, pf);
//}
//记得关闭文件和把指针置空
fclose(pf);
pf = NULL;
}
//文件版本
void InitContact(Contact* pc)
{
assert(pc); //记得加上断言
pc->capacity = DEFAULT_MAX;
pc->data = (Peoinfo*)malloc(pc->capacity * sizeof(Peoinfo));
//memset(pc, 0, sizeof(pc->data)); //错误写法,会导致程序崩溃
pc->sz = 0;
if (pc->data == NULL) //当初始化失败时显示失败信息
{
perror("InitContact::malloc");
return;
}
memset(pc->data, 0, pc->capacity * sizeof(Peoinfo));
LoadContact(pc);
}
//增加联系人
void AddContact(Contact* pc)
{
assert(pc);
//静态版本
//if (pc->sz == MAX) //当sz与MAX相等时就代表已经满了,不能用大于号来进行判断
//{
// printf("通讯录已满,无法添加\n");
// return;
//}
//动态版本
CheckCapacity(pc);
printf("请输入欲增加联系人的姓名:\n");
scanf("%s", pc->data[pc->sz].name);
printf("请输入欲增加联系人的性别:\n");
scanf("%s", pc->data[pc->sz].sex);
printf("请输入欲增加联系人的年龄:\n");
scanf("%d", &(pc->data[pc->sz].age)); //年龄是int型,不要用%s格式
printf("请输入欲增加联系人的电话号码:\n");
scanf("%s", pc->data[pc->sz].tele);
printf("请输入欲增加联系人的地址:\n");
scanf("%s", pc->data[pc->sz].addr);
pc->sz++;
printf("添加联系人成功\n"); //输出提示语句
}
//输出通讯录中人的信息
void PrintContact(const Contact* pc) //只打印不修改,可加const
{
assert(pc);
printf("%-20s %-5s %-5s %-14s %-20s\n", "姓名", "性别", "年龄", "电话号码", "地址");
for (int i = 0; i < pc->sz; ++i)
{
printf("%-20s %-5s %-5d %-14s %-20s\n", pc->data[i].name, pc->data[i].sex,
pc->data[i].age, pc->data[i].tele, pc->data[i].addr);
}
}
//以通讯录中人的姓名进行查找
int FindByName(Contact* pc, char* name)
{
assert(pc); //记得加上断言
for (int i = 0; i < pc->sz; ++i)
{
if (strcmp(pc->data[i].name, name) == 0)
return i; //找到返回下标
}
return -1; //找不到返回-1
}
//删除通讯录中人的信息
void DelContact(Contact* pc)
{
assert(pc);
if (pc->sz == 0)
{
printf("通讯录为空,无法删除\n");
return;
}
char name[NAME_MAX] = { 0 }; //可使用NAME_MAX,而不是数字
printf("请输入欲删除人的姓名\n");
scanf("%s", name);
int pos = FindByName(pc, name);
if (pos == -1)
{
printf("通讯录中无此人的信息,删除失败\n");
return;
}
for (int i = pos; i < pc->sz - 1; ++i)
{
pc->data[i] = pc->data[i + 1]; //data后无需加结构体成员变量名,因为其是不可修改的左值
}
pc->sz--;
printf("删除成功\n");
}
//查找通讯录中指定人的信息
void SeachContact(const Contact* pc)
{
assert(pc);
if (pc->sz == 0)
{
printf("通讯录为空,无法查找\n");
return;
}
char name[NAME_MAX] = { 0 }; //可使用NAME_MAX,而不是数字
printf("请输入欲查找人的姓名:\n");
scanf("%s", name);
int pos = FindByName(pc, name);
if (pos == -1)
{
printf("通讯录中无此人的信息\n");
return;
}
printf("%-20s %-5s %-5s %-14s %-20s\n", "姓名", "性别", "年龄", "电话号码", "地址");
printf("%-20s %-5s %-5d %-14s %-20s\n", pc->data[pos].name, pc->data[pos].sex,
pc->data[pos].age, pc->data[pos].tele, pc->data[pos].addr);
}
//修改通讯录中指定人的信息
void ModifyContact(Contact* pc)
{
assert(pc);
if (pc->sz == 0)
{
printf("通讯录为空,无法修改\n");
return;
}
char name[NAME_MAX] = { 0 };
printf("请输入欲修改人的姓名:\n");
scanf("%s", name);
int pos = FindByName(pc, name);
if (pos == -1)
{
printf("通讯录中无此人的信息,无法修改\n");
return;
}
printf("请输入修改后的联系人姓名:\n");
scanf("%s", pc->data[pos].name);
printf("请输入修改后的联系人性别:\n");
scanf("%s", pc->data[pos].sex);
printf("请输入修改后的联系人年龄:\n");
scanf("%d", &(pc->data[pos].age)); //年龄是int型,不要用%s的格式
printf("请输入修改后的联系人电话号码:\n");
scanf("%s", pc->data[pos].tele);
printf("请输入修改后的联系人地址:\n");
scanf("%s", pc->data[pos].addr);
}
//销毁通讯录
void DestroyContact(Contact* pc)
{
free(pc->data);
pc->data = NULL;
pc->sz = 0;
pc->capacity = 0;
printf("销毁通讯录成功\n");
}
//保存通讯录数据
void SaveContact(const Contact* pc)
{
FILE* pf = fopen("Contact.dat", "wb");
if (pf == NULL)
{
perror("SaveContact::fopen");
return;
}
for (int i = 0; i < pc->sz; ++i)
{
//fwrite(pc->data[i], sizeof(Peoinfo), 1, pf); //这种方式不可以
fwrite(pc->data + i, sizeof(Peoinfo), 1, pf);
}
fclose(pf);
pf = NULL;
}
//对通讯录进行排序
void SortContact(Contact* pc)
{
assert(pc);
if (pc->sz == 0)
{
printf("通讯录为空,无法排序\n");
return;
}
Peoinfo tmp = { 0 };
for (int i = 0; i < pc->sz; ++i)
{
for (int j = 0; j < pc->sz - 1 - i; ++j)
{
//if(strcmp(pc->data+j,pc->data+j+1)>0) //比较的是名字,而不是整体,不能用这种
if (strcmp(pc->data[j].name, pc->data[j + 1].name) > 0)
{
tmp = pc->data[j];
pc->data[j] = pc->data[j + 1];
pc->data[j + 1] = tmp;
}
}
}
printf("排序成功\n");
}