前言
C语言实现通讯录,包括增删改查以及动态开辟内存,写入文件等功能
一、注意
- 在通讯录菜单栏使用枚举
- 定义PeoInfo类型时,每个结构体类型的成员也使用枚举来确定长度
- 刚开始动态开辟3个PeoInfo类型的内存
- 若通讯录满员,则每次动态开辟2个PeoInfo类型的内存
- 每次退出通讯录,都会将现在已经存在的通讯录内容写入当前目录下的.txt文件中
- 每次重新进入通讯录,在初始化阶段会自动读取.txt文件,并存放到内存中,若内存不足,会自动增容,
二、源码
1. test.c源文件
#define _CRT_SECURE_NO_WARNINGS
#include "contact.h"
enum
{
QUIT,
ADD,
DEL,
MODIFY,
SEARCH,
SHOW,
SORT
};
void menu()
{
printf("*******************************\n");
printf("***** 1. Add 2. Del ******\n");
printf("***** 3. Modify 4. Search *****\n");
printf("***** 5. Show 6. Sort *****\n");
printf("***** 0. Quit *****\n");
printf("*******************************\n");
}
int main()
{
int input = 0;
// 创建变量
Contact con = { 0 };
// 初始化通讯录信息
InitContact(&con);
do
{
menu();
printf("请选择:>");
scanf("%d", &input);
switch (input)
{
case ADD:
AddContact(&con);
break;
case DEL:
DelContact(&con);
break;
case MODIFY:
ModifyContact(&con);
break;
case SEARCH:
SearchContact(&con);
break;
case SHOW:
ShowContact(&con);
break;
case SORT:
SortContact(&con);
break;
case QUIT:
SaveContact(&con);
DestoryContact(&con);
printf("退出通讯录!!!\n");
break;
default :
printf("输入错误!!!\n");
break;
}
} while (input);
return 0;
}
2. contact.h头文件
#pragma once
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include <assert.h>
enum
{
MAX_NAME = 20,
MAX_SEX = 5,
MAX_TELE = 12,
MAX_ADDR = 30,
DEFAULT_SZ = 3,
INC_SZ = 2
};
typedef struct PeoInfo
{
char name[MAX_NAME];
char sex[MAX_SEX];
char tele[MAX_TELE];
char addr[MAX_ADDR];
int age;
}PeoInfo;
typedef struct Contact
{
PeoInfo* data;
int count; // 人物数量
int capacity; // 通讯录容量
}Contact;
// 初始化通讯录信息
void InitContact(Contact* ps);
// 增加通讯录信息
void AddContact(Contact* ps);
// 删除通讯录信息
void DelContact(Contact* ps);
// 显示通讯录信息
void ShowContact(Contact* ps);
// 修改通讯录信息
void ModifyContact(Contact* ps);
// 查找指定联系人信息
void SearchContact(Contact* ps);
// 排序通讯录
void SortContact(Contact* ps);
// 释放开辟空间
void DestoryContact(Contact* ps);
// 保存通讯录信息
void SaveContact(Contact* ps);
// 加载通讯录信息
void LoadContact(Contact* ps);
3. contact.c源文件
#define _CRT_SECURE_NO_WARNINGS
#include "contact.h"
void CheckCap(Contact* ps)
{
if (ps->count == ps->capacity)
{
PeoInfo* tmp = (PeoInfo*)realloc(ps->data, (INC_SZ + ps->capacity) * sizeof(PeoInfo));
if (NULL == tmp)
{
perror("realloc");
return;
}
ps->data = tmp;
tmp = NULL;
ps->capacity += INC_SZ;
printf("增容成功!!!\n");
}
}
void LoadContact(Contact* ps)
{
FILE* pfread = fopen("contact.txt", "rb");
if (pfread == NULL)
{
perror("LoadContact");
return;
}
PeoInfo tmp = { 0 };
while (fread(&tmp, sizeof(PeoInfo), 1, pfread) == 1)
{
CheckCap(ps);
ps->data[ps->count] = tmp;
ps->count++;
}
fclose(pfread);
pfread = NULL;
}
// 初始化信息函数
void InitContact(Contact* ps)
{
assert(ps);
ps->capacity = DEFAULT_SZ;
ps->count = 0;
ps->data = (PeoInfo*)calloc(DEFAULT_SZ, sizeof(PeoInfo));
if (ps->data == NULL)
{
perror("InitContact");
return;
}
// 加载到通讯录中
LoadContact(ps);
}
// 增加信息函数
void AddContact(Contact* ps)
{
assert(ps);
// 判断增容
CheckCap(ps);
// 增加内容
printf("请输入姓名:>");
scanf("%s", ps->data[ps->count].name);
printf("请输入年龄:>");
scanf("%d", &(ps->data[ps->count].age));
printf("请输入性别:>");
scanf("%s", ps->data[ps->count].sex);
printf("请输入电话:>");
scanf("%s", ps->data[ps->count].tele);
printf("请输入住址:>");
scanf("%s", ps->data[ps->count].addr);
ps->count++;
printf("添加成功!!!\n");
}
int FindByName(Contact* ps)
{
char name[MAX_NAME];
printf("请输入要操作人的姓名:");
scanf("%s", name);
int i = 0;
for (i = 0; i < ps->count; i++)
{
if (strcmp(ps->data[i].name, name) == 0)
{
return i;
}
}
return -1;
}
// 删除信息函数
void DelContact(Contact* ps)
{
assert(ps);
if (ps->count == 0)
{
printf("通讯录为空,无法删除!!!\n");
return;
}
// 根据名字找信息
int pos = FindByName(ps);
if (-1 == pos)
{
printf("要删除的信息不存在!!!\n");
return;
}
int i = 0;
for (i = pos; i < ps->count; i++)
{
ps->data[i] = ps->data[i + 1];
}
ps->count--;
printf("删除成功!!!\n");
}
// 显示通讯录信息函数
void ShowContact(Contact* ps)
{
assert(ps);
printf("%-20s %-5s %-5s %-12s %-30s\n", "名字", "年龄", "性别", "电话", "地址");
int i = 0;
for (i = 0; i < ps->count; i++)
{
printf("%-20s %-5d %-5s %-12s %-30s\n", ps->data[i].name,
ps->data[i].age,
ps->data[i].sex,
ps->data[i].tele,
ps->data[i].addr);
}
}
// 修改通讯录信息
void ModifyContact(Contact* ps)
{
assert(ps);
int pos = FindByName(ps);
if (-1 == pos)
{
printf("要修改的人信息不存在!!!\n");
return;
}
printf("请输入姓名:>");
scanf("%s", ps->data[pos].name);
printf("请输入年龄:>");
scanf("%d", &(ps->data[pos].age));
printf("请输入性别:>");
scanf("%s", ps->data[pos].sex);
printf("请输入电话:>");
scanf("%s", ps->data[pos].tele);
printf("请输入住址:>");
scanf("%s", ps->data[pos].addr);
printf("修改信息成功!!!\n");
}
// 查找指定联系人信息函数
void SearchContact(const Contact* ps)
{
assert(ps);
int pos = FindByName(ps);
if (-1 == pos)
{
printf("要查中的联系人不存在!!!\n");
return;
}
printf("%-20s %-5s %-5s %-12s %-30s\n", "名字", "年龄", "性别", "电话", "地址");
printf("%-20s %-5d %-5s %-12s %-30s\n", ps->data[pos].name,
ps->data[pos].age,
ps->data[pos].sex,
ps->data[pos].tele,
ps->data[pos].addr);
}
int cmp_by_name(const void* e1, const void* e2)
{
return strcmp(((PeoInfo*)e1)->name, ((PeoInfo*)e2)->name);
}
// 排序通讯录函数
void SortContact(Contact* ps)
{
assert(ps);
qsort(ps->data, ps->count, sizeof(PeoInfo), cmp_by_name);
printf("排序成功!!!\n");
}
// 释放开辟空间函数
void DestoryContact(Contact* ps)
{
assert(ps);
free(ps->data);
ps->data = NULL;
}
// 保存通讯录信息函数
void SaveContact(Contact* ps)
{
FILE* pfwrite = fopen("contact.txt", "wb");
if (pfwrite == NULL)
{
perror("SaveContact");
}
int i = 0;
for (i = 0; i < ps->count; i++)
{
fwrite(ps->data+i, sizeof(PeoInfo), 1, pfwrite);
}
fclose(pfwrite);
pfwrite = NULL;
}
总结
C语言实现通讯录,包括增删改查以及动态开辟内存,写入文件等功能