Switch 语句在第二次尝试时变为默认值
Switch Statement goes to Default on Second try
我正在为 class 编写此程序,它可以为银行创建客户。我想我已经掌握了基础知识——我还有一些工作要做,还有一些事情要添加。它编译没有错误,但我有两个问题我无法弄清楚:
我可以添加客户,但是当菜单第二次出现时,无论我输入什么选项,它都会转到 switch
中的 default
声明。
添加客户后,如果我选择搜索,总是说找不到。如果您回答,请解释一下,因为我正在努力学习 :) 感谢您的任何见解和建议!
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;
}
请注意 c
的 int
类型,因此它可以接收 unsigned char
的所有值和 特殊值 EOF
. char
对此不正确,并且您的 while
循环有一个问题:您没有测试 EOF
,因此程序将 运行文件。尝试输入 control-Z(在 Windows 中)或 control-D(在 Unix 上)来验证。
还要注意明确的 continue
语句。您的空循环对于 C 语法是正确的,但对于 reader 有点混乱,因为 for
子句末尾的 ;
看起来像一个错误。建议使用 {}
或其他语法结构使这个空主体更加明确。我个人更喜欢一个明显的 continue;
语句。
我正在为 class 编写此程序,它可以为银行创建客户。我想我已经掌握了基础知识——我还有一些工作要做,还有一些事情要添加。它编译没有错误,但我有两个问题我无法弄清楚:
我可以添加客户,但是当菜单第二次出现时,无论我输入什么选项,它都会转到
switch
中的default
声明。添加客户后,如果我选择搜索,总是说找不到。如果您回答,请解释一下,因为我正在努力学习 :) 感谢您的任何见解和建议!
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
:
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;
}
请注意 c
的 int
类型,因此它可以接收 unsigned char
的所有值和 特殊值 EOF
. char
对此不正确,并且您的 while
循环有一个问题:您没有测试 EOF
,因此程序将 运行文件。尝试输入 control-Z(在 Windows 中)或 control-D(在 Unix 上)来验证。
还要注意明确的 continue
语句。您的空循环对于 C 语法是正确的,但对于 reader 有点混乱,因为 for
子句末尾的 ;
看起来像一个错误。建议使用 {}
或其他语法结构使这个空主体更加明确。我个人更喜欢一个明显的 continue;
语句。