首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >客户管理系统在C中注册客户

客户管理系统在C中注册客户
EN

Code Review用户
提问于 2021-04-11 20:15:46
回答 1查看 1.1K关注 0票数 2

提示是:我应该为客户管理系统编写一个用于注册客户的程序(用C编程语言)。

该方案应允许注册管理成员:

  • 将客户记录(id、姓名、年龄、性别和城市)添加到文件中。
  • 打印客户详细信息(ID、姓名、年龄、性别和城市)

(注:如果用户输入“男性或女性”以外的性别,程序应显示错误信息“无效输入!(性别必须为男性或女性)”,并强制用户输入正确的性别。)

代码语言:javascript
复制
#include <stdio.h>
#include<stdlib.h>
#include<string.h>

int n_r=0;
struct customer                                                                         // using a struct will be better than an array since it
{                                                                                       // can store several data types unlike an array
    int id;
    char firstname[20];
    char lastname[20];

    int age;
    char gender[6];
    char city[20];
};

void displayMainMenu()                                                                  // print menu
{
    printf("\n -------------------------------------------------------------\n");
    printf("\n -------------Customer Management System ---------------------\n");
    printf("\n ------------------------* MAIN MENU *----------------------------\n");
    printf("\n |A/a:Enter A or a for Adding a Customer ");
    printf("\n |D/d:Enter D or d for Printing Customer Details ");
    printf("\n |E/e:Enter E or e for Exiting the Program |------------------\n");
}  

char inputAndCheck()
{
    char ch;
    while(1)
    {
        displayMainMenu();
        printf("\n Please enter your choice: ");
        scanf("%c",&ch);
        if(ch=='A'||ch=='a'||ch=='D'||ch=='d'||ch=='E'||ch=='e')
        break;
        else
        {
            printf("\n > Invalid selection! Please try again ");
        }
    }
    return ch;
}
    

int readCustomerAge()
{
    int age;
    while(1)
    {
        printf("\n Enter age: ");
        scanf("%d",&age);
        if(age>=15 && age<=90)

        break;
        else
        {
            printf("\n > Invalid selection! (Age must be between 15 and 90) ");
        }
    }

    return age;
}                                                                       

int readCustomerGender()
{
    char ch1[6];
    while(1)
    {
        printf("\n Enter gender: ");
        scanf("%s",ch1);
        if((strcmp(ch1,"male")==0)||(strcmp(ch1,"MALE")==0))
        {
            return 0;
        }
        else if((strcmp(ch1,"female")==0)||(strcmp(ch1,"FEMALE")==0))
        {
            return 1;
        }
        else{
            printf("\n > Invalid selection! (Gender must be male or female) ");
        }
    }
}

char* readCustomerCity()
{
    char c[20];
    printf("\n Enter city: ");
    scanf("%s",c);
    return c;
}

void displayCustomerDetails()
{
    FILE *fp;
    struct customer c;
    fp=fopen("customer.txt","r");
    if(fp==NULL)
    {
        printf("\n Error in opening a file.");
        exit(1);
    }
    while(fread(&c,sizeof(struct customer),1,fp))
    printf("\n Id:%d \n Name:%s %s \n Age=%d \n Gender=%s \n City=%s",c.id,c.firstname,c.lastname,c.age,c.gender,c.city);

    fclose(fp);
}

void addCustomerDetails()
{
    FILE *fp;
    struct customer c;
    char* gen;
    //char cit[30];
    if(n_r==0)
    {
        fp=fopen("customer.txt","w");
        if(fp==NULL)
        {
            printf("\n Error in opening a file.");
            exit(1);
        }
    }
    else
    {
        fp=fopen("customer.txt","a");
        if(fp==NULL)
        {
            printf("\n Error in opening a file.");
            exit(1);
        }
    }

    printf("\n Enter customer ID: ");
    scanf("%d",&c.id);
    printf("\n Enter customer first name: ");
    scanf("%s",&c.firstname);
    printf("\n Enter customer last name: ");
    scanf("%s",&c.lastname);
    c.age=readCustomerAge();
    if(readCustomerGender())
    {
        strcpy(c.gender,"Female");
    }
    else
    {
        strcpy(c.gender,"Male");
    }

    printf("\n Enter customer city: ");
    scanf("%s",&c.city);
    fwrite(&c,sizeof(struct customer),1,fp);
    fclose(fp); 
}

