为什么scanf函数(QUOT;%D&QUOT,[...])不会消耗的'\\ n'?而scanf函数(QUOT;%C")呢? [英] Why scanf("%d", [...]) does not consume '\n'? while scanf("%c") does?

查看:132
本文介绍了为什么scanf函数(QUOT;%D&QUOT,[...])不会消耗的'\\ n'?而scanf函数(QUOT;%C")呢?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

这里,我看到了在接受的答案这条语句:


  

大部分的转换说明的跳过前导空白包括换行,但%C 没有。​​


对于我来说,目前还不清楚这下不同行为的理由,我本来期望一个统一的一个(例如总是跳跃或从不)。

我来到这样的问题了一块C $ C $的C是这样的:

 的#includestdio.h中诠释主要(无效){    焦炭CH;
    INT actualNum;    的printf(插入一个数字:);
    scanf函数(%d个,&安培; actualNum);
    //的getchar();    的printf(插入字符:);
    scanf函数(%C,&安培; CH);    返回0;
}

交换这两个 scanf函数取值可以解决问题,还有(评论)的getchar ,否则的'\\ n'第一插入将由第二 scanf函数%C 。我对GCC都在Linux和Windows的测试,该行为是一样的:


  

海湾合作委员会(GCC)4.7.2 20120921(红帽4.7.2-2)结果
  版权所有(C)2012自由软件基金会,公司

  这是自由软件;参见复印条件的来源。有否
  保证;即使不是针对特定目的的适销。


我的问题是:为什么%d个%C 表现不同w.r.t. 的'\\ n' scanf函数


解决方案

从的马的嘴


7.21.6.2 fscanf函数


...结果
5空白字符(S)组成的指令被读取输入到执行
第一个非空白字符(这仍然未读),或直到没有更多的字符可以
被读取。该指令永远不会失败。结果
...结果
7的指令,这是一个特定的转换阳离子科幻科幻德未列名一组匹配的输入序列,如
下面针对每个特定连接器描述。 A转换特定网络阳离子通过以下步骤执行:搜索结果
8输入空白字符(由 isspace为函数特定网络版)被跳过,除非
在特定网络阳离子包括 [ C N 特定连接器

284)搜索结果
9的输入项目是从流中读取,除非特定网络阳离子包括 N 特定连接器。
输入项目被定义为不超过输入字符序列最长
任何特定网络版场宽度,并且,或者是,一个匹配的输入序列pre网络的X.

285)
在第一个字符,如果有的话,之后的输入项保持未读。如果输入的长度
项是零,该指令失败的执行;这个条件是一个匹配失败,除非
最终OF-音响文件,编码错误,或从流读误差prevented输入,在这种
情况下,它是一个输入故障。


284)这些空白字符不是针对一个特定的编场宽度计算。结果
285)的fscanf推回至多一个输入字符到的输入流。因此,一些序列
可以接受的关于strtod,strtol将等等,都是不能接受的FSCANF。

重点由我补充道。

空格不是有效的整数字符串的一部分,所以它是有道理的%d个转换说明跳过任何前导空格。不过,空白可能是对自己有效,因此,它是有道理的%C 转换说明符的的跳过它。

根据以上第5条,如果你把一个空白的前%C 指令格式字符串,所有领先的空白将被忽略:

  scanf函数(%C,&安培; CH);

Here, I saw this statement in the accepted answer:

Most of the conversion specifiers skip leading whitespace including newlines but %c does not.

For me it is not clear the rationale under this different behaviors, I would have expected a uniform one (e.g. always skipping or never).

I came into this kind of problem with a piece of C code like this:

#include "stdio.h"

int main(void){

    char ch;
    int actualNum;

    printf("Insert a number: ");
    scanf("%d", &actualNum);
    // getchar();

    printf("Insert a character: ");
    scanf("%c", &ch);

    return 0;
}

Swapping the two scanfs solves the problem, as well as the (commented) getchar, otherwise the '\n' of the first insertion would be consumed by the second scanf with %c. I tested on gcc both on linux and windows, the behavior is the same:

gcc (GCC) 4.7.2 20120921 (Red Hat 4.7.2-2)
Copyright (C) 2012 Free Software Foundation, Inc.
This is free software; see the source for copying conditions. There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.

So my question is: Why does %d and %c behave differently w.r.t. '\n' in scanf?

解决方案

From the horse's mouth:

7.21.6.2 The fscanf function

...
5 A directive composed of white-space character(s) is executed by reading input up to the first non-white-space character (which remains unread), or until no more characters can be read. The directive never fails.
...
7 A directive that is a conversion specification defines a set of matching input sequences, as described below for each specifier. A conversion specification is executed in the following steps:

8 Input white-space characters (as specified by the isspace function) are skipped, unless the specification includes a [, c, or n specifier. 284)

9 An input item is read from the stream, unless the specification includes an n specifier. An input item is defined as the longest sequence of input characters which does not exceed any specified field width and which is, or is a prefix of, a matching input sequence. 285) The first character, if any, after the input item remains unread. If the length of the input item is zero, the execution of the directive fails; this condition is a matching failure unless end-of-file, an encoding error, or a read error prevented input from the stream, in which case it is an input failure.
284) These white-space characters are not counted against a specified field width.
285) fscanf pushes back at most one input character onto the input stream. Therefore, some sequences that are acceptable to strtod, strtol, etc., are unacceptable to fscanf.

Emphasis added by me.

Whitespace is not part of a valid integer string, so it makes sense for the %d conversion specifier to skip any leading whitespace. However, whitespace may be valid on its own, so it makes sense for the %c conversion specifier to not skip it.

Per clause 5 above, if you put a blank space in the format string prior to the %c directive, all leading whitespace will be skipped:

scanf(" %c", &ch);

这篇关于为什么scanf函数(QUOT;%D&QUOT,[...])不会消耗的'\\ n'?而scanf函数(QUOT;%C")呢?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