目录
导言
在本篇博客中,我们将一起剖析一个基于C语言编写的简易通讯录管理系统的源代码。该系统具备添加、删除、查找、修改、显示和排序联系人信息的核心功能。现在让我们逐一解析主程序(main.c)和功能函数实现文件(fun.c)中的关键代码段。
通讯录思想
-
数据结构设计(本篇不涉及到):
- 设计一个适合存储联系人信息的数据结构,例如在给出的代码中,我们定义了一个名为
Information
的结构体,它包含了姓名、电话号码、性别、地址和年龄等字段。 - 为了存储多个联系人,又创建了一个名为
contact
的结构体,它包含了一个Information
类型的数组和一个记录当前联系人总数的size
字段。
- 设计一个适合存储联系人信息的数据结构,例如在给出的代码中,我们定义了一个名为
-
功能模块:
- 初始化:创建通讯录时对其进行初始化,通常包括清空存储空间和设置联系人数为0。
- 添加联系人:接收用户输入的联系人信息并将其存入通讯录结构体中。
- 删除联系人:根据用户输入的姓名查找联系人并从通讯录中移除。
- 查找联系人:根据姓名查找并返回联系人信息。
- 修改联系人:查找指定联系人并允许用户更新其信息。
- 显示联系人:输出通讯录中所有联系人或特定联系人的详细信息。
- 排序联系人:提供一种排序方法(例如按姓名升序排列)对通讯录中的联系人进行排序。
-
用户交互:
- 创建一个菜单系统,让用户通过数字选择执行不同的操作。
- 提供适当的提示信息,引导用户正确输入数据,并对用户输入进行有效性验证。
-
异常处理:
- 针对可能出现的错误情况(如通讯录已满无法添加新联系人、查找的联系人不存在等)进行处理,并向用户提供友好的反馈信息。
-
编译器兼容性:
- 使用预处理器指令
#define _CRT_SECURE_NO_WARNINGS 1
避免Visual Studio等编译器针对某些不安全的C标准库函数发出警告。
- 使用预处理器指令
-
头文件(text.h):
- 在头文件中声明所需的结构体、枚举类型和函数原型,以便在不同源文件之间共享这些定义。
通过以上各个组成部分的设计和实现,即可构建一个基本的简易通讯录管理系统。
代码(注释)
下面代码注意看注释
text.h 头文件
#pragma once
#include<stdio.h>
#include<string.h>
#define NAME_ 20 // 姓名最大长度
#define PHONT_ 20 // 电话号码最大长度
#define ADD_ress_ 50 // 地址最大长度
#define Num 1000 // 最大联系人数限制
// 结构体声明
struct Information {
char name[NAME_];
char phone[PHONT_];
char sex[5];
char addr[ADD_ress_];
int age;
};
struct contact {
struct Information set[Num]; // 用于存储联系人的数组
int size; // 记录当前通讯录中的联系人数
};
// 枚举类型,对应菜单选项
enum MyEnum {
EXIT, // 0
ADD, // 1
DEL, // 2
FIND, // 3
REV, // 4
DISP, // 5
SORT // 6
};
// 函数声明
void initialize(struct contact* ps);
void addition(struct contact* ps);
void DEL_play(struct contact* ps);
void FIND_play(const struct contact* ps);
void REV_play(struct contact* ps);
void SORT_play(struct contact* ps);
void display(const struct contact* ps);
main.c 主程序
#define _CRT_SECURE_NO_WARNINGS 1
#include"text.h"
//菜单
void menu() {
printf(" ############################\n");
printf(" #*****1.添加 2.删除******#\n");
printf(" #*****3.查找 4.修改******#\n");
printf(" #*****5.显示 6.排序******#\n");
printf(" ****** 0.退出 ******\n");
printf(" ############################\n");
}
int main() {
int input = 0;
struct contact con;
//初始化
initialize(&con);
do
{
menu();
scanf("%d", &input);
switch (input)
{
case ADD:
addition(&con);
break;
case DEL:
DEL_play(&con);
break;
case FIND:
FIND_play(&con);
break;
case REV:
REV_play(&con);
break;
case DISP:
display(&con);
break;
case SORT:
SORT_play(&con);
break;
case EXIT:
break;
default:
printf("选择错误\n");
break;
}
} while (input);
return 0;
}
fun.c 功能函数实现
// 引入安全警告抑制宏,防止使用不安全的C运行时函数
#define _CRT_SECURE_NO_WARNINGS 1
// 包含头文件text.h,这里假设它包含了struct contact等相关定义
#include "text.h"
// 查找函数,输入一个指向contact结构体数组的指针和一个姓名字符串,返回该姓名在数组中的索引位置,
// 若未找到则返回-1
static int FIND_un(const struct contact* ps, char name[NAME_]) {
for (int i = 0; i < ps->size; i++) {
if (0 == strcmp(ps->set[i].name, name)) { // 使用strcmp比较姓名是否相等
return i; // 相等则返回当前索引
}
}
return -1; // 遍历完数组还未找到,则返回-1
}
// 初始化函数,清空contact结构体数组中的所有数据并将记录数量设为0
void initialize(struct contact* ps) {
memset(ps->set, 0, sizeof(ps->set)); // 使用memset填充数组为0,确保清除原有数据
ps->size = 0; // 设置当前通讯录的记录数量为0
}
// 添加联系人信息到通讯录
void addition(struct contact* ps) {
if (ps->size == Num) { // 检查通讯录是否已满
printf("通讯录已满,无法添加\n");
} else {
// 提示并获取用户输入的各项联系人信息
printf("请输入名字;>");
scanf("%s", ps->set[ps->size].name);
printf("请输入年龄;>");
int age;
while (scanf("%d", &age) != 1 || getchar() != '\n') { // 确保输入的是整数且以换行符结束
printf("无效输入!请确保您输入的是整数。\n请输入年龄;>");
while (getchar() != '\n'); // 清理输入缓存至下一个换行符
}
ps->set[ps->size].age = age;
printf("请输入电话;>");
scanf("%s", &(ps->set[ps->size].phone));
printf("请输入性别;>");
scanf("%s", ps->set[ps->size].sex);
printf("请输入地址;>");
scanf("%s", ps->set[ps->size].addr);
ps->size++; // 添加完成后增加通讯录记录数量
printf("添加成功!\n");
}
}
// 删除联系人信息
void DEL_play(struct contact* ps) {
char name[NAME_];
printf("请输入你要删除的姓名>");
scanf("%s", &name);
int pos = FIND_un(ps, name); // 获取要删除联系人在数组中的索引
if (pos == -1) {
printf("通讯录没有此人\n");
} else {
// 将删除位置之后的所有联系人信息前移一位
for (int i = pos; i < ps->size - 1; i++) {
ps->set[i] = ps->set[i + 1];
}
ps->size--; // 删除联系人后减小通讯录记录数量
printf("删除成功!\n");
}
}
// 查找联系人信息
void FIND_play(const struct contact* ps) {
char name[NAME_];
printf("请输入你要查找的姓名>");
scanf("%s", &name);
int pos = FIND_un(ps, name);
if (pos == -1) {
printf("通讯录没有此人\n");
} else {
// 打印表头
printf("%5s\t%5s\t%12s\t%5s\t%20s\n", "名字", "年龄", "电话", "性别", "地址");
// 打印找到的联系人信息
printf("%5s\t%5d\t%12s\t%5s\t%20s\n",
ps->set[pos].name,
ps->set[pos].age,
ps->set[pos].phone,
ps->set[pos].sex,
ps->set[pos].addr);
printf("\n");
}
}
// 修改联系人信息
void REV_play(struct contact* ps) {
char name[NAME_];
printf("请输入你要修改的姓名>");
scanf("%s", &name);
int pos = FIND_un(ps, name);
if (pos == -1) {
printf("通讯录没有此人\n");
} else {
// 提示并获取用户输入的新联系人信息
printf("请输入名字;>");
scanf("%s", ps->set[pos].name);
printf("请输入年龄;>");
int age;
while (scanf("%d", &age) != 1 || getchar() != '\n') {
printf("无效输入!请确保您输入的是整数。\n请输入年龄;>");
while (getchar() != '\n');
}
ps->set[pos].age = age;
printf("请输入电话;>");
scanf("%s", &(ps->set[pos].phone));
printf("请输入性别;>");
scanf("%s", ps->set[pos].sex);
printf("请输入地址;>");
scanf("%s", ps->set[pos].addr);
printf("修改成功!\n");
}
}
// 对通讯录进行升序排序(基于姓名)
void SORT_play(struct contact* ps) {
if (ps->size == 0) {
printf("通讯录为空\n");
} else {
// 使用冒泡排序算法对联系人数组按姓名进行升序排列
for (int i = 0; i < ps->size - 1; i++) {
for (int j = 0; j < ps->size - 1 - i; j++) {
if (strcmp(ps->set[j].name, ps->set[j + 1].name) > 0) {
// 交换两个相邻元素的位置
struct Information tmp;
tmp = ps->set[j];
ps->set[j] = ps->set[j + 1];
ps->set[j + 1] = tmp;
}
}
}
printf("排序成功!\n");
}
}
// 显示通讯录中的所有联系人信息
void display(const struct contact* ps) {
if (ps->size == 0) {
printf("通讯录为空\n");
} else {
// 打印表头
printf("%5s\t%5s\t%12s\t%5s\t%20s\n", "名字", "年龄", "电话", "性别", "地址");
// 遍历并打印通讯录中所有联系人信息
for (int i = 0; i < ps->size; i++) {
printf("%5s\t%5d\t%12s\t%5s\t%20s\n",
ps->set[i].name,
ps->set[i].age,
ps->set[i].phone,
ps->set[i].sex,
ps->set[i].addr);
}
printf("\n");
}
}
我注释上写的很清楚了