当您撰写21600
并输入int i; cin >> i;
或00325
时,两个输入的行为都与325
相同。但为什么?我认为当您输入i = 325;
时i
的值设置为0
,而下一个00325
产生cin >>i;
并且下一个i = 0;
产生了cin >> i;
。我知道i = 325;
可以是八进制数,但我现在输入数字作为十进制数字(我没有使用00325
操纵器)。
哪些书面证据可以保证这种行为?我快速浏览了N4140,却找不到任何证据。
注意:我想要的是不知道在输出时保留前面的零的方法,这在How can I pad an int with leading zeros when using cout << operator?中讨论。
只要有人给我一个像
这样的句子,我的问题就会得到解决 oct
在一些可靠的文件中。
答案 0 :(得分:5)
警告: 提前非常无聊的答案
C ++ 14 [istream.formatting.arithmetic]¶3
operator>>(int& val);
转换发生时好像由以下代码片段执行(使用与for相同的表示法) 前面的代码片段):
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);
这里的咕噜声工作由num_get::get
完成,在{em> [facet.num.get.members]¶1指定:
之后立即定义iter_type get(iter_type in, iter_type end, ios_base& str, ios_base::iostate& err, long& val) const;
[...] 返回:
do_get(in, end, str, err, val)
。
do_get
( [facet.num.get.virtuals] ),其中详细说明了整个shebang的确切工作方式。我不会复制三页的痛苦,而只是重点。
在阶段1中,根据流标志确定“等效stdio格式说明符”,如表85和86所示; std::ios_base
的默认值为dec | skipws
,因此我们将遵循该路径(对应于%d
)。此外,还为下一阶段确定了一些其他区域设置和特定于标志的字符。
在阶段2中,从流中读取字符并将其累积在缓冲区中;你的问题的关键点是
如果没有丢弃,则进行检查以确定是否允许
c
作为阶段1返回的转换说明符的输入字段的下一个字符。如果是,则累计
因此,决定继续阅读你的零或在一个零之后停止取决于上面的%d
;我们会回到它。
在第3阶段,累积的字符最终转换为long
通过标题
<cstdlib>
中声明的其中一个函数的规则:
- 对于有符号整数值,函数
strtoll
。
%d
说明符和strtoll
都在C标准中定义(C ++ 14指的是C99);让我们把它们挖出来。
在C99§7.19.6.2¶12(谈论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;只允许其归属值小于基数的字母和数字。如果base
的值为16,则字符0x
或0X
可以选择在字母和数字序列之前,如果存在,则在符号后面。主题序列被定义为输入字符串的最长初始子序列,从第一个非空白字符开始,即预期形式。如果输入字符串为空或完全由空格组成,或者第一个非空白字符不是符号或允许的字母或数字,则主题序列不包含任何字符。
如果主题序列具有预期形式且
base
的值为零,则根据6.4.4.1的规则将以第一个数字开头的字符序列解释为整数常量。如果主题序列具有预期形式并且base
的值在2和36之间,则将其用作转换的基础,将其值归于每个字母,如上所述。如果主题序列以减号开头,则转换产生的值将被否定(在返回类型中)。
(ibidem,¶3-5)
正如您所看到的,对于前导零没有特殊规定;如果它是一个有效的数字,它将进入主题序列,并在同一批次中进行处理。
答案 1 :(得分:1)
不会忽略前导零;它们在处理时被考虑,但保存在变量中的结果值与其他一些文本输入相同。
相同的“数学”数字可以有多个文本表示,有时取决于区域设置。对于阿拉伯数字,0325
等于+325
且等于325
。根据所选的区域设置,以下文本可能具有相同的数值:
让我们不要忘记其他数字书写系统,如罗马或Herbew,中文等。
多个数字表示的问题甚至比简单的人类传统更深,并且发生在编程之外的纯数学中。可以证明,像12.9(9)
[12.9999999 ...]这样的理性无穷分数在所有方面都与13
相等。
我认为如果我的值设置为0则更自然
这将假设符号“0”在输入解析中与[1-9]区别对待。但为什么呢?