C++ scanf%la返回0

Art*_*rez 7 c++ scanf

Win7 64-bit
gcc 4.8.2
g++ -Wall
Run Code Online (Sandbox Code Playgroud)

我尝试格式化我的C++ sscanf,如为什么scanf()需要"%lf"为双打,当printf()只用"%f"时可以吗?但是回报是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;
}
Run Code Online (Sandbox Code Playgroud)

产量

 Example 1.2 buffer -> 0x1.3333333333333p+0
 Example 1.2 scanf <- 0
Run Code Online (Sandbox Code Playgroud)

Kei*_*son 2

[更新:Cygwin 运行时库“newlib”在处理十六进制浮点输入时存在一个错误。截至 2021 年 4 月,修复已提交但尚未发布。]

我看你的代码没有任何问题。当我在 Linux 系统上编译并运行它时,输出是:

    Example 1.2 buffer -> 0x1.3333333333333p+0
    Example 1.2 scanf <- 1.2
Run Code Online (Sandbox Code Playgroud)

和函数%a的说明符在C99 中引入,并合并到 C++11 中。对于调用,是 类型参数的有效格式,对于调用是 类型参数的有效格式。*printf*scanfsprintf"%a"doublesscanf"%la"double*

gcc(或g++)的版本与问题没有直接关系。gcc 只是编译器;该sscanf功能由运行时库实现。

当我在 Windows 7 上的 Cygwin 下编译并运行您的程序时,我得到与您相同的错误输出。Cygwin 使用“newlib”C 库,该库与大多数 Linux 系统上使用的 glibc 库不同。

如果您使用的是 gcc 的 MinGW 安装,如果我没记错的话,它使用 Microsoft C 库。sscanf微软对1990年以后的C标准的支持并不好,所以如果它没有正确实现的格式也不足为奇"%la"

请注意,您不需要使用"%la"十六进制输入。对于*scanf函数,aefg说明符都是等效的,并且接受十进制或十六进制浮点输入。所以你应该能够使用:

sscanf(buffer, "%lf", &x);
Run Code Online (Sandbox Code Playgroud)

但如果"%la"不起作用,很可能"%lf"也不起作用。

sscanf函数返回一个int结果,指示成功扫描的项目数。您应该始终检查该结果。(虽然我在 Cygwin 上的实验有任何指导意义,但在这种情况下它不会有任何好处;sscanf返回1但仍设置x0.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;
}
Run Code Online (Sandbox Code Playgroud)

在我的 Linux 系统上,我得到了正确的输出,即:

sprintf returned 20, buffer = "0x1.3333333333333p+0"
sscanf returned 1, x = 1.200000
Run Code Online (Sandbox Code Playgroud)

在 Cygwin 下,我得到以下输出:

sprintf returned 20, buffer = "0x1.3333333333333p+0"
sscanf returned 2, x = 0.000000, leftover = "x1.3333333333333p+0"
Run Code Online (Sandbox Code Playgroud)

这表明该"%lf"格式导致sscanf仅消耗0,而使字符串的其余部分由 消耗"%s"。这是 C90 实现的特征(之前"%a"已添加到标准中)——但printf可以"%a"正常工作。

在您的系统上尝试一下。

7年后更新:我在 Windows 10 下仍然看到 Cygwin 存在同样的问题。进一步的实验表明它不支持格式说明符十六进制浮点输入。在 C99 及更高版本中, then 、、和说明符的行为方式都相同,接受十进制或十六进制输入,因此,例如,格式应该接受像 这样的输入。我已向 Cygwin 邮件列表提交了错误报告:https://cygwin.com/pipermail/cygwin/2021-April/248315.html%aaefg%la1.0

更新 2:补丁已推送到 newlib-cygwin,应该可以修复此问题,并且新的开发人员快照可用。如果一切顺利,我认为 Cygwin 将很快通过此修复进行更新。

https://cygwin.com/pipermail/cygwin/2021-April/248323.html