strtol
的规范在概念上将输入字符串分为“初始空格”,“主题序列”和“最终字符串”,并将“主题序列”定义为:
输入字符串的最长初始子序列,从第一个具有预期形式的非空白字符开始。如果输入字符串为空或完全由空格字符组成,或者第一个非空白字符不是符号或允许的字母或数字,则主题序列不应包含任何字符。
有一次,我认为“最长的初始子序列”业务类似于scanf
的工作方式,"0x@"
将扫描为"0x"
,匹配失败,然后是{{ 1}}作为下一个未读的角色。但是,在经过一些讨论后,我基本上确信"@"
处理了预期形式的最长初始子序列,而不是最长的初始字符串,它是预期形式的某些可能字符串的初始子序列。
令我困惑的是规范中的这种语言:
如果主题序列为空或者没有预期的形式,则不进行转换; str的值存储在endptr指向的对象中,前提是endptr不是空指针。
如果我们接受似乎是“主题序列”的正确定义,那么就没有不具有预期形式的非空主题序列,而是(以避免冗余和混淆)文本应该只读:
如果主题序列为空,则不执行转换; str的值存储在endptr指向的对象中,前提是endptr不是空指针。
有人可以为我澄清这些问题吗?也许与过去的讨论或任何相关缺陷报告的链接将是有用的。
答案 0 :(得分:3)
我认为C99语言很清楚:
主题序列被定义为最长的初始子序列 输入字符串,从第一个非空白字符开始, 这是预期的形式。
鉴于"0x@"
,"0x@"
不符合预期格式; "0x"
不符合预期的格式;因此"0"
是最长的初始子序列,具有预期的形式。
我同意这意味着您不能拥有非空的主题序列,而不是预期的形式 - 除非您解释以下内容:
除
"C"
区域设置以外的其他区域设置主题 序列表格可以被接受。
...允许区域设置定义主题序列可能具有的其他可能形式,但仍然不是“预期形式”。
最后一段中的措辞似乎只是“带括号”。
答案 1 :(得分:2)
如果您从§7.20.1.4(strtol,strtoll,strtoul和strtoull函数)开始,可能更容易理解C99标准的¶2,而不是¶4:
¶2strtol,strtoll,strtoul和strtoull函数转换初始值 nptr指向long int的字符串部分,long long int,unsigned long int和unsigned long long int表示。第一, 他们将输入字符串分解为三个部分:一个初始的,可能是空的序列 空白字符(由isspace函数指定),主题序列 类似于由base的值确定的某个基数表示的整数,和a 一个或多个无法识别的字符的最终字符串,包括终止null 输入字符串的字符。然后,他们尝试将主题序列转换为 整数,并返回结果。
¶3如果base的值为零,则主题序列的预期形式为a的预期形式 6.4.4.1中描述的整数常量,可选地前面带有加号或减号,但是 不包括整数后缀。如果base的值在2到36之间(包括),则 主题序列的预期形式是表示一个的字母和数字的序列 具有由base指定的基数的整数,可选地前面带有加号或减号, 但不包括整数后缀。来自(或A)到z(或Z)的字母是 归因于10到35的值;只有字母和数字的归属值较小 允许比基地的。如果base的值是16,则字符0x或0X可以 可选地在字母和数字序列之前,如果存在则在符号后面。
¶4主题序列被定义为输入字符串的最长初始子序列,...
特别是,¶3阐明了主题序列是什么。
答案 2 :(得分:1)
POSIX spec for strtol似乎更清晰:
这些函数应分别将str指向的字符串的初始部分转换为long和long long类型。首先,他们将输入字符串分解为三个部分:
一个初始的,可能是空的白色空格字符序列(由isspace()指定)
主题序列被解释为以某个基数表示的整数,由基数值确定
- 醇>
一个或多个无法识别的字符的最终字符串,包括输入字符串的终止NUL字符。
然后他们将尝试将主题序列转换为整数,并返回结果。
但当然,它不是规范性的,并且“遵循ISO C标准”。
答案 3 :(得分:1)