测试环境:vs2013
题目:
实现一个通讯录;
通讯录可以用来存储1000个人的信息,每个人的信息包括:
姓名、性别、年龄、电话、住址
提供方法:
- 退出
- 添加联系人信息
- 删除指定联系人信息
- 查找指定联系人信息
- 修改指定联系人信息
- 显示所有联系人信息
- 清空所有联系人
- 保存通讯录
代码如下:
通讯录框架(main.c)
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include "MailList.h"//引用两次会出现重定义现象
int menu()
{
int tmp, ret;
printf("0. 退出\n"
"1. 添加联系人信息\n"
"2. 删除指定联系人信息\n"
"3. 查找指定联系人信息\n"
"4. 修改指定联系人信息\n"
"5. 显示所有联系人信息\n"
"6. 清空所有联系人\n"
"7. 保存通讯录\n"
"请输入选项:");
ret = scanf("%d", &tmp);//防止输入错误(如果输入成功scanf返回1,否则返回0)
return ret ? tmp : -1;
}
void MailList()
{
int op, ret;
char str[256] = { 0 };//用来搜索字符串(256只是一个上限,不会搜255个字符)
int searchRes[1001] = { 0 };//为了存储1000条数据
MailLists allData; //创建通讯录的名称
struct MailList tmp;//创建储存每条信息的变量
initMailList(&allData);
if (loadData(&allData, FILENAME))
{
printf("读取失败\n");
}
while (1)
{
op = menu();
if (op == 0)
{
break;
}
switch (op)
{
case ADD_MSG:
inputData(&tmp);
addMailList(&allData, tmp);
break;
case DELETE_MSG:
printf("请输入你要删除的条目:\n");
memset(str, 0, sizeof(str));//每次调用str前,先将str置0
scanf("%s", str);
ret = catchOneData(allData, str);
if (ret >= 0)
{
deleteOneData(&allData, ret);
printf("删除成功\n");
}
else
{
printf("删除失败\n");
}
break;
case SEARCH_MSG:
printf("请输入你要检索的字符串:\n");
memset(str, 0, sizeof(str));//每次调用str前,先将str置0
memset(searchRes, 0, sizeof(searchRes));//每次调用searchRes前,先将searchRes置0
scanf("%s", str);
searchData(allData, str, searchRes);
outputSearchData(allData, searchRes);
printf("共找到%d条数据\n", searchRes[0]);
break;
case CHANGE_MSG:
printf("请输入你要检索的字符串:\n");
memset(str, 0, sizeof(str));
memset(searchRes, 0, sizeof(searchRes));
scanf("%s", str);
searchData(allData, str, searchRes);
outputSearchData(allData, searchRes);
printf("请输入你要修改联系人信息的序号\n");
scanf("%d", &ret);
deleteOneData(&allData, ret - 1);
inputData(&tmp);
addMailList(&allData, tmp);
break;
case DISPLAY_MSG:
outputData(allData);
break;
case EMPTY_MSG:
destoryMailList(&allData);
initMailList(&allData);
break;
case SAVE_FILE:
if (saveData(allData, FILENAME))
{
printf("保存失败\n");
}
else
{
printf("保存成功\n");
}
break;
case -1:
printf("输入有误,请重新输入\n");
getchar();
break;
default:
printf("输入有误,请重新输入\n");
}
}
destoryMailList(&allData);
}
int main(){
MailList();
return 0;
}
通讯录各个函数的定义(mailList.c)
#define _CRT_SECURE_NO_WARNINGS
#include "MailList.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
//初始化所有数据
void initMailList(MailLists * data)
{
//每一次动态开辟存储100条数据的空间,并将其初始化为0
data->allMsg = (struct MailList *)calloc(PERSPACE, sizeof(struct MailList));
data->count = 0;
data->limit = PERSPACE;
}
//输入数据
void inputData(struct MailList * oneData)
{
printf("请输入姓名:\n");
scanf("%49s", oneData->name);
getchar();//吞掉回车键
printf("请输入性别(f/m):\n");
scanf("%c", &oneData->gender);
printf("请输入年龄:\n");
scanf("%d", &oneData->age);
printf("请输入电话号码:\n");
scanf("%29s", oneData->telnum);
printf("请输入地址:\n");
scanf("%199s", oneData->addr);
}
//将每条信息存储到通讯录中
void addMailList(MailLists * data, struct MailList oneData)
{
int i;
if (data->count == data->limit)
{
//如果动态开辟的内存空间已经存满(信息存储100条),则继续动态开辟
data->limit += PERSPACE;
data->allMsg = (struct MailList *)realloc(data->allMsg, data->limit * sizeof(struct MailList));
}
for (i = 0; i < data->count; i++)
{
//按照名字进行排序
if (strcmp(data->allMsg[i].name, oneData.name) > 0)
{
break;
}
}
int j;
for (j = data->count; j > i; j--)
{
data->allMsg[j] = data->allMsg[j - 1];//将名字字母大于他的,排到他的后面
}
data->allMsg[i] = oneData;
data->count++;
}
//删除通讯录
void destoryMailList(MailLists * data)
{
if (data->allMsg)//allMsg开辟成功不返回NULL,条件为真
{
free(data->allMsg);//释放动态开辟的内存空间
}
data->allMsg = NULL;//释放完,让其等于NULL
data->count = 0;
data->limit = 0;
}
//寻找信息
void searchData(MailLists data, char * find, int * searchres)
{
int i, flag;
char age[4] = { 0 };//用来记录年龄的变量
char * ret;
for (i = 0; i < data.count; i++)
{
do{
flag = 1;
ret = strstr(data.allMsg[i].name, find);
if (ret)
{
break;
}
ret = strstr(data.allMsg[i].telnum, find);
if (ret)
{
break;
}
sprintf(age, "%d", data.allMsg[i].age);//将输入的数据以10进制格式存储在age中
if (!strcmp(age, find))
{
break;
}
ret = strstr(data.allMsg[i].addr, find);
if (ret)
{
break;
}
flag = 0;
} while (0);
//如果没有找到flag == 0;找到则查找有无其他信息
if (flag)
{
searchres[0]++;//0++
searchres[searchres[0]] = i;
}
}
}
//删除一条信息
void deleteOneData(MailLists * data, int n)
{
int i;
for (i = n; i < data->count; i++)
{
data->allMsg[i] = data->allMsg[i + 1];
}
data->count--;
}
//输出数据
void outputData(MailLists data)
{
int i;
if (data.count == 0)
{
printf("没有数据\n");
return;
}
printf(" 姓名 性别 年龄 电话 住址\n");
for (i = 0; i < data.count; i++)
{
printf("%-10s %3c %3d %11s %s\n",
data.allMsg[i].name,
data.allMsg[i].gender,
data.allMsg[i].age,
data.allMsg[i].telnum,
data.allMsg[i].addr);
}
}
//输出搜寻出来的数据
void outputSearchData(MailLists data, int * outputdata)
{
int i;
if (outputdata[0] == 0)
{
printf("没有符合条件的数据\n");
return;
}
printf(" 姓名 性别 年龄 电话 住址\n");
for (i = 1; i <= outputdata[0]; i++)
{
printf("%2d %-10s %3c %3d %11s %s\n",
i,
data.allMsg[outputdata[i]].name,
data.allMsg[outputdata[i]].gender,
data.allMsg[outputdata[i]].age,
data.allMsg[outputdata[i]].telnum,
data.allMsg[outputdata[i]].addr);
}
}
//得到一条通讯录信息
int catchOneData(MailLists data, char *find)
{
int schres[1001] = { 0 };//用来记录是哪一条信息被搜寻到
searchData(data, find, schres);
if (schres[0] == 0)
{
return -1;
}
else if (schres[0] == 1)
{
return schres[1];
}
else
{
int i;
outputSearchData(data, schres);
printf("请输入你要删除第几条数据:\n");
scanf("%d", &i);
if (i < 1 || i > schres[0])
{
return -1;
}
return schres[i];
}
}
//保存数据
int saveData(MailLists allData, const char * filename)
{
FILE * pf = fopen(filename, "wb");
if (pf == NULL)//文件打开失败
{
return 1;
}
fwrite(&allData.count, sizeof(int), 1, pf);//将通讯录信息的数量写入
fwrite(allData.allMsg, sizeof(struct MailList), allData.count, pf);//将通讯录信息写入
fclose(pf);
return 0;
}
//读取数据
int loadData(MailLists * allData, const char * filename)
{
FILE * pf = fopen(filename, "rb");
if (pf == NULL)
{
return 1;
}
fread(&allData->count, sizeof(int), 1, pf);//先读入通讯录的数量
if (allData->count > PERSPACE)
{
allData->limit = (allData->count / PERSPACE + 1) * PERSPACE;
allData->allMsg = (struct MailList *)realloc(allData->allMsg, allData->limit * sizeof(struct MailList));
}
else
{
allData->limit = PERSPACE;
}
fread(allData->allMsg, sizeof(struct MailList), allData->count, pf);//将通讯录信息读入
fclose(pf);
return 0;
}
通讯录的头文件(MailList.h)
#ifndef _MailList_H
#define _MailList_H
//声明一般放在头文件里
#define PERSPACE 100
#define FILENAME "maillist.txt"
enum{
ADD_MSG = 1,
DELETE_MSG,
SEARCH_MSG,
CHANGE_MSG,
DISPLAY_MSG,
EMPTY_MSG,
SAVE_FILE
};
//结构体 struct MailList 的声明
struct MailList{
char name[50]; //名字
char gender; //性别
char telnum[30];//电话
char addr[200]; //住址
int age; //年龄
};
//声明结构体MailLists
typedef struct{
struct MailList * allMsg;//声明结构体指针变量 allMsg
int count;
int limit;
}MailLists;
void initMailList(MailLists * data);
void inputData(struct MailList * oneData);
void addMailList(MailLists * data, struct MailList oneData);
void destoryMailList(MailLists * data);
void searchData(MailLists data, char * find, int * searchres);
void deleteOneData(MailLists * data, int n);
void outputData(MailLists data);
void outputSearchData(MailLists data, int * outputdata);
int catchOneData(MailLists data, char *find);
int saveData(MailLists allData, const char * filename);
int loadData(MailLists * allData, const char * filename);
#endif /* _MailList_H */