`strtod(&Q;3EX&q;,&;end)`应该是什么结果?‘sscanf’怎么样? [英] What is the result of `strtod("3ex", &end)` supposed to be? What about `sscanf`?
本文介绍了`strtod(&Q;3EX&q;,&;end)`应该是什么结果?‘sscanf’怎么样?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!
问题描述
在我的实验中,此表达式
double d = strtod("3ex", &end);
用3.0
初始化d
,并将end
指针放在输入字符串中的'e'
字符处。这正是我期望它的表现。'e'
字符可能看起来是指数部分的开头,但由于缺少实际指数值(6.4.4.2所需),因此'e'
应被视为完全独立的字符。
但是,当我这样做时
double d;
char c;
sscanf("3ex", "%lf%c", &d, &c);
我注意到sscanf
使用'3'
和'e'
作为%lf
格式说明符。变量d
接收3.0
值。变量c
以'x'
结尾。这在我看来很奇怪,原因有两个。
%f
格式说明符的行为时引用了strtod
,因此我直观地期望%lf
以与strtod
相同的方式处理输入(即选择与终止点相同的位置)。但是,我知道在历史上scanf
应该向输入流返回不超过一个字符。这将scanf
可以执行的任何前瞻的距离限制为一个字符。并且上面的示例需要至少两个字符的前瞻。因此,假设我接受%lf
同时使用输入流中的'3'
和'e'
这一事实。
然后我们遇到了第二个问题。现在sscanf
必须将该"3e"
转换为类型double
。"3e"
不是浮点常量的有效表示形式(同样,根据6.4.4.2,指数值不是可选的)。我希望sscanf
将此输入视为错误:在%lf
转换期间终止,返回0
,并保持d
和c
不变。但是,上述sscanf
已成功完成(返回2
)。
这一行为在GCC和标准库的msvc实现中是一致的。
那么我的问题是,在C语言标准文档中,究竟在什么地方允许sscanf
如上所述的行为,指的是上述两点:消费多于strtod
行为,并且成功地将"3e"
这样的序列转换为"3e"
?
通过查看我的实验结果,我可能可以对sscanf
的行为进行"反向工程":尽可能"看起来正确"而不后退,然后只将使用的序列传递给strtod
。这样,'e'
被%lf
消费,然后被strtod
忽略。但是语言规范中就只有这些吗?
推荐答案
我只是在die.net
上找到下面的描述strtod()、strtof()和strtered()函数将初始 NPTR指向双精度、浮点型和长整型的字符串部分 分别为双重表示。 字符串(初始部分)的预期形式是可选的 isspace(3)识别的前导空格,可选加号 (‘+’)或减号(‘-’),然后(I)一个十进制数,或 (Ii)十六进制数;或(Iii)无穷大;或(Iv)NaN (不是数字)。 十进制数由非空的十进制数字序列组成 可能包含基数字符(小数点, 取决于区域设置,通常为"."),可选择后跟小数 指数。十进制指数由"E"或"e"组成,后跟 可选的加号或减号,后跟一个非空序列 十进制数字,表示乘以10的幂。 十六进制数由"0x"或"0x"后跟非空 可能包含基数字符的十六进制数字序列, 可选地后跟二进制指数。一个二进制指数由 表示"p"或"p",后跟一个可选的加号或减号 用非空的十进制数字序列表示乘法 2的幂。基数字符和二进制指数中的至少一个 必须存在。无穷大可以是"INF"或"infinity",不区分大小写。
NaN可以选择"nan"(不区分大小写)后跟‘(’,a 字符序列,后跟‘)’。字符串 以依赖于实现的方式指定NaN的类型。
然后我做了一个实验,我和GCC一起执行了下面的代码
#include <stdlib.h>
#include <stdio.h>
char head[1024], *tail;
void core(const char *stmt){
sprintf(head, "%s", stmt);
double d=strtod(head, &tail);
printf("cover %s to %.2f with length=%ld.
", head, d, tail-head);
}
int main(){
core("3.0x");
core("3e");
core("3ex");
core("3e0x");
return 0;
}
并获取结果
cover 3.0x to 3.00 with length=3.
cover 3e to 3.00 with length=1.
cover 3ex to 3.00 with length=1.
cover 3e0x to 3.00 with length=3.
因此,"e"后面似乎应该有一些数字。
对于sscanf
,我用GCC代码做了另一个实验:
#include <stdlib.h>
#include <stdio.h>
char head[1024];
void core(const char *stmt){
int i;sscanf(stmt, "%x%s", &i, head);
printf("sscanf %s catch %d with '%s'.
", stmt, i, head);
}
int main(){
core("0");
core("0x0g");
core("0x1g");
core("0xg");
return 0;
}
然后获取以下输出:
sscanf 0 catch 0 with ''.
sscanf 0x0g catch 0 with 'g'.
sscanf 0x1g catch 1 with 'g'.
sscanf 0xg catch 0 with 'g'.
sscanf似乎会尝试捕获更多字符,如果它当前判断它是合法的(可能是非法的,情况不完整),它将不会回滚。
这篇关于`strtod(&Q;3EX&q;,&;end)`应该是什么结果?‘sscanf’怎么样?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!
查看全文