48 C 语言实战项目——客户信息管理系统
目录
1 需求说明
1.1 主菜单
1.2 添加客户
1.3 显示客户列表
1.4 修改客户
1.5 删除客户
1.6 退出
2 流程分析
2.1 总流程图
2.2 添加客户流程图
2.3 显示客户列表流程图
2.4 改客户流程图
2.4.1 修改客户总体流程图
2.4.2 具体执行修改部分的流程图
2.5 删除客户流程图
2.6 退出流程图
3 代码实现
3.1 框架搭建
3.2 结构体与菜单页面的抽取
3.3 退出功能
3.4 显示客户列表功能
3.5 添加客户功能
3.6 删除客户功能
3.7 修改客户功能
4 最终优化后的代码
1 需求说明
1.1 主菜单
进入系统,展示主菜单,输入各功能对应的数字编号选择要进行的操作,如下图:
1.2 添加客户
输入1,进入“添加客户” 界面,需要填写姓名、性别、年龄、电话、邮箱这些信息,如下图:
1.3 显示客户列表
输入 4,进入“客户列表”,显示客户列表信息,如下图:
1.4 修改客户
输入 2,进入“修改客户”,首先要输入要修改客户的编号,然后填写信息,如下图:
1.5 删除客户
输入 3,进入“删除客户”,输入要删除客户的编号,再确认是否删除,如下图:
1.6 退出
输出 5,经过确认后退出系统,如下图:
2 流程分析
2.1 总流程图
2.2 添加客户流程图
2.3 显示客户列表流程图
2.4 改客户流程图
2.4.1 修改客户总体流程图
2.4.2 具体执行修改部分的流程图
2.5 删除客户流程图
2.6 退出流程图
3 代码实现
3.1 框架搭建
#include <stdio.h>int main()
{int loop = 1; // 控制循环是否继续的变量while (loop) // 主循环,用于显示菜单直到用户选择退出{// 显示菜单printf("\n\n\n--------------客户信息管理软件--------------");printf("\n 1 添 加 客 户");printf("\n 2 修 改 客 户");printf("\n 3 删 除 客 户");printf("\n 4 客 户 列 表");printf("\n 5 退 出");printf("\n请选择(1-5):");int selection; // 存储用户的选项// 使用 scanf 读取用户输入if (scanf("%d", &selection) != 1) // 如果输入不是整数{puts("无效的输入,请输入一个数字 (1-5)!"); // 提示错误信息// 清理输入缓冲区中的非数字字符while (getchar() != '\n');continue; // 跳过本次循环的剩余部分,重新开始循环}// 根据用户选择执行相应操作switch (selection){case 1:puts("添 加 客 户"); // 用户选择了添加客户break;case 2:puts("修 改 客 户"); // 用户选择了修改客户break;case 3:puts("删 除 客 户"); // 用户选择了删除客户break;case 4:puts("客 户 列 表"); // 用户选择了查看客户列表break;case 5:puts("退 出"); // 用户选择了退出程序loop = 0; // 设置 loop 为 0 以结束主循环break;default:puts("无效的选择,请重新选择!"); // 用户输入了不在 1-5 范围内的数字break;}}// 提示用户已退出软件puts("你退出了客户管理系统~");return 0; // 程序正常结束
}
3.2 结构体与菜单页面的抽取
#include <stdio.h>
#define MAX_CAPACITY 100 // 客户数量的最大值// 定义结构体数据类型来存储客户信息
struct Customer
{int id; // 客户编号char name[10]; // 客户名字char gender; // 性别,'f' 表示女,'m' 表示男int age; // 年龄char phone[20]; // 电话号码char email[40]; // 邮箱地址
};// 客户结构体数组,最多可以存储 100 个客户信息
struct Customer customers[MAX_CAPACITY];// 当前客户数量,用于索引数组
int customerNum = 0;// 显示菜单并处理用户选择的函数
void menu()
{int loop = 1; // 控制主循环是否继续的变量while (loop) // 主循环,持续显示菜单直到用户选择退出{// 显示菜单选项printf("\n\n\n--------------客户信息管理软件--------------");printf("\n 1 添 加 客 户");printf("\n 2 修 改 客 户");printf("\n 3 删 除 客 户");printf("\n 4 客 户 列 表");printf("\n 5 退 出");printf("\n请选择(1-5):");int selection; // 存储用户的选项// 使用 scanf 读取用户输入if (scanf("%d", &selection) != 1) // 如果输入不是整数{puts("无效的输入,请输入一个数字 (1-5)!"); // 提示错误信息// 清理输入缓冲区中的非数字字符while (getchar() != '\n');continue; // 跳过本次循环的剩余部分,重新开始循环}// 根据用户选择执行相应操作switch (selection){case 1:puts("添 加 客 户"); // 用户选择了添加客户break;case 2:puts("修 改 客 户"); // 用户选择了修改客户break;case 3:puts("删 除 客 户"); // 用户选择了删除客户break;case 4:puts("客 户 列 表"); // 用户选择了查看客户列表break;case 5:puts("退 出"); // 用户选择了退出程序loop = 0; // 设置 loop 为 0 以结束主循环break;default:puts("无效的选择,请重新选择!"); // 用户输入了不在 1-5 范围内的数字break;}}
}int main()
{menu(); // 调用菜单函数// 提示用户已退出软件puts("你退出了客户管理系统~");return 0; // 程序正常结束
}
3.3 退出功能
#include <stdio.h>
#define MAX_CAPACITY 100 // 客户数量的最大值// 定义结构体数据类型来存储客户信息
struct Customer
{int id; // 客户编号char name[10]; // 客户名字char gender; // 性别,'f' 表示女,'m' 表示男int age; // 年龄char phone[20]; // 电话号码char email[40]; // 邮箱地址
};int loop = 1; // 全局变量控制主循环是否继续的变量// 客户结构体数组,最多可以存储 100 个客户信息
struct Customer customers[MAX_CAPACITY];// 当前客户数量,用于索引数组
int customerNum = 0;// 确认退出函数
void confirmExit()
{puts("确认是否退出(Y/N):");char isExit;// 读取用户输入的确认信息while (1){if (scanf(" %c", &isExit) != 1) // %c 前面有空格,用于跳过前面的空白字符{puts("无效的输入,请输入 Y 或 N!"); // 提示错误信息// 清理输入缓冲区while (getchar() != '\n');continue; // 跳过本次循环}// 检查用户输入是否有效if (isExit == 'Y' || isExit == 'N'){break; // 结束循环}else{puts("你输入有误,请从新输入(Y/N):"); // 提示重新输入}}// 如果用户选择退出,设置循环标志为 0if (isExit == 'Y'){loop = 0;puts("欢迎你的再次访问^_^"); // 退出提示}
}// 显示菜单并处理用户选择的函数
void menu()
{while (loop) // 主循环,持续显示菜单直到用户选择退出{// 显示菜单选项printf("\n\n\n--------------客户信息管理软件--------------");printf("\n 1 添 加 客 户");printf("\n 2 修 改 客 户");printf("\n 3 删 除 客 户");printf("\n 4 客 户 列 表");printf("\n 5 退 出");printf("\n请选择(1-5):");int selection; // 存储用户的选项// 使用 scanf 读取用户输入if (scanf("%d", &selection) != 1) // 如果输入不是整数{puts("无效的输入,请输入一个数字 (1-5)!"); // 提示错误信息// 清理输入缓冲区中的非数字字符while (getchar() != '\n');continue; // 跳过本次循环的剩余部分,重新开始循环}// 根据用户选择执行相应操作switch (selection){case 1:puts("添 加 客 户"); // 用户选择了添加客户break;case 2:puts("修 改 客 户"); // 用户选择了修改客户break;case 3:puts("删 除 客 户"); // 用户选择了删除客户break;case 4:puts("客 户 列 表"); // 用户选择了查看客户列表break;case 5:confirmExit(); // 用户选择了退出程序break;default:puts("无效的选择,请重新选择!"); // 用户输入了不在 1-5 范围内的数字break;}}
}int main()
{menu(); // 调用菜单函数// 提示用户已退出软件puts("你退出了客户管理系统~");return 0; // 程序正常结束
}
3.4 显示客户列表功能
#include <stdio.h>
#include <string.h>#define MAX_CAPACITY 100 // 客户数量的最大值// 定义结构体数据类型来存储客户信息
struct Customer
{int id; // 客户编号char name[10]; // 客户名字char gender; // 性别,'f' 表示女,'m' 表示男int age; // 年龄char phone[20]; // 电话号码char email[40]; // 邮箱地址
};int loop = 1; // 全局变量控制主循环是否继续的变量// 客户结构体数组,最多可以存储 100 个客户信息
struct Customer customers[MAX_CAPACITY];// 当前客户数量,用于索引数组
int customerNum = 0;// 显示某个客户的信息
void showCustomer(struct Customer *custPtr)
{// 两种方式访问结构体指针成员// 第一种方式:(*custPtr).member// 第二种方式:custPtr->memberprintf("%d\t%s\t%c\t%d\t%s\t\t%s\n", (*custPtr).id, custPtr->name, custPtr->gender, custPtr->age, custPtr->phone, custPtr->email);
}// 显示客户列表的功能
void showView()
{if (customerNum < 1){puts("系统中没有任何客户的信息,请先添加!");}else{puts("-------------------客户列表-------------------");puts("\n编号\t姓名\t\t性别\t年龄\t电话\t\t邮箱");// 遍历数组for (int i = 0; i < customerNum; i++){showCustomer(&customers[i]); // 调用 showCustomer 函数显示每个客户的信息}}
}// 确认退出函数
void confirmExit()
{puts("确认是否退出(Y/N):");char isExit;// 读取用户输入的确认信息while (1){if (scanf(" %c", &isExit) != 1) // %c 前面有空格,用于跳过前面的空白字符{puts("无效的输入,请输入 Y 或 N!"); // 提示错误信息// 清理输入缓冲区while (getchar() != '\n');continue; // 跳过本次循环}// 检查用户输入是否有效if (isExit == 'Y' || isExit == 'N'){break; // 结束循环}else{puts("你输入有误,请从新输入(Y/N):"); // 提示重新输入}}// 如果用户选择退出,设置循环标志为 0if (isExit == 'Y'){loop = 0;puts("欢迎你的再次访问^_^"); // 退出提示}
}// 显示菜单并处理用户选择的函数
void menu()
{while (loop) // 主循环,持续显示菜单直到用户选择退出{// 显示菜单选项printf("\n\n\n--------------客户信息管理软件--------------");printf("\n 1 添 加 客 户");printf("\n 2 修 改 客 户");printf("\n 3 删 除 客 户");printf("\n 4 客 户 列 表");printf("\n 5 退 出");printf("\n请选择(1-5):");int selection; // 存储用户的选项// 使用 scanf 读取用户输入if (scanf("%d", &selection) != 1) // 如果输入不是整数{puts("无效的输入,请输入一个数字 (1-5)!"); // 提示错误信息// 清理输入缓冲区中的非数字字符while (getchar() != '\n');continue; // 跳过本次循环的剩余部分,重新开始循环}// 根据用户选择执行相应操作switch (selection){case 1:puts("添 加 客 户"); // 用户选择了添加客户break;case 2:puts("修 改 客 户"); // 用户选择了修改客户break;case 3:puts("删 除 客 户"); // 用户选择了删除客户break;case 4:showView(); // 用户选择了查看客户列表break;case 5:confirmExit(); // 用户选择了退出程序break;default:puts("无效的选择,请重新选择!"); // 用户输入了不在 1-5 范围内的数字break;}}
}int main()
{// 模拟数据的添加,便于测试客户显示列表功能customers[0].id = 1;// 在 C 语言中,直接使用 = 运算符给字符数组赋值是不允许的// 这是因为字符数组实际上是一个指针,指向一个字符序列的起始位置// = 运算符只能用于初始化指针,而不能用于复制字符串内容// customers[0].name = "mynameis666"; 错误用法strcpy(customers[0].name, "Thanks_ks");customers[0].gender = 'm';customers[0].age = 18;strcpy(customers[0].phone, "1008611");strcpy(customers[0].email, "1008611@qq.com");customerNum++;// 模拟数据的添加,便于测试客户显示列表功能customers[1].id = 2;strcpy(customers[1].name, "THANKS_KS");customers[1].gender = 'f';customers[1].age = 22;strcpy(customers[1].phone, "1001010");strcpy(customers[1].email, "1009999@qq.com");customerNum++;menu(); // 调用菜单函数// 提示用户已退出软件puts("你退出了客户管理系统~");return 0; // 程序正常结束
}
3.5 添加客户功能
#include <stdio.h>
#include <string.h>#define MAX_CAPACITY 100 // 客户数量的最大值// 定义结构体数据类型来存储客户信息
struct Customer
{int id; // 客户编号char name[10]; // 客户名字char gender; // 性别,'f' 表示女,'m' 表示男int age; // 年龄char phone[20]; // 电话号码char email[40]; // 邮箱地址
};int loop = 1; // 全局变量控制主循环是否继续的变量// 客户结构体数组,最多可以存储 100 个客户信息
struct Customer customers[MAX_CAPACITY];// 当前客户数量,用于索引数组
int customerNum = 0;// 添加客户的功能
void addCustomer()
{if (customerNum < MAX_CAPACITY){puts("---------------------添加客户---------------------");// struct Customer cus = customers[customerNum]; // 错误写法,相当于复制数组// 使用指针指向当前客户的地址,后续操作是操作的地址所指向的内容struct Customer *cusPtr = &customers[customerNum];// 编号自动累加的方式赋值// 注意这里不要使用 customerNum++,因为后续需要用它进行赋值cusPtr->id = customerNum + 1;// 输入客户姓名printf("姓名: ");char name[10];if (scanf("%9s", name) != 1) // 限制输入长度为 9,防止溢出{puts("无效的输入,请重新输入!");while (getchar() != '\n'); // 清理输入缓冲区return;}strcpy(cusPtr->name, name);// 输入客户性别printf("性别: ");char gender;if (scanf(" %c", &gender) != 1) // %c 前面有空格,用于跳过前面的空白字符{puts("无效的输入,请重新输入!");while (getchar() != '\n'); // 清理输入缓冲区return;}cusPtr->gender = gender;// 输入客户年龄printf("年龄: ");int age;if (scanf("%d", &age) != 1){puts("无效的输入,请重新输入!");while (getchar() != '\n'); // 清理输入缓冲区return;}cusPtr->age = age;// 输入客户电话printf("电话: ");char phone[20];if (scanf("%19s", phone) != 1) // 限制输入长度为 19,防止溢出{puts("无效的输入,请重新输入!");while (getchar() != '\n'); // 清理输入缓冲区return;}strcpy(cusPtr->phone, phone);// 输入客户邮箱printf("邮箱: ");char email[40];if (scanf("%39s", email) != 1) // 限制输入长度为 39,防止溢出{puts("无效的输入,请重新输入!");while (getchar() != '\n'); // 清理输入缓冲区return;}strcpy(cusPtr->email, email);customerNum++; // 增加客户数量puts("---------------------添加完成---------------------");}else{puts("客户列表已满,添加失败");}
}// 显示某个客户的信息
void showCustomer(struct Customer *custPtr)
{// 两种方式访问结构体指针成员// 第一种方式:(*custPtr).member// 第二种方式:custPtr->memberprintf("%d\t%s\t%c\t%d\t%s\t\t%s\n", (*custPtr).id, custPtr->name, custPtr->gender, custPtr->age, custPtr->phone, custPtr->email);
}// 显示客户列表的功能
void showView()
{if (customerNum < 1){puts("系统中没有任何客户的信息,请先添加!");}else{puts("-------------------客户列表-------------------");puts("\n编号\t姓名\t\t性别\t年龄\t电话\t\t邮箱");// 遍历数组for (int i = 0; i < customerNum; i++){showCustomer(&customers[i]); // 调用 showCustomer 函数显示每个客户的信息}}
}// 确认退出函数
void confirmExit()
{puts("确认是否退出(Y/N):");char isExit;// 读取用户输入的确认信息while (1){if (scanf(" %c", &isExit) != 1) // %c 前面有空格,用于跳过前面的空白字符{puts("无效的输入,请输入 Y 或 N!"); // 提示错误信息// 清理输入缓冲区while (getchar() != '\n');continue; // 跳过本次循环}// 检查用户输入是否有效if (isExit == 'Y' || isExit == 'N'){break; // 结束循环}else{puts("你输入有误,请从新输入(Y/N):"); // 提示重新输入}}// 如果用户选择退出,设置循环标志为 0if (isExit == 'Y'){loop = 0;puts("欢迎你的再次访问^_^"); // 退出提示}
}// 显示菜单并处理用户选择的函数
void menu()
{while (loop) // 主循环,持续显示菜单直到用户选择退出{// 显示菜单选项printf("\n\n\n--------------客户信息管理软件--------------");printf("\n 1 添 加 客 户");printf("\n 2 修 改 客 户");printf("\n 3 删 除 客 户");printf("\n 4 客 户 列 表");printf("\n 5 退 出");printf("\n请选择(1-5):");int selection; // 存储用户的选项// 使用 scanf 读取用户输入if (scanf("%d", &selection) != 1) // 如果输入不是整数{puts("无效的输入,请输入一个数字 (1-5)!"); // 提示错误信息// 清理输入缓冲区中的非数字字符while (getchar() != '\n');continue; // 跳过本次循环的剩余部分,重新开始循环}// 根据用户选择执行相应操作switch (selection){case 1:addCustomer(); // 用户选择了添加客户break;case 2:puts("修 改 客 户"); // 用户选择了修改客户break;case 3:puts("删 除 客 户"); // 用户选择了删除客户break;case 4:showView(); // 用户选择了查看客户列表break;case 5:confirmExit(); // 用户选择了退出程序break;default:puts("无效的选择,请重新选择!"); // 用户输入了不在 1-5 范围内的数字break;}}
}int main()
{// 模拟数据的添加,便于测试客户显示列表功能customers[0].id = 1;// 在 C 语言中,直接使用 = 运算符给字符数组赋值是不允许的// 这是因为字符数组实际上是一个指针,指向一个字符序列的起始位置// = 运算符只能用于初始化指针,而不能用于复制字符串内容// customers[0].name = "mynameis666"; 错误用法strcpy(customers[0].name, "Thanks_ks");customers[0].gender = 'm';customers[0].age = 18;strcpy(customers[0].phone, "1008611");strcpy(customers[0].email, "1008611@qq.com");customerNum++;// 模拟数据的添加,便于测试客户显示列表功能customers[1].id = 2;strcpy(customers[1].name, "THANKS_KS");customers[1].gender = 'f';customers[1].age = 22;strcpy(customers[1].phone, "1001010");strcpy(customers[1].email, "1009999@qq.com");customerNum++;menu(); // 调用菜单函数// 提示用户已退出软件puts("你退出了客户管理系统~");return 0; // 程序正常结束
}
3.6 删除客户功能
#include <stdio.h>
#include <string.h>#define MAX_CAPACITY 100 // 客户数量的最大值// 定义结构体数据类型来存储客户信息
struct Customer
{int id; // 客户编号char name[10]; // 客户名字char gender; // 性别,'f' 表示女,'m' 表示男int age; // 年龄char phone[20]; // 电话号码char email[40]; // 邮箱地址
};int loop = 1; // 全局变量控制主循环是否继续的变量// 客户结构体数组,最多可以存储 100 个客户信息
struct Customer customers[MAX_CAPACITY];// 当前客户数量,用于索引数组
int customerNum = 0;// 删除指定索引位置的客户
// 删除失败,返回0
// 删除成功,返回非0
int removeCustomer(int index)
{if (index < 0 || index >= customerNum){return -1;}// 通过循环遍历的方式,将 index 后续位置依次前移,实现删除for (int i = index; i < customerNum - 1; i++){customers[i] = customers[i + 1];// 如果需要修改编号customers[i].id = i + 1;}customerNum--;return 1;
}// 判断指定编号的客户是否存在
// 如果客户不存在, 返回 -1
// 如果客户存在,返回此编号的客户所在数组中的索引位置
int getCustomerIndex(int id)
{for (int i = 0; i < customerNum; i++){if (customers[i].id == id){return i;}}// 如果没有找到return -1;
}// 删除客户的功能
// 删除客户的功能
void deleteCustomer()
{puts("---------------------删除客户---------------------");puts("请选择待删除客户编号(-1退出):");int deleteId;if (scanf("%d", &deleteId) != 1) // 检查输入是否为整数{puts("无效的输入,请输入一个数字!");while (getchar() != '\n'); // 清理输入缓冲区return;}if (deleteId == -1){return;}// 判断给定的客户编号对应的客户是否存在int deleteIndex = getCustomerIndex(deleteId);if (deleteIndex == -1){puts("不存在指定编号的客户!");return;}// 确认删除puts("确认是否删除(Y/N):");char isDelete;if (scanf(" %c", &isDelete) != 1) // 检查输入是否为字符{puts("无效的输入,请输入 Y 或 N!");while (getchar() != '\n'); // 清理输入缓冲区return;}if (isDelete == 'N'){return;}else if (isDelete == 'Y'){// 具体删除过程if (removeCustomer(deleteIndex) != 0){puts("---------------------删除成功---------------------");}else{puts("---------------------删除失败---------------------");}}else{puts("你输入的选择有误!");}
}// 添加客户的功能
void addCustomer()
{if (customerNum < MAX_CAPACITY){puts("---------------------添加客户---------------------");// struct Customer cus = customers[customerNum]; // 错误写法,相当于复制数组// 使用指针指向当前客户的地址,后续操作是操作的地址所指向的内容struct Customer *cusPtr = &customers[customerNum];// 编号自动累加的方式赋值// 注意这里不要使用 customerNum++,因为后续需要用它进行赋值cusPtr->id = customerNum + 1;// 输入客户姓名printf("姓名: ");char name[10];if (scanf("%9s", name) != 1) // 限制输入长度为 9,防止溢出{puts("无效的输入,请重新输入!");while (getchar() != '\n'); // 清理输入缓冲区return;}strcpy(cusPtr->name, name);// 输入客户性别printf("性别: ");char gender;if (scanf(" %c", &gender) != 1) // %c 前面有空格,用于跳过前面的空白字符{puts("无效的输入,请重新输入!");while (getchar() != '\n'); // 清理输入缓冲区return;}cusPtr->gender = gender;// 输入客户年龄printf("年龄: ");int age;if (scanf("%d", &age) != 1){puts("无效的输入,请重新输入!");while (getchar() != '\n'); // 清理输入缓冲区return;}cusPtr->age = age;// 输入客户电话printf("电话: ");char phone[20];if (scanf("%19s", phone) != 1) // 限制输入长度为 19,防止溢出{puts("无效的输入,请重新输入!");while (getchar() != '\n'); // 清理输入缓冲区return;}strcpy(cusPtr->phone, phone);// 输入客户邮箱printf("邮箱: ");char email[40];if (scanf("%39s", email) != 1) // 限制输入长度为 39,防止溢出{puts("无效的输入,请重新输入!");while (getchar() != '\n'); // 清理输入缓冲区return;}strcpy(cusPtr->email, email);customerNum++; // 增加客户数量puts("---------------------添加完成---------------------");}else{puts("客户列表已满,添加失败");}
}// 显示某个客户的信息
void showCustomer(struct Customer *custPtr)
{// 两种方式访问结构体指针成员// 第一种方式:(*custPtr).member// 第二种方式:custPtr->memberprintf("%d\t%s\t%c\t%d\t%s\t\t%s\n", (*custPtr).id, custPtr->name, custPtr->gender, custPtr->age, custPtr->phone, custPtr->email);
}// 显示客户列表的功能
void showView()
{if (customerNum < 1){puts("系统中没有任何客户的信息,请先添加!");}else{puts("-------------------客户列表-------------------");puts("\n编号\t姓名\t\t性别\t年龄\t电话\t\t邮箱");// 遍历数组for (int i = 0; i < customerNum; i++){showCustomer(&customers[i]); // 调用 showCustomer 函数显示每个客户的信息}}
}// 确认退出函数
void confirmExit()
{puts("确认是否退出(Y/N):");char isExit;// 读取用户输入的确认信息while (1){if (scanf(" %c", &isExit) != 1) // %c 前面有空格,用于跳过前面的空白字符{puts("无效的输入,请输入 Y 或 N!"); // 提示错误信息// 清理输入缓冲区while (getchar() != '\n');continue; // 跳过本次循环}// 检查用户输入是否有效if (isExit == 'Y' || isExit == 'N'){break; // 结束循环}else{puts("你输入有误,请从新输入(Y/N):"); // 提示重新输入}}// 如果用户选择退出,设置循环标志为 0if (isExit == 'Y'){loop = 0;puts("欢迎你的再次访问^_^"); // 退出提示}
}// 显示菜单并处理用户选择的函数
void menu()
{while (loop) // 主循环,持续显示菜单直到用户选择退出{// 显示菜单选项printf("\n\n\n--------------客户信息管理软件--------------");printf("\n 1 添 加 客 户");printf("\n 2 修 改 客 户");printf("\n 3 删 除 客 户");printf("\n 4 客 户 列 表");printf("\n 5 退 出");printf("\n请选择(1-5):");int selection; // 存储用户的选项// 使用 scanf 读取用户输入if (scanf("%d", &selection) != 1) // 如果输入不是整数{puts("无效的输入,请输入一个数字 (1-5)!"); // 提示错误信息// 清理输入缓冲区中的非数字字符while (getchar() != '\n');continue; // 跳过本次循环的剩余部分,重新开始循环}// 根据用户选择执行相应操作switch (selection){case 1:addCustomer(); // 用户选择了添加客户break;case 2:puts("修 改 客 户"); // 用户选择了修改客户break;case 3:deleteCustomer(); // 用户选择了删除客户break;case 4:showView(); // 用户选择了查看客户列表break;case 5:confirmExit(); // 用户选择了退出程序break;default:puts("无效的选择,请重新选择!"); // 用户输入了不在 1-5 范围内的数字break;}}
}int main()
{// 模拟数据的添加,便于测试客户显示列表功能customers[0].id = 1;// 在 C 语言中,直接使用 = 运算符给字符数组赋值是不允许的// 这是因为字符数组实际上是一个指针,指向一个字符序列的起始位置// = 运算符只能用于初始化指针,而不能用于复制字符串内容// customers[0].name = "mynameis666"; 错误用法strcpy(customers[0].name, "Thanks_ks");customers[0].gender = 'm';customers[0].age = 18;strcpy(customers[0].phone, "1008611");strcpy(customers[0].email, "1008611@qq.com");customerNum++;// 模拟数据的添加,便于测试客户显示列表功能customers[1].id = 2;strcpy(customers[1].name, "THANKS_KS");customers[1].gender = 'f';customers[1].age = 22;strcpy(customers[1].phone, "1001010");strcpy(customers[1].email, "1009999@qq.com");customerNum++;menu(); // 调用菜单函数// 提示用户已退出软件puts("你退出了客户管理系统~");return 0; // 程序正常结束
}
3.7 修改客户功能
#include <stdio.h>
#include <string.h>#define MAX_CAPACITY 100 // 客户数量的最大值// 定义结构体数据类型来存储客户信息
struct Customer
{int id; // 客户编号char name[10]; // 客户名字char gender; // 性别,'f' 表示女,'m' 表示男int age; // 年龄char phone[20]; // 电话号码char email[40]; // 邮箱地址
};int loop = 1; // 全局变量控制主循环是否继续的变量// 客户结构体数组,最多可以存储 100 个客户信息
struct Customer customers[MAX_CAPACITY];// 当前客户数量,用于索引数组
int customerNum = 0;// 删除指定索引位置的客户
// 删除失败,返回0
// 删除成功,返回非0
int removeCustomer(int index)
{if (index < 0 || index >= customerNum){return -1;}// 通过循环遍历的方式,将 index 后续位置依次前移,实现删除for (int i = index; i < customerNum - 1; i++){customers[i] = customers[i + 1];// 如果需要修改编号customers[i].id = i + 1;}customerNum--;return 1;
}// 判断指定编号的客户是否存在
// 如果客户不存在, 返回 -1
// 如果客户存在,返回此编号的客户所在数组中的索引位置
int getCustomerIndex(int id)
{for (int i = 0; i < customerNum; i++){if (customers[i].id == id){return i;}}// 如果没有找到return -1;
}// 删除客户的功能
// 删除客户的功能
void deleteCustomer()
{puts("---------------------删除客户---------------------");puts("请选择待删除客户编号(-1退出):");int deleteId;if (scanf("%d", &deleteId) != 1) // 检查输入是否为整数{puts("无效的输入,请输入一个数字!");while (getchar() != '\n'); // 清理输入缓冲区return;}if (deleteId == -1){return;}// 判断给定的客户编号对应的客户是否存在int deleteIndex = getCustomerIndex(deleteId);if (deleteIndex == -1){puts("不存在指定编号的客户!");return;}// 确认删除puts("确认是否删除(Y/N):");char isDelete;if (scanf(" %c", &isDelete) != 1) // 检查输入是否为字符{puts("无效的输入,请输入 Y 或 N!");while (getchar() != '\n'); // 清理输入缓冲区return;}if (isDelete == 'N'){return;}else if (isDelete == 'Y'){// 具体删除过程if (removeCustomer(deleteIndex) != 0){puts("---------------------删除成功---------------------");}else{puts("---------------------删除失败---------------------");}}else{puts("你输入的选择有误!");}
}// 添加客户的功能
void addCustomer()
{if (customerNum < MAX_CAPACITY){puts("---------------------添加客户---------------------");// struct Customer cus = customers[customerNum]; // 错误写法,相当于复制数组// 使用指针指向当前客户的地址,后续操作是操作的地址所指向的内容struct Customer *cusPtr = &customers[customerNum];// 编号自动累加的方式赋值// 注意这里不要使用 customerNum++,因为后续需要用它进行赋值cusPtr->id = customerNum + 1;// 输入客户姓名printf("姓名: ");char name[10];if (scanf("%9s", name) != 1) // 限制输入长度为 9,防止溢出{puts("无效的输入,请重新输入!");while (getchar() != '\n'); // 清理输入缓冲区return;}strcpy(cusPtr->name, name);// 输入客户性别printf("性别: ");char gender;if (scanf(" %c", &gender) != 1) // %c 前面有空格,用于跳过前面的空白字符{puts("无效的输入,请重新输入!");while (getchar() != '\n'); // 清理输入缓冲区return;}cusPtr->gender = gender;// 输入客户年龄printf("年龄: ");int age;if (scanf("%d", &age) != 1){puts("无效的输入,请重新输入!");while (getchar() != '\n'); // 清理输入缓冲区return;}cusPtr->age = age;// 输入客户电话printf("电话: ");char phone[20];if (scanf("%19s", phone) != 1) // 限制输入长度为 19,防止溢出{puts("无效的输入,请重新输入!");while (getchar() != '\n'); // 清理输入缓冲区return;}strcpy(cusPtr->phone, phone);// 输入客户邮箱printf("邮箱: ");char email[40];if (scanf("%39s", email) != 1) // 限制输入长度为 39,防止溢出{puts("无效的输入,请重新输入!");while (getchar() != '\n'); // 清理输入缓冲区return;}strcpy(cusPtr->email, email);customerNum++; // 增加客户数量puts("---------------------添加完成---------------------");}else{puts("客户列表已满,添加失败");}
}// 显示某个客户的信息
void showCustomer(struct Customer *custPtr)
{// 两种方式访问结构体指针成员// 第一种方式:(*custPtr).member// 第二种方式:custPtr->memberprintf("%d\t%s\t%c\t%d\t%s\t\t%s\n", (*custPtr).id, custPtr->name, custPtr->gender, custPtr->age, custPtr->phone, custPtr->email);
}// 显示客户列表的功能
void showView()
{if (customerNum < 1){puts("系统中没有任何客户的信息,请先添加!");}else{puts("-------------------客户列表-------------------");puts("\n编号\t姓名\t\t性别\t年龄\t电话\t\t邮箱");// 遍历数组for (int i = 0; i < customerNum; i++){showCustomer(&customers[i]); // 调用 showCustomer 函数显示每个客户的信息}}
}// 修改客户的功能
void modifyCustomer()
{puts("---------------------修改客户---------------------");puts("请选择待修改客户编号(-1退出):");int modifyId;if (scanf("%d", &modifyId) != 1) // 检查输入是否为整数{puts("无效的输入,请输入一个数字!");while (getchar() != '\n'); // 清理输入缓冲区return;}if (modifyId == -1){return;}// 判断给定的客户编号对应的客户是否存在int modifyIndex = getCustomerIndex(modifyId);if (modifyIndex == -1){puts("不存在指定编号的客户!");return;}struct Customer *cusPtr = &customers[modifyIndex];puts("---------------------修改客户---------------------");// 声明一个通用的字符串,用于存储可能要修改的数据char info[30];getchar();// 展示初始信息printf("姓名(%s):", cusPtr->name);fgets(info, sizeof(info), stdin);// 如果读取到的是换行,说明不想改数据,反之就是要修改数据if (!(info[0] == '\n')){// strcpy(cusPtr->name, info);sscanf(info, "%s", cusPtr->name);}printf("性别( %c):", cusPtr->gender);// scanf("%s", info);fgets(info, sizeof(info), stdin);// 如果读取到的是换行,说明不想改数据,反之就是要修改数据if (!(info[0] == '\n')){// cusPtr->gender = info[0];sscanf(info, "%c", &cusPtr->gender);}printf("年龄(%d):", cusPtr->age);fgets(info, sizeof(info), stdin);// 如果读取到的是换行,说明不想改数据,反之就是要修改数据if (!(info[0] == '\n')){// cusPtr->age = info[0];sscanf(info, "%d", &cusPtr->age);}printf("电话(%s):", cusPtr->phone);fgets(info, sizeof(info), stdin);// 如果读取到的是换行,说明不想改数据,反之就是要修改数据if (!(info[0] == '\n')){// strcpy(cusPtr->phone, info);sscanf(info, "%s", cusPtr->phone);}printf("邮箱(%s):", cusPtr->email);fgets(info, sizeof(info), stdin);// 如果读取到的是换行,说明不想改数据,反之就是要修改数据if (!(info[0] == '\n')){// strcpy(cusPtr->email, info);sscanf(info, "%s", cusPtr->email);}puts("---------------------修改完成---------------------");
}// 确认退出函数
void confirmExit()
{puts("确认是否退出(Y/N):");char isExit;// 读取用户输入的确认信息while (1){if (scanf(" %c", &isExit) != 1) // %c 前面有空格,用于跳过前面的空白字符{puts("无效的输入,请输入 Y 或 N!"); // 提示错误信息// 清理输入缓冲区while (getchar() != '\n');continue; // 跳过本次循环}// 检查用户输入是否有效if (isExit == 'Y' || isExit == 'N'){break; // 结束循环}else{puts("你输入有误,请从新输入(Y/N):"); // 提示重新输入}}// 如果用户选择退出,设置循环标志为 0if (isExit == 'Y'){loop = 0;puts("欢迎你的再次访问^_^"); // 退出提示}
}// 显示菜单并处理用户选择的函数
void menu()
{while (loop) // 主循环,持续显示菜单直到用户选择退出{// 显示菜单选项printf("\n\n\n--------------客户信息管理软件--------------");printf("\n 1 添 加 客 户");printf("\n 2 修 改 客 户");printf("\n 3 删 除 客 户");printf("\n 4 客 户 列 表");printf("\n 5 退 出");printf("\n请选择(1-5):");int selection; // 存储用户的选项// 使用 scanf 读取用户输入if (scanf("%d", &selection) != 1) // 如果输入不是整数{puts("无效的输入,请输入一个数字 (1-5)!"); // 提示错误信息// 清理输入缓冲区中的非数字字符while (getchar() != '\n');continue; // 跳过本次循环的剩余部分,重新开始循环}// 根据用户选择执行相应操作switch (selection){case 1:addCustomer(); // 用户选择了添加客户break;case 2:modifyCustomer(); // 用户选择了修改客户break;case 3:deleteCustomer(); // 用户选择了删除客户break;case 4:showView(); // 用户选择了查看客户列表break;case 5:confirmExit(); // 用户选择了退出程序break;default:puts("无效的选择,请重新选择!"); // 用户输入了不在 1-5 范围内的数字break;}}
}int main()
{// 模拟数据的添加,便于测试客户显示列表功能customers[0].id = 1;// 在 C 语言中,直接使用 = 运算符给字符数组赋值是不允许的// 这是因为字符数组实际上是一个指针,指向一个字符序列的起始位置// = 运算符只能用于初始化指针,而不能用于复制字符串内容// customers[0].name = "mynameis666"; 错误用法strcpy(customers[0].name, "Thanks_ks");customers[0].gender = 'm';customers[0].age = 18;strcpy(customers[0].phone, "1008611");strcpy(customers[0].email, "1008611@qq.com");customerNum++;// 模拟数据的添加,便于测试客户显示列表功能customers[1].id = 2;strcpy(customers[1].name, "THANKS_KS");customers[1].gender = 'f';customers[1].age = 22;strcpy(customers[1].phone, "1001010");strcpy(customers[1].email, "1009999@qq.com");customerNum++;menu(); // 调用菜单函数// 提示用户已退出软件puts("你退出了客户管理系统~");return 0; // 程序正常结束
}
4 最终优化后的代码
#include <stdio.h>
#include <string.h>#define MAX_CAPACITY 100 // 客户数量的最大值// 定义结构体数据类型来存储客户信息
struct Customer
{int id; // 客户编号char name[10]; // 客户名字char gender; // 性别,'f' 表示女,'m' 表示男int age; // 年龄char phone[20]; // 电话号码char email[40]; // 邮箱地址
};int loop = 1; // 全局变量控制主循环是否继续的变量// 客户结构体数组,最多可以存储 100 个客户信息
struct Customer customers[MAX_CAPACITY];// 当前客户数量,用于索引数组
int customerNum = 0;// 函数原型声明
int removeCustomer(int index);
int getCustomerIndex(int id);
void deleteCustomer();
void addCustomer();
void showCustomer(struct Customer *custPtr);
void showView();
void modifyCustomer();
void confirmExit();
void menu();// 主函数
int main()
{// 模拟数据的添加,便于测试客户显示列表功能customers[0].id = 1;strcpy(customers[0].name, "Thanks_ks");customers[0].gender = 'm';customers[0].age = 18;strcpy(customers[0].phone, "1008611");strcpy(customers[0].email, "1008611@qq.com");customerNum++;customers[1].id = 2;strcpy(customers[1].name, "THANKS_KS");customers[1].gender = 'f';customers[1].age = 22;strcpy(customers[1].phone, "1001010");strcpy(customers[1].email, "1009999@qq.com");customerNum++;menu(); // 调用菜单函数// 提示用户已退出软件puts("你退出了客户管理系统~");return 0; // 程序正常结束
}// 删除指定索引位置的客户
// 删除失败,返回0
// 删除成功,返回非0
int removeCustomer(int index)
{if (index < 0 || index >= customerNum){return -1;}// 通过循环遍历的方式,将 index 后续位置依次前移,实现删除for (int i = index; i < customerNum - 1; i++){customers[i] = customers[i + 1];// 如果需要修改编号customers[i].id = i + 1;}customerNum--;return 1;
}// 判断指定编号的客户是否存在
// 如果客户不存在, 返回 -1
// 如果客户存在,返回此编号的客户所在数组中的索引位置
int getCustomerIndex(int id)
{for (int i = 0; i < customerNum; i++){if (customers[i].id == id){return i;}}// 如果没有找到return -1;
}// 删除客户的功能
void deleteCustomer()
{puts("---------------------删除客户---------------------");puts("请选择待删除客户编号(-1退出):");int deleteId;if (scanf("%d", &deleteId) != 1) // 检查输入是否为整数{puts("无效的输入,请输入一个数字!");while (getchar() != '\n'); // 清理输入缓冲区return;}if (deleteId == -1){return;}// 判断给定的客户编号对应的客户是否存在int deleteIndex = getCustomerIndex(deleteId);if (deleteIndex == -1){puts("不存在指定编号的客户!");return;}// 确认删除puts("确认是否删除(Y/N):");char isDelete;if (scanf(" %c", &isDelete) != 1) // 检查输入是否为字符{puts("无效的输入,请输入 Y 或 N!");while (getchar() != '\n'); // 清理输入缓冲区return;}if (isDelete == 'N'){return;}else if (isDelete == 'Y'){// 具体删除过程if (removeCustomer(deleteIndex) != 0){puts("---------------------删除成功---------------------");}else{puts("---------------------删除失败---------------------");}}else{puts("你输入的选择有误!");}
}// 添加客户的功能
void addCustomer()
{if (customerNum < MAX_CAPACITY){puts("---------------------添加客户---------------------");// 使用指针指向当前客户的地址,后续操作是操作的地址所指向的内容struct Customer *cusPtr = &customers[customerNum];// 编号自动累加的方式赋值// 注意这里不要使用 customerNum++,因为后续需要用它进行赋值cusPtr->id = customerNum + 1;// 输入客户姓名printf("姓名: ");char name[10];if (scanf("%9s", name) != 1) // 限制输入长度为 9,防止溢出{puts("无效的输入,请重新输入!");while (getchar() != '\n'); // 清理输入缓冲区return;}strcpy(cusPtr->name, name);// 输入客户性别printf("性别: ");char gender;if (scanf(" %c", &gender) != 1) // %c 前面有空格,用于跳过前面的空白字符{puts("无效的输入,请重新输入!");while (getchar() != '\n'); // 清理输入缓冲区return;}cusPtr->gender = gender;// 输入客户年龄printf("年龄: ");int age;if (scanf("%d", &age) != 1){puts("无效的输入,请重新输入!");while (getchar() != '\n'); // 清理输入缓冲区return;}cusPtr->age = age;// 输入客户电话printf("电话: ");char phone[20];if (scanf("%19s", phone) != 1) // 限制输入长度为 19,防止溢出{puts("无效的输入,请重新输入!");while (getchar() != '\n'); // 清理输入缓冲区return;}strcpy(cusPtr->phone, phone);// 输入客户邮箱printf("邮箱: ");char email[40];if (scanf("%39s", email) != 1) // 限制输入长度为 39,防止溢出{puts("无效的输入,请重新输入!");while (getchar() != '\n'); // 清理输入缓冲区return;}strcpy(cusPtr->email, email);customerNum++; // 增加客户数量puts("---------------------添加完成---------------------");}else{puts("客户列表已满,添加失败");}
}// 显示某个客户的信息
void showCustomer(struct Customer *custPtr)
{// 两种方式访问结构体指针成员// 第一种方式:(*custPtr).member// 第二种方式:custPtr->memberprintf("%d\t%s\t%c\t%d\t%s\t\t%s\n", (*custPtr).id, custPtr->name, custPtr->gender, custPtr->age, custPtr->phone, custPtr->email);
}// 显示客户列表的功能
void showView()
{if (customerNum < 1){puts("系统中没有任何客户的信息,请先添加!");}else{puts("-------------------客户列表-------------------");puts("\n编号\t姓名\t\t性别\t年龄\t电话\t\t邮箱");// 遍历数组for (int i = 0; i < customerNum; i++){showCustomer(&customers[i]); // 调用 showCustomer 函数显示每个客户的信息}}
}// 修改客户的功能
void modifyCustomer()
{puts("---------------------修改客户---------------------");puts("请选择待修改客户编号(-1退出):");int modifyId;if (scanf("%d", &modifyId) != 1) // 检查输入是否为整数{puts("无效的输入,请输入一个数字!");while (getchar() != '\n'); // 清理输入缓冲区return;}if (modifyId == -1){return;}// 判断给定的客户编号对应的客户是否存在int modifyIndex = getCustomerIndex(modifyId);if (modifyIndex == -1){puts("不存在指定编号的客户!");return;}struct Customer *cusPtr = &customers[modifyIndex];puts("---------------------修改客户---------------------");// 声明一个通用的字符串,用于存储可能要修改的数据char info[30];getchar();// 展示初始信息printf("姓名(%s):", cusPtr->name);fgets(info, sizeof(info), stdin);// 如果读取到的是换行,说明不想改数据,反之就是要修改数据if (!(info[0] == '\n')){sscanf(info, "%s", cusPtr->name);}printf("性别( %c):", cusPtr->gender);fgets(info, sizeof(info), stdin);// 如果读取到的是换行,说明不想改数据,反之就是要修改数据if (!(info[0] == '\n')){sscanf(info, "%c", &cusPtr->gender);}printf("年龄(%d):", cusPtr->age);fgets(info, sizeof(info), stdin);// 如果读取到的是换行,说明不想改数据,反之就是要修改数据if (!(info[0] == '\n')){sscanf(info, "%d", &cusPtr->age);}printf("电话(%s):", cusPtr->phone);fgets(info, sizeof(info), stdin);// 如果读取到的是换行,说明不想改数据,反之就是要修改数据if (!(info[0] == '\n')){sscanf(info, "%s", cusPtr->phone);}printf("邮箱(%s):", cusPtr->email);fgets(info, sizeof(info), stdin);// 如果读取到的是换行,说明不想改数据,反之就是要修改数据if (!(info[0] == '\n')){sscanf(info, "%s", cusPtr->email);}puts("---------------------修改完成---------------------");
}// 确认退出函数
void confirmExit()
{puts("确认是否退出(Y/N):");char isExit;// 读取用户输入的确认信息while (1){if (scanf(" %c", &isExit) != 1) // %c 前面有空格,用于跳过前面的空白字符{puts("无效的输入,请输入 Y 或 N!"); // 提示错误信息// 清理输入缓冲区while (getchar() != '\n');continue; // 跳过本次循环}// 检查用户输入是否有效if (isExit == 'Y' || isExit == 'N'){break; // 结束循环}else{puts("你输入有误,请从新输入(Y/N):"); // 提示重新输入}}// 如果用户选择退出,设置循环标志为 0if (isExit == 'Y'){loop = 0;puts("欢迎你的再次访问^_^"); // 退出提示}
}// 显示菜单并处理用户选择的函数
void menu()
{while (loop) // 主循环,持续显示菜单直到用户选择退出{// 显示菜单选项printf("\n\n\n--------------客户信息管理软件--------------");printf("\n 1 添 加 客 户");printf("\n 2 修 改 客 户");printf("\n 3 删 除 客 户");printf("\n 4 客 户 列 表");printf("\n 5 退 出");printf("\n请选择(1-5):");int selection; // 存储用户的选项// 使用 scanf 读取用户输入if (scanf("%d", &selection) != 1) // 如果输入不是整数{puts("无效的输入,请输入一个数字 (1-5)!"); // 提示错误信息// 清理输入缓冲区中的非数字字符while (getchar() != '\n');continue; // 跳过本次循环的剩余部分,重新开始循环}// 根据用户选择执行相应操作switch (selection){case 1:addCustomer(); // 用户选择了添加客户break;case 2:modifyCustomer(); // 用户选择了修改客户break;case 3:deleteCustomer(); // 用户选择了删除客户break;case 4:showView(); // 用户选择了查看客户列表break;case 5:confirmExit(); // 用户选择了退出程序break;default:puts("无效的选择,请重新选择!"); // 用户输入了不在 1-5 范围内的数字break;}}
}