Switch 语句在第二次尝试时变为默认值

Switch Statement goes to Default on Second try

我正在为 class 编写此程序,它可以为银行创建客户。我想我已经掌握了基础知识——我还有一些工作要做,还有一些事情要添加。它编译没有错误,但我有两个问题我无法弄清楚:

  1. 我可以添加客户,但是当菜单第二次出现时,无论我输入什么选项,它都会转到 switch 中的 default声明。

  2. 添加客户后,如果我选择搜索,总是说找不到。如果您回答,请解释一下,因为我正在努力学习 :) 感谢您的任何见解和建议!

customer.c

#include <stdio.h>
#include <stdlib.h>
#include "person.h"

// Program Contstants
#define INTEREST    .03
#define CHAR_LEN    40
#define MIN_PRINC   1000
#define MAX_PRINC   1000000
#define MIN_TERM    5
#define MAX_TERM    30

// Program Variables
struct person *customer = NULL;

// Function Prototypes
void addCustomer();
struct person *findCustomer(int custID);
void printCustomer();

int main(void) {
    char input;

    for (;;) {
        printf("\n\nChoose From the Options Below:\n");
        printf("Type 'N' to Add a New Customer\n");
        printf("Type 'P' to Print a Customer's Information\n");
        printf("Type 'Q' to Quit the Program\n\n");
        scanf("%c", &input);
        while (getchar() != '\n');

        switch (toupper(input)) {
          case 'N':
            addCustomer();
            break;
          case 'P':
            printCustomer();
            break;
          case 'Q':
            exit(0);
          default:
            printf("Invalid Entry. Please Reenter.\n");
            break;
        }
    }
}

void addCustomer() {
    struct person *cur, *prev, *new_node;

    new_node = malloc(sizeof(struct person));

    if (new_node == NULL) {
        printf("The Database is Full. You Cannot Add a New Customer.");
        return;
    }

    printf("\nEnter the Customer ID: ");
    scanf("%d", &new_node->custID);

    for (cur = customer, prev = NULL; 
         cur != NULL && new_node->custID > cur->custID;
         prev = cur, cur = cur->next);

    if (cur != NULL && new_node->custID == cur->custID) {
        printf("This Customer ID Already Exists\n");
        free(new_node);
        return;
    }

    printf("\nEnter Customer's First Name: ");
    gets(new_node->fName);

    printf("\nEnter Customer's Last Name: ");
    gets(new_node->lName);

    printf("\nEnter Customer's Street Address: ");
    gets(new_node->address);

    printf("\nEnter Customer's City: ");
    gets(new_node->city);

    printf("\nEnter Customer's 2-Digit State: ");
    gets(new_node->state);

    printf("\nEnter Customer's 5-Digit Zip Code: ");
    gets(new_node->zip);

    printf("\nEnter Customer's Principal: ");
    scanf("%f", &new_node->principal);

    printf("\nEnter Customer's Loan Term (In Years): ");
    scanf("%d", &new_node->yearlyTerm);

    new_node->next = cur;
    if (prev == NULL) {
        customer = new_node;
    } else {
        prev->next = new_node;
    }
}

struct person *findCustomer(int custID) {
    struct person *p;

    for (p = customer; p != NULL && custID > p->custID; p = p->next);

    if (p != NULL && custID == p->custID) {
        return p;
    } else {
        return NULL;
    }
}

void printCustomer() {
    int custID;
    struct person *p;

    printf("Enter Customer ID: ");
    scanf("%d", &custID);

    p = findCustomer(custID);

    if (p != NULL) {
        printf("\nCustomer ID:\t\t%d", p->custID);
        printf("\nCustomer's Name:\t%s %s", p->fName, p->lName);
        printf("\nCustomer's Address:\t%s", p->address);
        printf("\n\t\t\t%s, %s %s", p->city, p->state, p->zip);
        printf("\nCustomer's Principal:\t$%.2f", p->principal);
        printf("\nCustomer's Loan Term:\t%d", p->yearlyTerm);
    } else {
        printf("The Customer ID Wasn't Found.\n");
    }
}

person.h

// Program Constants
#define MAX_CUSTOMERS  10
#define CHAR_LEN       40

struct person {
    int custID;
    char fName[CHAR_LEN + 1];
    char lName[CHAR_LEN + 1];
    char address[CHAR_LEN + 1];
    char city[CHAR_LEN + 1];
    char state[3];
    char zip[6];
    float principal;
    int yearlyTerm;         // Loan Term in Years
    int monthlyTerm;        // Loan Term in Months
    float monthlyPayment;   // Calculated Monthly Payment
    float actualPayment;    // Calculated Monthly Payment Total 
    struct person *next;
};

第二次执行scanf("%c", &input);,它读取在上次执行的scanf("%d", ...)之后在标准输入中挂起的\n

您可以通过在 %c:

前面插入一个 space 字符来忽略要阅读的字符之前的任何白色 space 来解决此问题
scanf(" %c", &input);

请注意,您应该测试 scanf 中的 return 值以验证输入是否被正确解析。您绝对不应该使用 gets(),您应该通过指定要读取的最大字符数来保护 scanf("%s", ...)scanf("%19s", buffer); 如果 buffer 的长度为 20字符。

getchar() 循环消耗了用户选择执行哪个选项的输入行的其余部分,但看看 addCustomer():最后的输入操作是 scanf("%d", &new_node->yearlyTerm);。此对 scanf 的调用将其行的其余部分留在标准输入中,包括 \n.

在调用 scanf() 刷新 待处理输入的正确方法是:

void flush_line(void) {
    int c;
    while ((c = getchar()) != EOF && c != '\n')
        continue;
}

请注意 cint 类型,因此它可以接收 unsigned char 的所有值和 特殊值 EOF . char 对此不正确,并且您的 while 循环有一个问题:您没有测试 EOF,因此程序将 运行文件。尝试输入 control-Z(在 Windows 中)或 control-D(在 Unix 上)来验证。

还要注意明确的 continue 语句。您的空循环对于 C 语法是正确的,但对于 reader 有点混乱,因为 for 子句末尾的 ; 看起来像一个错误。建议使用 {} 或其他语法结构使这个空主体更加明确。我个人更喜欢一个明显的 continue; 语句。