C++ scanf %la 返回 0

标签 c++ cygwin scanf

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 函数,aefg说明符都是等效的,并且将接受十进制或十六进制浮点输入。所以你应该能够使用:

sscanf(buffer, "%lf", &x);

但是如果 "%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;
}

在我的 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 及更高版本中,aefg 说明符的行为都相同,接受十进制或十六进制输入,例如,%la 格式应该接受像 1.0 这样的输入。我已经向 Cygwin 邮件列表提交了错误报告:https://cygwin.com/pipermail/cygwin/2021-April/248315.html

更新 2:已将补丁推送到 newlib-cygwin,应该可以解决此问题,并且可以使用新的开发人员快照。如果一切顺利,我想 Cygwin 很快就会更新这个修复程序。

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

关于C++ scanf %la 返回 0,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/23900921/

相关文章:

c++ - 并行 I/O SSD 与 HDD 的惊人结果

c++ - 调用需要引用 vector 的函数时崩溃

c++ - 如何将十六进制字符串转换为 C++ 中相应的整数?

C++异或加密截断文件

c - 如何在C中实现AES加密?

c - 使用 sscanf() 函数读取字符串

gdb - Cygwin 与 CodeBlocks 调试器错误

c++ - cygwin 上的 gcc 4.7.3 是否支持 C++11 并发特性?

c - scanf 输入的 %d 间距

c - c语言获取和检查字符串