通讯录项目用于针对c语言初学者练手使用,涉及到数组,指针,结构体,枚举等知识。
通讯录需要实现对用户信息的存储,新增,删除,查找,排序,修改等内容,每位用户的信息包含姓名,性别,年龄,电话号码,住址等信息。因此需要创建一个用户信息结构体,结构体成员包含姓名,性别,年龄,电话号码,住址信息。
(1)在初级阶段由于无法让程序自动开辟内存,因此需要额外创建一个结构体,结构体成员包含用户信息成员变量,当前结构体指针变量(用于指向存储位置),成员信息最大存储能力。
(2)当初级阶段实现后,需要利用动态内存管理的方法,使开辟用户信息的内存可以实现自动开辟。
(3)当完成上述两个阶段后,需要利用文件存储的方式,将已经存储在通讯录中的用户信息存储在磁盘中,当打开通讯录文件后,自动读取数据,同时在关闭通讯录时自动保存通讯录。
由于实现通讯录项目需要许多头文件和函数,因此需要将项目分为两大部分:头文件和.cpp文件,头文件用于声明一些函数,引入一些库函数,创建一些宏定义和结构体。.cpp文件用于对函数进行实现。
需要引入两个头文件:一个公共头文件utili.h 一个通讯录头文件contact.h。其中公共头文件引入一些库函数。通讯录头文件负责声明通讯录中需要用到的函数,创建宏定义和结构体
需要引入两个.cpp文件:一个函数实现文件Contact.cpp 一个主函数文件MainContact.cpp。
注:(1)表示这段代码是实现项目整体分析中第一个阶段,(2) (3)相同
//utili.h
#ifndef _UTILI_H_
#define _UTILI_H_
#include
#include
#include
#include
#include
#endif /* _UTILI_H_ */
//
#ifndef _CONTACT_H_
#define _CONTACT_H_
//Contact.h
#include"utili.h"//首先引入公共头文件
enum {QUIT, ADD, DEL, FIND, MODIFY, SHOW, CLEAR, SORT};//定义菜单中的选项
#define MAX_NAME_SIZE 10 //定义用户姓名最大字符数
#define MAX_SEX_SIZE 3 //定义用户性别最大字符数
#define MAX_AGE_SIZE 100 //定义用户年龄最大数
#define MAX_TEL_SIZE 12 //定义电话号码最大位数
#define MAX_ADDRESS_SIZE 128 //定义地址信息最大字符数
#define MAX_CONTACT_SIZE 8 //定义最大存储通讯录用户个数(1)
#define DEFAULT_CONTACT_SIZE 2 //定义默认存储通讯录用户个数(2)
//打印菜单
void Menu();
//定义通讯录人员信息
typedef struct PersonInfo
{
char name[MAX_NAME_SIZE];
char sex[MAX_SEX_SIZE];
int age;
char tel[MAX_TEL_SIZE];
char address[MAX_ADDRESS_SIZE];
}PersonInfo;
//定义通讯录结构
typedef struct Contact
{
//PersonInfo cont[MAX_CONTACT_SIZE];(1)
PersonInfo *cont(2)//需要动态开辟空间,因此设为指针变量
size_t capacity; //通讯录最大存储用户个数
size_t size; //通讯录当前指针指向位置
}Contact;
//初始化通讯录
void InitContact(Contact* pcont);
//查验通讯录是否已满
bool IsFullContact(Contact* pcont);
//增加通讯录
void AddContact(Contact* pcont);
//显示通讯录
void ShowContact(Contact* pcont);
//查找通讯录信息
int FindContact(Contact* pcont);
//清除通讯录
void ClearContact(Contact* pcont);
//删除通讯录成员
void DelContact(Contact* pcont);
//修改通讯录成员
void ModifyContact(Contact* pcont);
//对通讯录成员进行排序(bubble)
void SortContact_bubble(Contact* pcont);
//使用快排函数(qsort)
void SortContact_qsort(Contact* pcont);
#endif /* _UTILI_H_ */
//Contact.cpp
#define _CRT_SECURE_NO_WARNINGS 1
#include"contact.h" //引入通讯录头文件
//打印菜单
void Menu()
{
printf("********************通 讯 录***********************\n");
printf("* [1]Add [2]Del *\n");
printf("* [3]Find [4]Modif *\n");
printf("* [5]Show [6]Clear *\n");
printf("* [7]Sort [0]Quit *\n");
printf("********************通 讯 录***********************\n");
}
//初始化通讯录
void InitContact(Contact* pcont)
{
assert(pcont != NULL);
//memset(pcont->cont, 0, sizeof(PersonInfo) * MAX_CONTACT_SIZE);(1)
pcont->cont = (PersonInfo*)malloc(sizeof(PersonInfo)*DEFAULT_CONTACT_SIZE);(2)
memset(pcont->cont, 0,sizeof(PersonInfo) * DEFAULT_CONTACT_SIZE);(2)
pcont->capacity = MAX_CONTACT_SIZE;(1)
pcont->capacity = DEFAULT_CONTACT_SIZE;(2)
pcont->size = 0;
}
static bool _Inc(Contact* pcont)//(2)
{
PersonInfo* new_cont = (PersonInfo*)realloc(pcont->cont, sizeof(PersonInfo) * pcont->capacity * 2); //使用realloc进行扩容
if (new_cont == NULL)
{
printf("扩容失败,内存不足\n");
return false;
}
pcont->cont = new_cont;//扩容成功,修改cont指针
pcont->capacity *= 2;//扩容成功,修改容量
return true;
}
//判断通讯录是否已满
bool IsFullContact(Contact* pcont)
{
assert(pcont != NULL);
return pcont->size >= pcont->capacity;
}
//添加通讯录用户
void AddContact(Contact* pcont)
{
assert(pcont != NULL);
//if (IsFullContact(pcont))//(1)
if(IsFullContact(pcont) && !_Inc(pcont))//(2)
{
printf("通讯录空间已满,不能新增信息");
return;
}
printf("姓名:>");
scanf("%s", pcont->cont[pcont->size].name);
printf("性别:>");
scanf("%s", pcont->cont[pcont->size].sex);
printf("年龄:>");
scanf("%d", &pcont->cont[pcont->size].age);
printf("电话号码:>");
scanf("%s", pcont->cont[pcont->size].tel);
printf("地址:>");
scanf("%s", pcont->cont[pcont->size].address);
pcont->size++;
printf("添加完成!!!\n");
}
//展示当前通讯录已存用户信息
void ShowContact(Contact* pcont)
{
assert(pcont != NULL);
printf("***************************************************\n");
printf("*%-8s%-7s%-6s%-13s%s\n", "姓名", "性别", "年龄", "电话", "地址");
for (int i = 0; i < pcont->size; i++)
{
printf("*%-8s%-7s%-6d%-13s%s\n",pcont->cont[i].name,
pcont->cont[i].sex,
pcont->cont[i].age,
pcont->cont[i].tel,
pcont->cont[i].address);
}
}
//查找通讯录成员
int FindContact(Contact* pcont)
{
assert(pcont != NULL);
printf("请输入要查找的姓名:>");
char name[MAX_NAME_SIZE] = {0};
scanf("%s", name);
for (int i = 0; i < pcont->size; i++)
{
if (strcmp(pcont->cont[i].name, name) == 0)
{
printf("*%-8s%-7s%-6s%-13s%s\n", "姓名", "性别", "年龄", "电话", "地址");
printf("*%-8s%-7s%-6d%-13s%s\n",pcont->cont[i].name,
pcont->cont[i].sex,
pcont->cont[i].age,
pcont->cont[i].tel,
pcont->cont[i].address);
return i;
}
}
printf("对不起,没找到\n");
return -1;
}
//清除通讯录
void ClearContact(Contact* pcont)
{
assert(pcont != NULL);
pcont->size = 0;
printf("清除完成!!!\n");
}
//删除通讯录成员
void DelContact(Contact* pcont)
{
assert(pcont != NULL);
printf("请输入要删除的名字:>");
char name[MAX_NAME_SIZE] = { 0 };
scanf("%s", name);
int i;
for (i = 0; i < pcont->size; i++)
{
if (strcmp(pcont->cont[i].name, name) == 0)
break;
}
if (i >= pcont->size)
{
printf("对不起,您所删除的名字不存在\n");
return;
}
for (int k = i; k < pcont->size - 1; k++)
pcont->cont[k] = pcont->cont[k + 1];
pcont->size--;
printf("删除完成!!!\n");
}
//修改通讯录成员
void ModifyContact(Contact* pcont)
{
assert(pcont != NULL);
printf("请输入要修改的名字:>");
char name[MAX_NAME_SIZE] = { 0 };
scanf("%s", name);
int i;
for (i = 0; i < pcont->size; i++)
{
if (strcmp(pcont->cont[i].name, name) == 0)
break;
}
if (i >= pcont->size)
{
printf("对不起,您所要修改的名字不存在\n");
return;
}
printf("你要修改什么信息(1-姓名 2-性别 3-年龄 4-电话 5-住址)\n");
int select;
scanf("%d", &select);
switch (select)
{
case 1:
printf("请输入要修改的名字:>");
scanf("%s", pcont->cont[i].name);
break;
case 2:
printf("请输入要修改的性别:>");
scanf("%s", pcont->cont[i].sex);
break;
case 3:
printf("请输入要修改的年龄:>");
scanf("%d", &pcont->cont[i].age);
break;
case 4:
printf("请输入要修改的电话:>");
scanf("%s", pcont->cont[i].tel);
break;
case 5:
printf("请输入要修改的住址:>");
scanf("%s", pcont->cont[i].address);
break;
}
printf("修改完成!!!\n");
}
//对通讯录成员进行排序
//方法一利用冒泡排序
void SortContact_bubble(Contact* pcont)
{
//采用冒泡排序
assert(pcont != NULL);
//qsort(pcont, pcont->size, sizeof(pcont->cont[0]), compar);
for (int i = 0; i < pcont->size-1; i++)
{
for (int j = 0; j < pcont->size - 1 - i; j++)
{
if (strcmp(pcont->cont[j].name, pcont->cont[j + 1].name) > 0 )
{
PersonInfo tmp = pcont->cont[j];
pcont->cont[j] = pcont->cont[j + 1];
pcont->cont[j + 1] = tmp;
}
}
}
printf("排序完成!!!\n");
}
//方法二利用快排函数
int compar_name(Contact* pcont->cont.name1, pcont->cont.name2)
{
return strcmp(pcont->cont.name1, pcont->cont.name2);
}
void SortContact_qsort(Contact* pcont)
{
assert(pcont != NULL);
qsort(pcont, pcont->size, sizeof(pcont->cont[0]), compar_name);
}
//摧毁通讯录目的是为了防止内存泄漏
void DestoryContact(Contact* pcont)
{
assert(pcont != NULL);
free(pcont->cont);//释放内存
pcont->cont = NULL;//预防野指针
pcont->capacity = pcont->size = 0;
}
//存储通讯录(3)
void SaveContact(Contact* pcont)
{
assert(pcont != NULL);
FILE* fp = fopen("cont.dat", "w");
if (fp == NULL)
{
printf("写入通讯录文件失败\n");
return;
}
for (int i = 0; i < pcont->size; i++)
{
fprintf(fp, "*%-8s%-7s%-6d%-13s%s\n", pcont->cont[i].name,
pcont->cont[i].sex,
pcont->cont[i].age,
pcont->cont[i].tel,
pcont->cont[i].address);
}
fclose(fp);
}
//数据的加载(3)
void LoadContact(Contact* pcont)
{
assert(pcont != NULL);
FILE* fp = fopen("\cont.dat", "r");
if (fp == NULL);
{
printf("读取通讯录文件失败\n");
return;
}
int idx = 0;
while(1)
{
if (IsFullContact(pcont) && !_Inc(pcont))
break;
int res = fscanf(fp, "*%s %s %d %s %s\n", pcont->cont[idx].name,
pcont->cont[idx].sex,
&pcont->cont[idx].age,
pcont->cont[idx].tel,
pcont->cont[idx].address);
if (res == EOF)
break;
idx++;
pcont->size++;
}
fclose(fp);
}
//MainContact.cpp
#define _CRT_SECURE_NO_WARNINGS 1
#include"contact.h"//引入通讯录头文件
void main()
{
Contact cont;//先进行通讯录的创建和初始化
InitContact(&cont);
int select = 1;
while (select)
{
Menu(); //打印开始菜单
printf("请选择:>");
scanf("%d", &select);
if (select == QUIT)
break;
switch (select)
{
case ADD:
IsFullContact(&cont); //判断通讯录是否已满
AddContact(&cont); //添加用户信息
break;
case DEL:
DelContact(&cont); //删除用户信息
break;
case FIND:
FindContact(&cont); //查找用户信息
break;
case MODIFY:
ModifyContact(&cont); //修改用户信息
break;
case SHOW:
ShowContact(&cont); //展示通讯录内容
break;
case CLEAR:
ClearContact(&cont); //清除通讯录
break;
case SORT:
SortContact_bubble(&cont); //对通讯录进行排序
break;
}
}
SaveContact(&cont);
DestoryContact(&cont);
}
选择1,添加用户
选择5,展示
选择4,修改用户信息
选择2,删除用户信息
选择7,对用户信息进行排序,注意(这里的排序是通过冒泡排序对用户姓名进行排序,用户姓名排序的原理是利用其对应的ASCII码值进行排序),通过对排序函数的修改,可以实现通过年龄,电话住址等信息进行排序。
选择3,进行信息查找
如果查找的姓名不存在,会报找不到的错误