48 C 语言实战项目——客户信息管理系统

news2024/11/26 18:43:36

目录

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):"); // 提示重新输入
        }
    }

    // 如果用户选择退出,设置循环标志为 0
    if (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->member
    printf("%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):"); // 提示重新输入
        }
    }

    // 如果用户选择退出,设置循环标志为 0
    if (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->member
    printf("%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):"); // 提示重新输入
        }
    }

    // 如果用户选择退出,设置循环标志为 0
    if (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->member
    printf("%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):"); // 提示重新输入
        }
    }

    // 如果用户选择退出,设置循环标志为 0
    if (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->member
    printf("%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):"); // 提示重新输入
        }
    }

    // 如果用户选择退出,设置循环标志为 0
    if (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->member
    printf("%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):"); // 提示重新输入
        }
    }

    // 如果用户选择退出,设置循环标志为 0
    if (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;
        }
    }
}

 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2207244.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

MySQL-约束Constraint详解

文章目录 约束简介非空约束检查约束唯一约束列级约束与表级约束给约束起名字主键约束 约束简介 约束是我们在创建表的时候, 我们可以给表中的字段添加约束确保我们的数据的完整性和有效性, 比如大家平时上网时注册用户常见的 : 用户名不能为空, 对不起, 用户名已经存在等提示信…

【C++】用红黑树模拟实现set与map

目录 一、红黑树的完善&#xff1a; 1、红黑树节点模版的修改&#xff1a; 2、仿函数在模拟实现中的应用&#xff1a; 3、新增迭代器&#xff1a; 4、红黑树中的迭代器实现&#xff1a; 二、set与map的模拟实现&#xff1a; 1、insert&#xff1a; 2、map的[ ]: 三、测…

无刷直流电机工作原理:【图文讲解】

电动机 (俗称马达) 是机械能与电能之间转换装置的通称。可以分为电动机和发电机.一般称电机时就是指电动机。这个在日常应用中&#xff0c;比较多见&#xff0c;比如机器人&#xff0c;手机&#xff0c;电动车等。 直流电机&#xff1a;分为有刷直流电机&#xff08;BDC&#…

本地ubuntu主机搭建我的世界服务器并免费开启公网映射 结合MESM面板 chmlfrp 保姆级教学

本地ubuntu主机搭建我的世界forge服务器并免费开启公网映射 结合MESM面板 chmlfrp 这是一篇很完成的从ssh命令->配置java环境->安装MCS->部署服务器->开启公网映射的我的世界保姆级开服教程,可以慢慢食用ଘ(੭ˊ꒳ˋ)੭ 。 为什么选择forge服务器进行开服&#x…

【前车之鉴】坑啊~ RestHighLevelClient 超时时间偶尔失效问题解决方案

文章目录 show me code缘起原因分析 几点建议 结论&#xff1a;实际你的配置是生效的&#xff0c;只不过效果不明显而已&#xff0c;通过下面的配置放大直观效果。 show me code 核心代码 public static void main(String[] args) {RestClientBuilder builder RestClient.bu…

【M2TR】M2TR: Multi-modal Multi-scale Transformers for Deepfake Detection

文章目录 M2TR: Multi-modal Multi-scale Transformers for Deepfake Detectionkey points研究贡献方法多尺度变压器频率过滤器跨模态融合损失函数SR-DF数据集实验总结M2TR: Multi-modal Multi-scale Transformers for Deepfake Detection 会议/期刊:ICMR ’22 作者: key …

深入理解栈(Stack)(纯小白进)

目录&#xff1a; 一、栈是什么&#xff1f;1. 栈的概念2.栈的结构选择 二、栈的实现1. 栈结构体的定义2. 栈的初始化3. 栈的销毁4. 入栈5.出栈6. 取栈顶元素7. 栈中元素的个数8. 判断栈是否为空 总结 一、栈是什么&#xff1f; 1. 栈的概念 栈&#xff08;Stack&#xff09;…

游戏开发指南:使用 UOS C# 云函数快速构建与部署服务端逻辑实战教学

零基础的服务端小白&#xff0c;现在也可以使用 Unity 结合 C# 来轻松搞定游戏服务端啦&#xff01; 在本篇文章中&#xff0c;我们将以游戏中的“抽卡”功能为例&#xff0c;展示如何使用 Unity Online Services&#xff08;UOS&#xff09;提供的强大 C# 云函数服务&#xf…

Elasticsearch(二)集成Spring Boot 基本的API操作

