Win7 64-bit
gcc 4.8.2
g++ -Wall
我尝试按照 Why does scanf() need "%lf" for doubles, when printf() is okay with just "%f"? 中的定义格式化我的 C++ sscanf但返回的是x == 0。程序如下。我不知道我做错了什么,所以欢迎任何建议。
# include <stdio.h>
# include <ios>
# include <iostream>
# include <iomanip>
#include <cstdlib>
using namespace std;
int main(int argc, char** argv) {
char buffer[30];
double x = 5.0;
sprintf(buffer, "%a", 1.2);
sscanf(buffer, "%la", &x);
cout << " Example 1.2 buffer -> " << buffer << endl;
cout << " Example 1.2 scanf <- " << x << endl;
return 0;
}
输出
Example 1.2 buffer -> 0x1.3333333333333p+0
Example 1.2 scanf <- 0
最佳答案
[更新:在处理十六进制浮点输入的 Cygwin 运行时库“newlib”中存在一个错误。截至 2021 年 4 月,已提交修复程序但尚未发布。]
我看不出你的代码有什么问题。当我在我的 Linux 系统上编译并运行它时,输出是:
Example 1.2 buffer -> 0x1.3333333333333p+0
Example 1.2 scanf <- 1.2
*printf
和 *scanf
函数的 %a
说明符在 C99 中引入,并合并到 C++11 中。对于 sprintf
调用,"%a"
是 double
类型参数的有效格式,对于 sscanf
code> 调用 "%la"
是 double*
类型参数的有效格式。
gcc(或 g++)的版本与问题没有直接关系。 gcc 只是编译器; sscanf
函数由运行时库实现。
当我在 Windows 7 上的 Cygwin 下编译和运行您的程序时,我得到了与您相同的错误输出。 Cygwin 使用“newlib”C 库,它不同于大多数 Linux 系统上使用的 glibc 库。
如果您使用的是 gcc 的 MinGW 安装,如果我没记错的话,它会使用 Microsoft C 库。微软对 1990 以后的 C 标准的支持并不好,所以如果它没有正确实现 sscanf
的 "%la"
格式也就不足为奇了。
请注意,您不需要使用 "%la"
进行十六进制输入。对于 *scanf
函数,a
、e
、f
和 g
说明符都是等效的,并且将接受十进制或十六进制浮点输入。所以你应该能够使用:
sscanf(buffer, "%lf", &x);
但是如果 "%la"
不起作用,那么 "%lf"
也可能不起作用。
sscanf
函数返回一个 int
结果,指示成功扫描了多少项目。您应该始终检查该结果。 (虽然如果我在 Cygwin 上的实验有任何指导作用,它在这种情况下不会有任何好处;sscanf
返回 1
但仍设置 x
到 0.0
。)
底线:您的代码没问题,但您使用的运行时库可能不支持您尝试执行的操作。
这是另一个程序(它是直接的 C,但它应该像 C++ 一样工作)应该提供更多信息。 sprintf
返回写入的字符数; sscanf
返回读取的项目数。
#include <stdio.h>
int main(void) {
char buffer[40];
char leftover[40];
double x = 5.0;
int sprintf_result = sprintf(buffer, "%a", 1.2);
printf("sprintf returned %d, buffer = \"%s\"\n", sprintf_result, buffer);
int sscanf_result = sscanf(buffer, "%lf%s", &x, leftover);
printf("sscanf returned %d, x = %f", sscanf_result, x);
if (sscanf_result >= 2) {
printf(", leftover = \"%s\"", leftover);
}
putchar('\n');
return 0;
}
在我的 Linux 系统上,我得到了正确的输出,即:
sprintf returned 20, buffer = "0x1.3333333333333p+0"
sscanf returned 1, x = 1.200000
在 Cygwin 下,我得到了这个输出:
sprintf returned 20, buffer = "0x1.3333333333333p+0"
sscanf returned 2, x = 0.000000, leftover = "x1.3333333333333p+0"
这表示 "%lf"
格式导致 sscanf
仅使用 0
,而剩下的字符串将被使用通过 "%s"
。这是 C90 实现的特征(在 "%a"
被添加到标准之前)——但是 printf
的 "%a"
工作正常。
在你的系统上试试这个。
更新 7 年后:我仍然在 Windows 10 下看到与 Cygwin 相同的问题。进一步的实验表明它不支持 either %a
格式说明符 < em> 或 十六进制浮点输入。在 C99 及更高版本中,a
、e
、f
和 g
说明符的行为都相同,接受十进制或十六进制输入,例如,%la
格式应该接受像 1.0
这样的输入。我已经向 Cygwin 邮件列表提交了错误报告:https://cygwin.com/pipermail/cygwin/2021-April/248315.html
更新 2:已将补丁推送到 newlib-cygwin,应该可以解决此问题,并且可以使用新的开发人员快照。如果一切顺利,我想 Cygwin 很快就会更新这个修复程序。
关于C++ scanf %la 返回 0,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/23900921/