int main()
{
    int year;
    char ch;
    printf("\n -------------------------------------------------------------\n");
    printf("\n -------------Welcome to Customer Management System ---------------------\n");
    printf("\n > Please Enter Customer registration year (ex:2017):");
    scanf("%d",&year);
    printf("\n > How many customers do you want register in the year %d:",year);
    scanf("%d",&n_r);

    while(1)
    {
        ch=inputAndCheck();
        switch(ch)
        {
            case 'A':
            case 'a':
            addCustomerDetails();
            n_r++;
            break;

            case 'D':
            case 'd':
            displayCustomerDetails();
            break;
            
            case 'E':
            case 'e':
            printf("\n > Thank you for using Customer Management System!\n");
            printf("\n > Good Bye. \n");
            exit(0);
        }
    }

    return 0;
}

请注意,我还没有完成为程序的评论,但将继续写在我收到反馈意见。

EN

回答 1

Code Review用户

发布于 2021-04-12 21:28:16

域特定类型

而不是

代码语言:javascript
复制
char gender[6];

如果你想限制两个性别,你最好做一个enum。然而,这样做通常是一个糟糕的选择;相反,只需要接受一个自由字符串,而不必为M/F编写逻辑。

预先存在的文件

n_r目前唯一有用的角色似乎是决定数据库文件的写入模式。您可以完全摆脱它,并根据I/O操作自动排序写入模式。

前后换行符

在命令行接口中,更典型的做法是

代码语言:javascript
复制
printf("Foo\n");

代码语言:javascript
复制
printf("\nFoo");

因为--从程序的一开始--我们就假设得到一个空行,所以做第二行是没有意义的。另一个原因是,某些缓存逻辑依赖后缀换行符,而不是前缀换行符,以知道何时写入流。

inputAndCheck

您基本上是一次检查这个逻辑,一次检查有效的选择字符,另一次实际注意选择。这样做一次而不是tolower(),这样您只需要检查一个值。

验证循环

scanf已经..。很多问题。例如,它污染了stdin缓冲区,因此很难从错误(例如,有人输入文本而不是整数)中恢复。

一个常见的解决方法是用fgets/sscanf对替换它。

关注点分离

displayCustomerDetails实际上做了两件事--从文件中读取,并显示给stdout。你应该把这个分开。同样适用于addCustomerDetails

未用输入

您要求--而且完全忽略--注册年份的输入;而n_r的输入既令人困惑,也没有正确地使用。你可以把这两样都处理掉。

超支

当扫描到固定缓冲区中的字符串时,关键是要告诉输入函数缓冲区大小,这样就不会出现溢出。C特别容易受到缓冲区溢出崩溃和安全漏洞的影响。

Backus-Naur

代码语言:javascript
复制
 |E/e

在格式化方面有点奇怪。熟悉命令行接口的用户将管道理解为两个选项之间的“或”;因此,在这里将其视为可视分隔符有点令人不快。EBNF建议使用E|e

建议

此代码提供了一种处理(大部分)上述问题的方法:

代码语言:javascript
复制
#include <ctype.h>
#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

static int n_r = 0;

typedef enum {
    MALE = 0,
    FEMALE = 1
} gender;

typedef struct tag_customer
{
    unsigned id;
    char firstname[20];
    char lastname[20];

    unsigned age;
    gender gender;
    char city[20];
} customer;

