18-混合字符和数值输入
8.7.3 混合字符和数值输入
前面分析过混合字符和数值输入会产生一些问题,创建菜单也有这样的问题。例如,假设 count()
函数(选择 c
)的代码如下:
void count(void)
{
int n, i;
printf("Count how far? Enter an integer:\n");
scanf("%d", &n);
for (i = 1; i <= n; i++)
printf("%d\n", i);
}
如果输入 3
作为响应, scanf()
会读取 3
并把换行符留在输入队列中。下次调用 get_choice()
将导致 get_first()
返回这个换行符,从而导致我们不希望出现的行为。
重写 get_first()
,使其返回下一个非空白字符而不仅仅是下一个字符,即可修复这个问题。我们把这个任务留给读者作为练习。另一种方法是,在 count()
函数中清理换行符,如下所示:
void count(void)
{
int n, i;
printf("Count how far? Enter an integer:\n");
n = get_int();
for (i = 1; i <= n; i++)
printf("%d\n", i);
while (getchar() != '\n')
continue;
}
该函数借鉴了程序清单8.7中的 get_long()
函数,将其改为 get_int()
获取 int
类型的数据而不是 long
类型的数据。回忆一下,原来的 get_long()
函数如何检查有效输入和让用户重新输入。程序清单8.8演示了菜单程序的最终版本。
程序清单8.8 menuette.c
程序
/* menuette.c -- 菜单程序 */
#include <stdio.h>
char get_choice(void);
char get_first(void);
int get_int(void);
void count(void);
int main(void)
{
int choice;
while ((choice = get_choice()) != 'q')
{
switch (choice)
{
case 'a': printf("Buy low, sell high.\n");
break;
case 'b': putchar('\a'); /* ANSI */
break;
case 'c': count();
break;
default: printf("Program error!\n");
break;
}
}
printf("Bye.\n");
return 0;
}
void count(void)
{
int n, i;
printf("Count how far? Enter an integer:\n");
n = get_int();
for (i = 1; i <= n; i++)
printf("%d\n", i);
while (getchar() != '\n')
continue;
}
char get_choice(void)
{
int ch;
printf("Enter the letter of your choice:\n");
printf("a. advice b. bell\n");
printf("c. count q. quit\n");
ch = get_first();
while ((ch < 'a' || ch > 'c') && ch != 'q')
{
printf("Please respond with a, b, c, or q.\n");
ch = get_first();
}
return ch;
}
char get_first(void)
{
int ch;
ch = getchar();
while (getchar() != '\n')
continue;
return ch;
}
int get_int(void)
{
int input;
char ch;
while (scanf("%d", &input) != 1)
{
while ((ch = getchar()) != '\n')
putchar(ch); // 处理错误输出
printf(" is not an integer.\nPlease enter an ");
printf("integer value, such as 25, -178, or 3: ");
}
return input;
}
下面是该程序的一个运行示例:
Enter the letter of your choice:
a. advice b. bell
c. count q. quit
a
Buy low, sell high.
Enter the letter of your choice:
a. advice b. bell
c. count q. quit
count
Count how far? Enter an integer:
two
two is not an integer.
Please enter an integer value, such as 25, -178, or 3: 5
1
2
3
4
5
Enter the letter of your choice:
a. advice b. bell
c. count q. quit
d
Please respond with a, b, c, or q.
q
要写出一个自己十分满意的菜单界面并不容易。但是,在开发了一种可行的方案后,可以在其他情况下复用这个菜单界面。
学完以上程序示例后,还要注意在处理较复杂的任务时,如何让函数把任务委派给另一个函数。这样让程序更模块化。