前言
本文将详细分析一个功能完备的C语言通讯录管理系统,涵盖动态扩容、文件存储、用户登录等核心功能,并提供完整实现思路和代码解析。
一、项目概述
这个通讯录管理系统是一个综合性的C语言项目,实现了以下核心功能:
基本通讯录功能:添加、删除、修改、查询、打印、排序联系人
用户系统:注册、登录、找回密码
文件存储:通讯录数据和用户数据的持久化存储
界面设计:心形欢迎界面、系统时间显示
动态扩容:根据联系人数量自动调整存储空间
二、系统架构设计
文件结构
contact.h # 通讯录结构体和函数声明
contact.c # 通讯录核心功能实现
New contact.h # 用户系统结构体和函数声明
New contact.c # 用户系统功能实现
main.c # 程序入口和主流程
users.txt # 用户数据存储文件
contact.dat # 通讯录数据存储文件
核心数据结构
// 联系人信息
struct PeoInfo {
char name[MAX_NAME]; // 姓名
char phone[MAX_PHONE]; // 电话
char sex[MAX_SEX]; // 性别
char address[MAX_ADDRESS]; // 地址
int age; // 年龄
};
// 通讯录结构
struct contact {
struct PeoInfo* data; // 联系人数组指针
int size; // 当前联系人数量
int capacity; // 通讯录容量
};
// 用户信息
typedef struct The_users {
char id[11]; // 账号
char pwd[20]; // 密码
char name[15]; // 姓名
char sex; // 性别
long phone; // 电话
} users;
三、核心功能实现
1. 动态扩容机制
通讯录采用动态数组实现,当联系人数量达到当前容量时自动扩容:
#define DEFAULT_SZ 3 // 默认容量
void CheckCapacity(struct contact* ps) {
if (ps->size == ps->capacity) {
// 每次增加2个位置的容量
struct PeoInfo* ptr = realloc(ps->data,
(ps->capacity + 2) * sizeof(struct PeoInfo));
if (ptr != NULL) {
ps->data = ptr;
ps->capacity += 2;
printf("增容成功!\n");
} else {
printf("增容失败!\n");
}
}
}
2. 文件存储与加载
通讯录数据持久化存储,程序启动时自动加载数据:
// 保存通讯录到文件
void Save_Contact(struct contact* ps) {
FILE* pfWrite = fopen("contact.dat", "wb");
if (pfWrite == NULL) {
perror("Save_Contact");
return;
}
for (int i = 0; i < ps->size; i++) {
fwrite(&(ps->data[i]), sizeof(struct PeoInfo), 1, pfWrite);
}
fclose(pfWrite);
}
// 从文件加载通讯录
void Load_Contact(struct contact* ps) {
FILE* pfRead = fopen("contact.dat", "rb");
if (pfRead == NULL) {
return; // 文件不存在时不报错
}
struct PeoInfo tmp = {0};
while (fread(&tmp, sizeof(tmp), 1, pfRead)) {
CheckCapacity(ps); // 确保容量足够
ps->data[ps->size] = tmp;
ps->size++;
}
fclose(pfRead);
}
3. 用户系统实现
用户注册流程
void registers() {
users a, b;
FILE* fp = fopen("users.txt", "r");
// 检查账号是否已存在
printf("请输入账号(六位数账号)\n");
scanf("%s", a.id);
while (fread(&b, sizeof(users), 1, fp)) {
if (strcmp(a.id, b.id) == 0) {
printf("此用户名已存在!\n");
fclose(fp);
return;
}
}
fclose(fp);
// 收集用户信息
printf("请输入姓名:\n");
scanf("%s", a.name);
// 性别验证
do {
printf("请输入性别(f(女)/m(男)):\n");
scanf(" %c", &a.sex);
} while(a.sex != 'f' && a.sex != 'm');
printf("请输入电话号码:\n");
scanf("%ld", &a.phone);
// 密码确认
char temp[20];
do {
printf("请输入密码(六位数字)\n");
scanf("%s", a.pwd);
printf("请确认密码\n");
scanf("%s", temp);
} while(strcmp(a.pwd, temp) != 0);
// 保存用户信息
fp = fopen("users.txt", "a");
fwrite(&a, sizeof(users), 1, fp);
fclose(fp);
printf("账号注册成功!\n");
}
用户登录流程
void Input_login() {
users a, b;
FILE* fp = fopen("users.txt", "r");
printf("请输入账号\n");
scanf("%s", a.id);
// 查找用户
while (fread(&b, sizeof(users), 1, fp)) {
if (strcmp(a.id, b.id) == 0) {
// 验证密码
do {
printf("请输入密码:\n");
scanf("%s", a.pwd);
if (strcmp(a.pwd, b.pwd) == 0) {
fclose(fp);
In(); // 进入通讯录主界面
return;
} else {
printf("密码不正确!\n");
}
} while(1);
}
}
printf("此用户名不存在!\n");
fclose(fp);
}
4. 通讯录核心功能
联系人添加
void Add_Contacter(struct contact* ps) {
CheckCapacity(ps); // 确保容量足够
printf("请输入名字:");
scanf("%s", ps->data[ps->size].name);
printf("请输入年龄:");
scanf("%d", &ps->data[ps->size].age);
printf("请输入性别:");
scanf("%s", ps->data[ps->size].sex);
printf("请输入电话:");
scanf("%s", ps->data[ps->size].phone);
printf("请输入地址:");
scanf("%s", ps->data[ps->size].address);
ps->size++;
printf("添加成功!\n");
}
联系人查询
void Find_Contacter(const struct contact* ps) {
char name[MAX_NAME];
printf("请输入你要查找的联系人的姓名:");
scanf("%s", name);
for (int i = 0; i < ps->size; i++) {
if (strcmp(ps->data[i].name, name) == 0) {
printf("%-20s\t%-4s\t%-5s\t%-12s\t%-20s\n",
"姓名", "年龄", "性别", "电话", "地址");
printf("%-20s\t%-4d\t%-5s\t%-12s\t%-20s\n",
ps->data[i].name,
ps->data[i].age,
ps->data[i].sex,
ps->data[i].phone,
ps->data[i].address);
return;
}
}
printf("要查找的人不存在!\n");
}
联系人排序
// 按姓名排序
int Conpare_ByName(const void *e1, const void *e2) {
return strcmp(((struct PeoInfo*)e1)->name,
((struct PeoInfo*)e2)->name);
}
// 按年龄排序
int Conpare_ByAge(const void* e1, const void* e2) {
return ((struct PeoInfo*)e1)->age - ((struct PeoInfo*)e2)->age;
}
void Sort_Contacter(struct contact* ps) {
printf("请选择排序方式:\n1.姓名\n2.年龄\n3.住址\n");
int input;
scanf("%d", &input);
switch (input) {
case 1:
qsort(ps->data, ps->size, sizeof(struct PeoInfo), Conpare_ByName);
break;
case 2:
qsort(ps->data, ps->size, sizeof(struct PeoInfo), Conpare_ByAge);
break;
case 3:
qsort(ps->data, ps->size, sizeof(struct PeoInfo), Conpare_ByAddress);
break;
default:
printf("无效选择\n");
return;
}
printf("排序成功!\n");
}
按照姓名排序
按照年龄排序
按照住址排序
5. 图形界面设计
心形欢迎界面
void paintheart() {
float y, x, a;
for (y = 1.5f; y > -1.5f; y -= 0.1f) {
for (x = -1.5f; x < 1.5f; x += 0.05f) {
a = x * x + y * y - 1;
putchar(a * a * a - x * x * y * y * y <= 0.0f ? '*' : ' ');
}
putchar('\n');
}
}
系统时间显示
void showtime() {
time_t timep;
struct tm *p;
time(&timep);
p = localtime(&timep);
printf("现在是 %d年%02d月%02d日 %02d:%02d:%02d\n",
1900 + p->tm_year,
1 + p->tm_mon,
p->tm_mday,
p->tm_hour,
p->tm_min,
p->tm_sec);
}
四、项目亮点与改进方向
项目亮点
模块化设计:清晰分离通讯录核心功能和用户系统
动态内存管理:智能扩容机制避免内存浪费
数据持久化:文件存储确保数据不丢失
用户友好界面:图形化界面提升用户体验
健壮性设计:关键操作增加输入验证
改进方向
密码加密存储:当前明文存储存在安全隐患
批量操作支持:添加批量导入/导出功能
模糊搜索:实现基于部分信息的联系人查找
数据备份机制:定期自动备份通讯录数据
跨平台支持:使用跨平台库增强可移植性
五、使用指南
初始账号:123456
初始密码:123789
编译运行:
gcc main.c contact.c "New contact.c" -o contact
./contact
六、总结
这个C语言通讯录项目综合运用了结构体、指针、文件操作、动态内存管理等核心技术,实现了功能较为完备的通讯录管理系统。通过模块化设计和良好的用户体验,展示了C语言在系统级应用开发中的强大能力。项目代码结构清晰,注释完善,可以作为大家在进行C语言项目开发的参考范例。也欢迎大家一起讨论改进项目。