C ++ scanf%la返回0

时间:2014-05-28 00:08:13

标签: c++ 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

2 个答案:

答案 0 :(得分:1)

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

    Example 1.2 buffer -> 0x1.3333333333333p+0
    Example 1.2 scanf <- 1.2

%a*printf函数的*scanf说明符是在C99中引入的,并且已合并到C ++ 11中。对于sprintf调用,"%a"double类型参数的有效格式,而sscanf调用"%la"是参数的有效格式类型为double*

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

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

如果您正在使用gcc的MinGW安装,如果我没记错,它会使用Microsoft C库。微软在1990年以后对C标准的支持并不好,如果它没有正确实现sscanf的{​​{1}}格式,那就太不足为奇了。

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

g

但如果sscanf(buffer, "%lf", &x); 无法正常工作,"%la"可能无法正常工作。

"%lf"函数返回sscanf结果,表示已成功扫描的项目数。你应该经常检查结果。 (虽然如果我在Cygwin上的实验是任何指南,在这种情况下它不会有任何好处; int返回sscanf但仍然将1设置为x。 )

结论:您的代码没问题,但您可能正在使用的运行时库不支持您尝试做的事情。

这是另一个程序(它是直接的C但它应该像C ++一样工作),应该提供更多的信息。 0.0返回写入的字符数; sprintf返回读取的项目数。

sscanf

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

#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;
}

在Cygwin下,我得到了这个输出:

sprintf returned 20, buffer = "0x1.3333333333333p+0"
sscanf returned 1, x = 1.200000

表示sprintf returned 20, buffer = "0x1.3333333333333p+0" sscanf returned 2, x = 0.000000, leftover = "x1.3333333333333p+0" 格式导致"%lf"只使用sscanf,其余字符串将被0使用。这是C90实现的特征(在"%s"添加到标准之前) - 但"%a" printf正常工作。

在您的系统上试试这个。

答案 1 :(得分:0)

sprintf(buffer, "%a", 1.2);
  

实施例1.2缓冲液 - &gt; 0x1.3333333333333p + 0

%a格式将数字读取为十六进制浮点格式。此格式的数字以

的形式表示

0xB.CpN

,其中

  • 0x,前缀
  • B,一个十六进制数字,表示标准化二进制分数的前导1位
  • C,十六进制数字小数部分
  • N,2到N的幂

这样:

0x1.3333333333333p + 0

代表

1.0011001100110011001100110011001100110011001100110011 x 2 ^ 0

此十六进制格式表示最接近十进制数1.2的双精度浮点数。

关于你的例子中的原因

  

示例1.2 scanf&lt; - 0

使用gcc 4.7.2编译,这与4.8.1一样正常。问题出在您链接的运行时库中。