输入时为什么忽略前导零?

ynn*_*ynn 0 c++ language-lawyer

当你写int i; cin >> i;输入00325325,两者的投入表现得像i = 325;.但为什么?我认为如果你输入i的价值设定为更自然,那么下一个产生了,而下一个产生了.我知道可以是八进制数,但我现在输入数字作为十进制数(我不使用操纵器).000325cin >>i;i = 0;cin >> i;i = 325;00325oct

什么书面证据保证了这种行为?我快速浏览了N4140,却找不到任何证据.

注意:我想要的是不知道在输出时保持前面的零的方法,这在使用cout << operator时如何用前导零填充int中讨论.


一旦有人给我这样的句子,我的问题就会得到解决

preceding zeros are ignored when setting a number-type object as the right operand of <<

在一些可靠的文件中.

Mat*_*lia 5

警告: 非常无聊的回答

C++ 14 [istream.formatting.arithmetic]3

operator>>(int& val);
Run Code Online (Sandbox Code Playgroud)

转换发生时好像由以下代码片段执行(使用与前面的代码片段相同的表示法):

typedef num_get<charT,istreambuf_iterator<charT,traits> > numget;
iostate err = ios_base::goodbit;
long lval;
use_facet<numget>(loc).get(*this, 0, *this, err, lval);
if (lval < numeric_limits<int>::min()) {
    err |= ios_base::failbit;
    val = numeric_limits<int>::min();
} else if (numeric_limits<int>::max() < lval) {
    err |= ios_base::failbit;
    val = numeric_limits<int>::max();
} else
    val = static_cast<int>(lval);
setstate(err);
Run Code Online (Sandbox Code Playgroud)

这里的咕噜声完成了num_get::get,在[facet.num.get.members]中指定了1:

iter_type get(iter_type in, iter_type end, ios_base& str,
     ios_base::iostate& err, long& val) const;
Run Code Online (Sandbox Code Playgroud)

[...] 返回:do_get(in, end, str, err, val).

do_get然后立即定义([facet.num.get.virtuals]),其中详细说明了整个shebang的确切运作.我不会复制三页的痛苦,而只是重点.

在阶段1中,根据流标志确定"等效的stdio格式说明符",如表85和86所示; std::ios_baseis 的默认值dec | skipws,所以我们将遵循该路径(对应于%d).此外,还为下一阶段确定了一些其他区域设置和特定于标志的字符.

在阶段2中,从流中读取字符并将其累积在缓冲器中; 你问题的关键点在于

如果它没有被丢弃,则进行检查以确定是否c允许作为阶段1返回的转换说明符的输入字段的下一个字符.如果是,则累积它

因此,决定是继续阅读你的零还是在一个零之后停止取决于%d上述情况; 我们会回到它.

在阶段3中,累积的字符最终转换为a long

通过标题中声明的其中一个函数的规则<cstdlib>:

  • 对于有符号整数值,该函数strtoll.

说明%d符和strtollC语言都定义了(C++ 14指的是C99); 让我们把它们挖出来.

C99§7.19.6.212(谈论时fscanf),它被告知

d匹配可选带符号的十进制整数,其格式与strtol函数的主题序列的预期相同,base参数值为10 .

所以这一切归结为strtol/ strtoll,我们可以在C99§7.20.1.4找到.指定跳过最长的空白序列,然后考虑"主题序列":

如果值base为零,则主题序列的预期形式是如6.4.4.1中所述的整数常量的形式,可选地前面带有加号或减号,但不包括整数后缀.如果值base介于2和36之间(包括),则主题序列的预期形式是字母和数字序列,表示具有指定基数的整数base,可选地前面带有加号或减号,但不包括整数后缀.来自a(或A)到z(或Z)的字母归属于值10到35; 只允许其归属值小于基数的字母和数字.如果值为base16,则字符0x0X可选地在字母和数字序列之前,如果存在则在符号之后.

主题序列被定义为输入字符串的最长初始子序列,从第一个非空白字符开始,即预期形式.如果输入字符串为空或完全由空格组成,或者第一个非空白字符不是符号或允许的字母或数字,则主题序列不包含任何字符.

如果主题序列具有预期形式且值base为零,则根据6.4.4.1的规则将以第一个数字开头的字符序列解释为整数常量.如果主题序列具有预期形式并且值base在2和36之间,则将其用作转换的基础,将其值归于每个字母,如上所述.如果主题序列以减号开头,则转换产生的值将被否定(在返回类型中).

(ibidem,3-5)

如您所见,对于前导零没有特殊规定; 如果它是一个有效的数字,它将进入主题序列,在同一批次中进行处理.