C++ 为什么输入时忽略前导零?
当你写C++ 为什么输入时忽略前导零?,c++,language-lawyer,C++,Language Lawyer,当你写inti;cin>>i和输入00325或325,两个输入的行为类似于i=325。但是为什么呢?我认为如果在您输入00325时将I的值设置为0,并且下一个cin>>I,则更为自然导致i=0和下一个cin>>i导致i=325。我知道00325可以是一个八进制数,但我现在输入一个十进制数(我没有使用oct操纵器) 什么书面证据可以保证这种行为?我快速查看了N4140,但找不到任何证据 注意:我不想知道在输出时如何保持前面的零,这在使用cout时如何用前导零填充int中进行了讨论前导零不会被忽略;
inti;cin>>i代码>和输入00325
或325
,两个输入的行为类似于i=325代码>。但是为什么呢?我认为如果在您输入00325
时将I
的值设置为0
,并且下一个cin>>I,则更为自然代码>导致i=0
和下一个cin>>i代码>导致i=325代码>。我知道00325
可以是一个八进制数,但我现在输入一个十进制数(我没有使用oct
操纵器)
什么书面证据可以保证这种行为?我快速查看了N4140,但找不到任何证据
注意:我不想知道在输出时如何保持前面的零,这在使用cout时如何用前导零填充int中进行了讨论前导零不会被忽略;它们在处理时会被考虑,但保存在变量中的结果值与其他一些文本输入的结果值相同
同一个“数学”数字可以有多个文本表示,有时取决于语言环境。对于阿拉伯数字,0325
等于+325
,等于325
。根据选择的区域设置,以下文本可能具有相同的数值:
- 123456.89
- 123.456,89
- 123456.89
- 123 456,89(请记住半空间符号为千分隔符)
让我们不要忘记其他数字书写系统,如罗马或赫布、中文等
多重数字表示的问题甚至比简单的人类传统还要深刻,发生在编程之外的纯数学中。可以证明,像12.9(9)
[12.999999…]这样的有理无止境分数在所有方面都等于13
我认为如果I的值设置为0,则更为自然
这将假定符号“0”在输入解析中的处理方式与[1-9]不同。但是为什么呢?前导零不会被忽略;它们在处理时会被考虑,但保存在变量中的结果值与其他一些文本输入的结果值相同
同一个“数学”数字可以有多个文本表示,有时取决于语言环境。对于阿拉伯数字,0325
等于+325
,等于325
。根据选择的区域设置,以下文本可能具有相同的数值:
- 123456.89
- 123.456,89
- 123456.89
- 123 456,89(请记住半空间符号为千分隔符)
让我们不要忘记其他数字书写系统,如罗马或赫布、中文等
多重数字表示的问题甚至比简单的人类传统还要深刻,发生在编程之外的纯数学中。可以证明,像12.9(9)
[12.999999…]这样的有理无止境分数在所有方面都等于13
我认为如果I的值设置为0,则更为自然
这将假定符号“0”在输入解析中的处理方式与[1-9]不同。但是为什么呢?警告:前面的答案非常无聊
C++14[istream.formatting.Algorithm]^3
转换就像由以下代码片段执行一样进行(使用与
前面的代码片段):
[……]
返回:do_get(in,end,str,err,val)
do_get
随后立即定义([facet.num.get.virtuals]),它以极其详细的方式指定了整个shebang的确切工作方式。我不会复制三页纸的痛苦,只会复制要点
在阶段1中,根据表85和86,根据流标志确定“等效stdio格式说明符”;std::ios_base
的默认值是dec | skipws
,因此我们将遵循该路径(对应于%d
)。此外,还将为下一阶段确定一些其他特定于区域设置和标志的字符
在阶段2中,从流中读取字符并将其累积到缓冲区中;你问题的要点是
如果未放弃,则进行检查以确定是否允许c
作为阶段1返回的转换说明符输入字段的下一个字符。如果是的话,它是累积的
因此,决定是继续读取零还是在单个零后停止取决于上面的%d
;我们会回去的
在阶段3中,累积字符最终转换为long
根据标题
中声明的函数之一的规则:
- 对于有符号整数值,函数
strtoll
%d
说明符和strtoll
都在C标准中定义(C++14指C99);让我们把它们挖出来
在C99§7.19.6.2∗12(当谈论fscanf
)时,被告知
d
匹配可选带符号的十进制整数,其格式与strtol
函数的主题序列的预期格式相同,base
参数的值为10
因此,我们可以在C99§7.20.1.4中找到所有这些都归结为strtol
/strtol
。指定跳过最长的空白序列,然后考虑“主题序列”:
如果base
的值为零,则主题序列的预期形式为6.4.4.1中所述的整数常量,可选择前面加上加号或减号,但不包括整数后缀。如果base
的值介于2和36之间(包括2和36),则主题序列的预期形式是表示in的字母和数字序列
operator>>(int& val);
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);
iter_type get(iter_type in, iter_type end, ios_base& str,
ios_base::iostate& err, long& val) const;