static void displayMainMenu()
{
    puts(
          "-------------------------------------------------------------"
        "\n-------------Customer Management System ---------------------"
        "\n------------------------* MAIN MENU *------------------------"
        "\n A|a: Add a Customer"
        "\n D|d: Print Customer Details"
        "\n E|e: Exit"
    );
}

static void scanLoop(const char *prompt, const char *fmt, void *dest)
{
    char buffer[80];
    int fields;
    do
    {
        printf(prompt);
        if (!fgets(buffer, sizeof(buffer), stdin))
        {
            perror("I/O error on stdin");
            exit(1);
        }

        fields = sscanf(buffer, fmt, dest);
    } while (fields != 1);
}

static char menuChoice()
{
    displayMainMenu();
    char choice;
    scanLoop("Please enter your choice: ", "%c", &choice);
    return tolower(choice);
}

static unsigned readCustomerAge()
{
    while (true)
    {
        unsigned age;
        scanLoop("Enter age: ", "%u", &age);
        if (age >= 15 && age <= 90)
            return age;
        puts("Invalid selection! (Age must be between 15 and 90)");
    }
}

static gender readCustomerGender()
{
    char buffer[10];
    while (true)
    {
        scanLoop("Enter gender (male|female): ", "%9s", buffer);

        for (char *p = buffer; *p; p++)
            *p = tolower(*p);

        if (!strcmp(buffer, "male"))
            return MALE;
        if (!strcmp(buffer, "female"))
            return FEMALE;

        puts("Invalid selection!");
    }
}

static void displayCustomer(const customer *c)
{
    printf(
        "Id: %u"
        "\nName: %s %s"
        "\nAge: %u"
        "\nGender: %s"
        "\nCity: %s"
        "\n",
        c->id, c->firstname, c->lastname, c->age,
        c->gender == MALE ? "male" : "female",
        c->city
    );
}

static void readCustomers(const char *filename)
{
    FILE *fp;
    customer c;
    fp = fopen(filename, "r");
    if (fp == NULL)
    {
        perror("Error opening file for customer display");
        exit(1);
    }

    while (fread(&c, sizeof(customer), 1, fp))
        displayCustomer(&c);

    fclose(fp);
}

static void scanCustomer(customer *c)
{
    scanLoop("Enter customer ID: ", "%u", &c->id);
    scanLoop("Enter customer first name: ", "%20s", c->firstname);
    scanLoop("Enter customer last name: ", "%20s", c->lastname);

    c->age = readCustomerAge();
    c->gender = readCustomerGender();

    scanLoop("Enter city: ", "%20s", c->city);
}

static void addCustomer(const char *filename)
{
    const char *mode;
    if (n_r == 0)
        mode = "w";
    else mode = "a";

    FILE *fp = fopen(filename, mode);
    if (fp == NULL)
    {
        perror("Error in opening customer file for writing");
        exit(1);
    }

    customer c;
    scanCustomer(&c);
    fwrite(&c, sizeof(customer), 1, fp);
    fclose(fp);
}

static unsigned readYear()
{
    unsigned year;
    while (true)
    {
        scanLoop("Please Enter Customer registration year (ex:2017): ", "%u", &year);
        if (year >= 2000 && year <= 2500)
            return year;
        puts("Year out of range");
    }
}

int main()
{
    printf(
          "------------------------------------------------------------------------"
        "\n-------------Welcome to Customer Management System ---------------------"
        "\n"
        "\n"
    );

    readYear();

    while (true)
    {
        switch (menuChoice())
        {
            case 'a':
                addCustomer("customer.txt");
                n_r++;
                break;

            case 'd':
                readCustomers("customer.txt");
                break;

            case 'e':
                puts(
                    "Thank you for using Customer Management System!"
                    "\nGoodbye."
                );
                return 0;

            default:
                puts("Invalid selection! Please try again.");
        }
    }
}
票数 1
EN
页面原文内容由Code Review提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://codereview.stackexchange.com/questions/259376

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档