当输入是int和string的混合时,Scanf读取两次

时间:2017-05-21 08:32:06

标签: c string loops io scanf

我试图从stdin读取一个整数,然后读取字符串char:char:

#include <stdio.h>
int main(int argc, char const *argv[])
{
    int T,N,i;
    scanf("%d",&T);

    while ( T-- )
    {
        scanf("%d",&N);
        printf("N is %d\n",N );
        char ch = getchar();

        while ( (int)ch != '\n')
        {
            ch = getchar();
        }

        // printf("Outside.\n");
    }
    return 0;
}

我的意见是:

4
7
cookie milk milk cookie milk cookie milk
5
cookie cookie milk milk milk
4
milk milk milk milk
1
cookie

但是在运行时,我得到的输出如下:

./COOMILK < input.txt
N is 7
N is 7
N is 5
N is 5

为什么两次读取相同的值?

2 个答案:

答案 0 :(得分:3)

想想用户在做什么。他键入一个数字然后是什么?他打进了!这是换行符,它被插入到stdin缓冲区中,等待程序读取。

因此,当您尝试读取字符时,从之前存储的换行符获取,这解释了您正在目睹的行为。

无需转换ch来检查内循环中的换行符。而且,内环在循环中会更好。

getchar()返回一个int,而不是一个char,所以我会更改它,并考虑到EOF。阅读I'm trying to understand getchar() != EOF中的更多内容。

正如Ed Heal指出的那样,您可以利用scanf()的返回值来确保 读取整数。

我会将您的更改为:

int ch;
while ( T-- )
{
    if(scanf("%d", &N) != 1) // read the integer and check the return value
    {
        printf("I was expecting to read an integer! Exiting...\n");
        return 1;
    }
    ch = getchar();                      // consume the newline
    printf("N is %d\n",N );
    do {
       ch = getchar();                   // read the string char by char
       printf("%c", ch);                 // while printing every char
    } while (ch != '\n' || ch == EOF);   // until you see the newline
}

输出:

Georgioss-MacBook-Pro:~ gsamaras$ gcc -Wall main.c 
Georgioss-MacBook-Pro:~ gsamaras$ ./a.out < input.txt 
N is 7
cookie milk milk cookie milk cookie milk
N is 5
cookie cookie milk milk milk
N is 4
milk milk milk milk
N is 1
cookie

答案 1 :(得分:1)

有些聪明?!使用scanf - 参见手册页 - 您可以将代码简化为:

#include <stdio.h>
int main(int argc, char const *argv[])
{
    int T,N,i;
    if (scanf("%d\n",&T) != 1) { // Notice the new line
       // Do so error reporting
       return 1;
    }

    while ( T-- )
    {
        if (scanf("%d\n%*[^\n]\n",&N) != 1) { // Please see scanf for an explaination
           // Do some error reporting
           return 1;
        }
    }
    return 0;
}

修改

scanf格式的说明

  1. %d - 读取整数
  2. \ n - 阅读新行
  3. %* [^ \ n} - 读取除新行之外的任何内容,丢弃结果
  4. \ n - 最后阅读新行