c---字符输入/输出和输入验证

创建更友好的用户界面

使用缓冲输入

/* guess.c */
#include <stdio.h>
int main(void)
{
    int  guess = 1;
    printf("Pick an integer from 1 to 100. I will try to guess it\n");
    printf("Respond with a y if my guess is right and with a n if it is wrong.\n");
    printf("Uh...is your number %d?\n", guess);

    while (getchar() != 'y')
    {
        printf("Well, then, is it %d?\n", ++guess);
    }
    printf("I knew I could do it\n");
    return 0;

}
mali@mali:~/code/file$ gcc guess.c -o guess
mali@mali:~/code/file$ ./guess
Pick an integer from 1 to 100. I will try to guess it
Respond with a y if my guess is right and with a n if it is wrong.
Uh...is your number 1?
n
Well, then, is it 2?
Well, then, is it 3?
n
Well, then, is it 4?
Well, then, is it 5?
y
I knew I could do it
mali@mali:~/code/file$ 

可以看到,每次输入n时,程序打印了两条消息。这是由于程序读取n作为用户否定了数字1,然后还读取了一个换行符作为用户否定了数字2.

一种解决方案是:使用while循环丢弃输入行最后剩余的内容,包括换行符。这种方法的优点是:能把no和no way这样的响应视为简单的n。

/* guess.c */
#include <stdio.h>
int main(void)
{
    int  guess = 1;
    printf("Pick an integer from 1 to 100. I will try to guess it\n");
    printf("Respond with a y if my guess is right and with a n if it is wrong.\n");
    printf("Uh...is your number %d?\n", guess);

    while (getchar() != 'y')
    {
        printf("Well, then, is it %d?\n", ++guess);
        while (getchar() != '\n')
            continue;
    }
    printf("I knew I could do it\n");
    return 0;

}
mali@mali:~/code/file$ gcc guess1.c -o guess1
mali@mali:~/code/file$ ./guess1
Pick an integer from 1 to 100. I will try to guess it
Respond with a y if my guess is right and with a n if it is wrong.
Uh...is your number 1?
n
Well, then, is it 2?
no
Well, then, is it 3?
no sir
Well, then, is it 4?
forget it
Well, then, is it 5?
y
I knew I could do it
mali@mali:~/code/file$ 

这的确解决了换行符的问题。但是,程序还是会把fp视为n。

我们用if语句筛选其他响应。

/* guess1.c */
#include <stdio.h>
int main(void)
{
    int  guess = 1;
    char response;
    printf("Pick an integer from 1 to 100. I will try to guess it\n");
    printf("Respond with a y if my guess is right and with a n if it is wrong.\n");
    printf("Uh...is your number %d?\n", guess);

    while ((response = getchar()) != 'y')
    {
        if (response == 'n')
            printf("Well, then, is it %d?\n", ++guess);
        else
            printf("Sorry, I understand only y or n.\n");
        while (getchar() != '\n')
            continue;
    }
    printf("I knew I could do it\n");
    return 0;

}

mali@mali:~/code/file$ ./guess2
Pick an integer from 1 to 100. I will try to guess it
Respond with a y if my guess is right and with a n if it is wrong.
Uh...is your number 1?
n
Well, then, is it 2?
no
Well, then, is it 3?
no sir
Well, then, is it 4?
forget it
Sorry, I understand only y or n.
n
Well, then, is it 5?
y
I knew I could do it
mali@mali:~/code/file$ 

在编写交互式程序时,应该事先预料到用户可能会输入错误,然后设计程序处理用户的错误输入。在用户出错时通知用户再次输入。

混合数值和字符输入

假设程序要求用getchar()处理字符输入,用scanf()处理数值输入,这两个函数都能很好地完成任务,但是不能把它们混用。因为getchar()读取每个字符,包括空格、制表符和换行符,而scanf()在读取数字时会跳过空格、制表符和换行符。

该程序读入一个字符和两个数字,然后根据输入的两个数字指定的行数和列数打印该字符。

 

输入验证

在实际应用中,用户不一定会按照程序的指令行事。用户的输入和程序期望的输入不匹配时常发生,这会导致程序运行失败。作为程序员,除了完成编程的本职工作,还要事先预料一些可能的输入错误,这样才能编写出能检测并处理这些问题的程序。

例如,假设你编写了一个处理非负整数的循环,但是用户很可能输入一个负数。可以使用关系表达式来排除这种情况:

long n;
scanf("%ld", &n);//获取第一个值
while (n >= 0)//检测不在范围内的值
{
    //处理n
    scanf("%ld", &n); //获取下一个值
}

另一类潜在的陷阱是:用户可能输入错误类型的值,如字符q。排除这种情况的一种办法是,检查scanf()的返回值。scanf()返回成功读取项的个数。因此,下面的表达式当且仅当用户输入一个整数时才为真:

scanf("%ld", &n) == 1

结合上面的while循环,可改进为:

long n;
while (scanf("%ld", &n) == 1&& n >= 0)
{
    //处理n
}

while循环条件可以描述为:“当输入是一个整数且该整数为非负整数时”。

对于最后的例子,当用户输入错误类型的值时,程序结束。然而,可以让程序友好些,提示用户再次输入正确类型的值。在这种情况下,要处理有问题的输入。如果scanf()没有成功获取,就会将其留在输入队列中。这里要明确,输入实际上是字符流。可以使用getchar()函数逐字符地读取输入,甚至可以把这些想法都结合在一个函数中:

/* input.c */
#include <stdio.h>
int main(void)
{
    long input;
    int num = 0;
    puts("please input an integer greater than 0 or equal to 0");
    while ((num = scanf("%ld", &input)) != 1 || input < 0)
    {
        if (num != 1 )
            puts("the input value is not an integer");
        else if (input < 0)
            puts("the input value is less than 0");
        while (getchar() != '\n')
            continue;
        puts("please input an integer greater than 0 or equal to 0");
    }
    printf("input:%ld\n", input);
    return 0;

}

mali@mali:~/code/file$ ./input
please input an integer greater than 0 or equal to 0
a
the input value is not an integer
please input an integer greater than 0 or equal to 0
-9
the input value is less than 0
please input an integer greater than 0 or equal to 0
hello
the input value is not an integer
please input an integer greater than 0 or equal to 0
-10
the input value is less than 0
please input an integer greater than 0 or equal to 0
e
the input value is not an integer
please input an integer greater than 0 or equal to 0
10
input:10
mali@mali:~/code/file$ 

 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值