目录 一、集成Spring Boot 1、创建项目 2、pom文件 查看springboot集成的依赖 3、增加es的config类 二、索引相关API 1、创建索引 2、获取索引&#xff0c;判断其是否存在 3、删除索引 三、文档相关API 1、添加文档 2、获取文档&#xff0c;判断是否存在 3、获取文档…

Java后端面试----某团一面

美团一面 1.介绍一下你的第一个项目 这个就不多说了&#xff0c;主要是根据自己的简历上面的项目进行一个简短的概括使用的技术栈和什么背景解决了什么问题等等。 2.线程安全的类有哪些&#xff0c;平时有使用过哪些&#xff0c;主要解决什么问题 在Java中线程安全的类比如…

对后端返回的日期属性进行格式化(扩展 Spring MVC 的消息转换器)

格式化之前 格式化之后&#xff1a; 解决方式 方式一 在属性中加上注解&#xff0c;对日期进行格式化 JsonFormat(pattern "yyyy-MM-dd HH:mm:ss")private LocalDateTime createTime;//JsonFormat(pattern &quo…

echarts按需引入解决项目大小问题

背景&#xff1a; 按需加载缩减项目大小&#xff0c;提升项目性能和可用性 实现&#xff1a; 创建echarts.js main.js进行配置 页面中引用 效果 全量导入 按需加载&#xff1a;

Chrome清除nslookup解析记录 - 强制http访问 - 如何禁止chrome 强制跳转https

步骤&#xff1a; 地址栏输入 chrome://net-internals/#hsts在Delete domain 栏的输入框中输入要http访问的域名&#xff0c;然后点击“delete”按钮最后在Query domain 栏中搜索刚才输入的域名&#xff0c;点击“query”按钮后如果提示“Not found”即可&#xff01; 办法来自…

Linux系统:apt upgrade与apt update 命令的作用

一.sudo apt update命令 sudo apt update命令的主要作用是更新本地软件包列表。‌ 它不会下载或安装新的软件包&#xff0c;而是更新本地系统中软件包的列表&#xff0c;以反映远程存储库中的最新可用软件包信息。这确保了软件包管理器&#xff08;APT&#xff09;具有最新的软…

第十六周周报:单发的目标检测系列

目录 摘要 Abstract 一、SSD 1.1 模型结构 1.2 代码 二、YOLO 三、Termius 总结 摘要 本周主要学习单阶段的目标检测算法&#xff0c;如SSD、YOLO模型。详细学习了每个模型的原理&#xff0c;以及SSD和YOLO模型之间的异同。在本篇博客中将展示SSD的PyTorch实现代码&am…

Django使用uwsgi和nginx进行手动部署

在Django项目中使用uWSGI和Nginx进行部署是一种常见的生产环境配置。以下是一个详细的步骤指南&#xff0c;帮助你完成这个过程。 前提条件 有一个已经开发好的Django项目。服务器已安装Python、pip、Nginx和uWSGI。有一个有效的域名(可选&#xff0c;但推荐)。 步骤一&#xf…

CPU指令融合技术概述

什么是指令融合&#xff1f; 某些指令&#xff0c;例如add $3,$2,0, 只会使用rd/rs两个字段&#xff0c;但是这条指令却占用了全部32个bit, 这样会使得代码密度不高&#xff0c;指令域的有效利用率不高&#xff1b;这样&#xff0c;在实现某些功能的情况下&#xff0c;会使得CP…

Java创建线程池和线程池的七个核心参数

线程池的工作流程是&#xff1a;当一个任务被提交到线程池时&#xff0c;线程池会根据当前的线程数量和工作队列的状态来决定如何处理这个任务。如果当前运行的线程数量小于corePoolSize&#xff0c;则创建新线程执行任务&#xff1b;如果大于等于corePoolSize&#xff0c;则将…

毕设开源 大数据电影数据分析与可视化系统(源码+论文)

文章目录 0 前言1 项目运行效果2 设计概要3 最后 0 前言 &#x1f525;这两年开始毕业设计和毕业答辩的要求和难度不断提升&#xff0c;传统的毕设题目缺少创新和亮点&#xff0c;往往达不到毕业答辩的要求&#xff0c;这两年不断有学弟学妹告诉学长自己做的项目系统达不到老师…

完全免费安卓远程安卓方案:FRP+ADB甲壳虫方案,远程手机不是问题。

引言 在当今这个数字化时代&#xff0c;无论是在个人项目还是商业应用中&#xff0c;能够从公网访问到内网设备的能力变得越来越重要&#xff0c;尤其是安卓终端设备&#xff0c;在必要的情况下&#xff0c;从安卓远程到安卓进行紧急指导救援是未来一种重要的趋势. 通过合理的…