目录
游戏声明部分
#pragma once
#include<stdio.h>
#include<string.h>
#include<stdlib.h>
#define MAX_NAME 20
#define MAX_SEX 10
#define MAX_CALL 12
#define MAX_ADDR 30
#define MAX_CON 100
#define MAX_SPACE 3 //初始化动态内存开辟空间大小
//一个人的信息
typedef struct ProInfo //使用typedef进行重命名
{
char name[MAX_NAME];
char sex[MAX_SEX];
int age;
char call[MAX_CALL];
char addr[MAX_ADDR];
}ProInfo;
//静态版本
//typedef struct Contact //使用typedef进行重命名
//{
// ProInfo data[MAX_CON];
// int sz;
//}Contact;
//动态版本
typedef struct Contact
{
ProInfo* data;//使用动态内存开辟的空间 由于存放联系人信息
int sz;//用于记录联系人数量
int capacity;//用于记录动态内存开辟空间的容量大小
}Contact;
//初始化
void initialize(Contact* pc);
//添加联系人
void AddContact(Contact* pc);
//打印联系人
void PrintContact(Contact* pc);
//删除联系人
void DelContact(Contact* pc);
//查询联系人
void QweryContact(Contact* pc);
//修改联系人
void ModfiyContact(Contact* pc);
//排序联系人
void SortContact(Contact* pc);
//退出程序时将数据保存到文件
void SaveContact(Contact* pc);
检查是否要扩容
void checkContact(Contact* pc);
//销毁通讯录
void destroycontact(Contact* pc);
游戏实现部分
#define _CRT_SECURE_NO_WARNINGS 1
#include"contact.h"
//静态版本
//void initialize(Contact* pc)
//{
// memset(pc->data, 0, sizeof(pc->data)); //内存设置函数,以字节为单位将目标内存设置为想要的值
// pc->sz = 0;
//
//}
//动态版本
void initialize(Contact* pc)
{
pc->sz = 0;
ProInfo* p=(ProInfo*)calloc(MAX_SPACE,sizeof(ProInfo));//使用动态内存开辟一块空间,不把大小固定,方便后期修改大小
if (p == NULL)//判断是否成功开辟空间
{
perror("initialize");//若开辟失败进行报错
return;
}
pc->data = p;
pc->capacity = MAX_SPACE;
//读入数据--从文件中输入数据
FILE* pf = fopen("contact.dat", "r");
if (pf == NULL)
{
perror("initialize:fopen");
return;
}
while (fread(pc->data + (pc->sz), sizeof(ProInfo), 1, pf))
{
checkContact(pc);
pc->sz++;
}
//关闭文件
fclose(pf);
pf = NULL;
}
//检查是否要扩容
void checkContact(Contact* pc)
{
if (pc->sz == pc->capacity)
{
pc->capacity += 2;
ProInfo* p = (ProInfo*)realloc(pc->data, pc->capacity * sizeof(ProInfo));//使用realloc函数进行扩容
if (p == NULL)//判断是否成功开辟空间
{
perror("checkContact");//若开辟失败进行报错
return;
}
pc->data = p;
printf("扩容成功\n");
}
}
//将数据保存到文件
void SaveContact(Contact* pc)
{
//打开文件
FILE* pf = fopen("contact.dat", "w");
if (pf == NULL)
{
perror("SaveContact");
return;
}
//写入数据--将数据输出至文件中
int i;
for (i = 0; i<pc->sz; i++)
{
fwrite(pc->data + i, sizeof(ProInfo), 1, pf);
}
//关闭文件
fclose(pf);
pf = NULL;
}
//销毁通讯录
void destroycontact(Contact* pc)
{
free(pc->data);//释放之前动态开辟的内存
pc->data = NULL;
pc->capacity = 0;
pc->sz = 0;
}
//静态版本
//void AddContact(Contact* pc)
//{
// printf("请输入姓名:");
// scanf("%s", pc->data[pc->sz].name);
// printf("请输入性别:");
// scanf("%s", pc->data[pc->sz].sex);
// printf("请输入年龄:");
// scanf("%d", &pc->data[pc->sz].age);
// printf("请输入电话:");
// scanf("%s", pc->data[pc->sz].call);
// printf("请输入地址:");
// scanf("%s", pc->data[pc->sz].addr);
// printf("输入成功\n");
// pc->sz++;
//}
//动态版本
void AddContact(Contact* pc)
{
//检查是否要扩容
checkContact(pc);
printf("请输入姓名:");
scanf("%s", pc->data[pc->sz].name);
printf("请输入性别:");
scanf("%s", pc->data[pc->sz].sex);
printf("请输入年龄:");
scanf("%d", &pc->data[pc->sz].age);
printf("请输入电话:");
scanf("%s", pc->data[pc->sz].call);
printf("请输入地址:");
scanf("%s", pc->data[pc->sz].addr);
printf("输入成功\n");
pc->sz++;
}
void PrintContact(Contact* pc)
{
int i = 0;
printf("%-5s\t%-5s\t%-5s\t%-15s\t%-30s\n", "姓名", "性别", "年龄", "电话", "地址");
for (i = 0; i < pc->sz; i++)
{
printf("%-5s\t%-5s\t%-5d\t%-15s\t%-30s\n"
, pc->data[i].name
, pc->data[i].sex
, pc->data[i].age
, pc->data[i].call
, pc->data[i].addr);
}
}
static int FindContact(const 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)
{
printf("请输入删除人姓名:");
char Name[20] = { 0 };
scanf("%s", Name);
int ret=FindContact(pc,Name);//返回下标,若无此联系人返回-1
if (ret == -1)
{
printf("无此联系人,请重新选择\n");
return;
}
int i = 0;
for (i = ret; i < pc->sz-1; i++) //将要删除联系人之后的下标向前移动一位,将要删除联系人覆盖
{
pc->data[i] = pc->data[i + 1];
}
printf("删除成功\n");
pc->sz--; //移动完后,将sz--使得无法访问打印最后一位联系人即可,无需删除
}
void QweryContact(Contact* pc)
{
printf("请输入查找人姓名:");
char Name[MAX_NAME] = { 0 };
scanf("%s", Name);
int ret = FindContact(pc, Name);
if (ret == -1)//若无则返回,重新选择
{
printf("无此联系人,请重新选择\n");
return;
}
//若有则打印
printf("%-5s\t%-5s\t%-5s\t%-15s\t%-30s\n", "姓名", "性别", "年龄", "电话", "地址");
printf("%-5s\t%-5s\t%-5d\t%-15s\t%-30s\n"
, pc->data[ret].name
, pc->data[ret].sex
, pc->data[ret].age
, pc->data[ret].call
, pc->data[ret].addr);
}
void ModfiyContact(Contact* pc)
{
printf("请输入修改人姓名:");
char Name[MAX_NAME] = { 0 };
scanf("%s", Name);
int ret = FindContact(pc, Name);
if (ret == -1)
{
printf("无此联系人,请重新选择\n");
return;
}
printf("请输入修改后姓名:");
scanf("%s", pc->data[ret].name);
printf("请输入修改后性别:");
scanf("%s", pc->data[ret].sex);
printf("请输入修改后年龄:");
scanf("%d", &pc->data[ret].age);
printf("请输入修改后电话:");
scanf("%s", pc->data[ret].call);
printf("请输入修改后地址:");
scanf("%s", pc->data[ret].addr);
printf("修改成功\n");
}
//不同排序方法所使用的不同函数,用于比较两个元素的大小
int NameSort(const void*e1, const void*e2)
{
return strcmp(((Contact*)e1)->data->name, ((Contact*)e2)->data->name);
}
int SexSort(const void* e1, const void* e2)
{
return strcmp(((Contact*)e1)->data->sex, ((Contact*)e2)->data->sex);
}
int AgeSort(const void* e1, const void* e2)
{
return ((Contact*)e1)->data->age - ((Contact*)e2)->data->age;
}
int CallSort(const void* e1, const void* e2)
{
return strcmp(((Contact*)e1)->data->call, ((Contact*)e2)->data->call);
}
int AddrSort(const void* e1, const void* e2)
{
return strcmp(((Contact*)e1)->data->addr, ((Contact*)e2)->data->addr);
}
void SortContact(Contact* pc)
{
printf("请选择排序方法:\n");
printf("** 1.name 2.sex ***\n");
printf("** 3.age 4.call ***\n");
printf("** 5.addr 0.exit ***\n");
int n = 0;
scanf("%d", &n);
//使用函数指针数组,利用下标访问不同函数
int(*cmp[6])(const void*, const void*) = { NULL,NameSort ,SexSort, AgeSort, CallSort, AddrSort };
switch (n)
{
case 1:
qsort(pc, pc->sz, sizeof(ProInfo), cmp[n]); //使用qsort函数进行排序
break;
case 2:
qsort(pc, pc->sz, sizeof(ProInfo), cmp[n]);
break;
case 3:
qsort(pc, pc->sz, sizeof(ProInfo), cmp[n]);
break;
case 4:
qsort(pc, pc->sz, sizeof(ProInfo), cmp[n]);
break;
case 5:
qsort(pc, pc->sz, sizeof(ProInfo), cmp[n]);
break;
case 0:
return;
default:
printf("输入错误,请重新选择\n");
return;
}
printf("排序成功\n");
}
主要逻辑部分
#define _CRT_SECURE_NO_WARNINGS 1
#include"contact.h"
void menu()
{
printf("***********************************\n");
printf("***** 1.add 2.del *********\n");
printf("***** 3.query 4.modify *********\n");
printf("***** 5.print 6.sort *********\n");
printf("***** 0.exit *********\n");
printf("***********************************\n");
}
enum en
{
EXIT,
ADD,
DEL,
QWERY,
MODIFY,
PRINT,
SORT
};
//添加,删除,查找,修改,打印,排序,
int main()
{
int input = 0;
Contact con;
//初始化
initialize(&con);
do
{
menu();
printf("请输入->");
scanf("%d", &input);
switch (input)
{
case ADD:
AddContact(&con);
break;
case DEL:
DelContact(&con);
break;
case QWERY:
QweryContact(&con);
break;
case MODIFY:
ModfiyContact(&con);
break;
case PRINT:
PrintContact(&con);
break;
case SORT:
SortContact(&con);
break;
case EXIT:
SaveContact(&con);
destroycontact(&con);//销毁通讯录
printf("退出程序");
break;
default:
printf("输入错误,请重新输入\n");
break;
}
} while (input);
return 0;
}