【问题标题】:stupid bug with fscanf - comma instead of pointfscanf 的愚蠢错误 - 逗号而不是点
【发布时间】:2012-11-21 09:21:36
【问题描述】:

我的一个项目的 C++ 源代码中有一个愚蠢的错误。我在这部分做源 I/O 操作。我有一个愚蠢的错误,我打印 fscanf 读取值。在这部分下面: 首先,我没有读取好的值,当我打印一个浮点值时,我得到一个带有逗号“,”而不是点“。”的十进制值。在整数部分和浮点部分之间。

FILE* file3;
file3=fopen("test.dat","r");
float test1;
fscanf(file3," %f ",&test1);
printf("here %f\n",test1);
float test3 = 1.2345;
printf("here %f\n",test3);
fclose(file3);        

test.dat 文件包含“1.1234”,我执行:

here 1,000000
here 1,234500

所以,我做了一个用 g++ 编译的简单测试 C 程序:

#include <stdio.h>
#include <stdlib.h>

int main()
{
  FILE* file3;
  float test3;
  file3=fopen("test.dat","r");
  fscanf(file3,"%f",&test3);
  printf("here %f\n",test3);
  fclose(file3);
}

它给出了:

here 1.123400

这是我第一次遇到这样的错误。任何人都可以看到有什么问题吗?

【问题讨论】:

  • 用g++编译的C程序是C++程序。
  • 这取决于区域设置。如果您的程序必须表现出特定的行为(例如使用. 作为小数分隔符),则必须相应地设置语言环境。
  • @nos:不,这很明显。这是语言环境初始化的区别。

标签: c++ c scanf


【解决方案1】:

您的 C++ 语言环境是否以某种方式设置为使用欧洲惯例?他们使用逗号,而我们使用点和点作为千位分隔符。

看看环境变量的设置

朗 LC_CTYPE LC_ALL

尝试设置 en_GB 或 en_US。确定这是一个语言环境问题后,接下来决定什么行为是有意义的。显示 1224,45 是一个错误吗?用户设置了区域设置是有原因的。

【讨论】:

  • 还有一件更重要的事情。它还取决于是否在应用程序中初始化了语言环境。测试应用程序不初始化语言环境,所以它总是使用小数点,较大的应用程序可能会初始化它们。
  • 最终用户会坚持保留他们的语言环境。这必须通过在应用程序中正确启用/禁用区域设置来解决。
  • 谢谢:“std::setlocale(LC_ALL, "En_US");"在 main.cpp 中编辑它!
  • @user1773603 并且可能破坏了其他一切。任何用 C++ 编写的控制台应用程序的(几乎)第一行应该是std::locale::global( std::locale( "" ) );;在 C 中,这将是 setlocale( LC_ALL, "" );
【解决方案2】:

您正在使用为程序环境设置区域设置的代码。在某些语言环境中,例如在法语语言环境中,逗号是小数点分隔符。所以这段代码正在做它的语言环境可能告诉它的事情。

在您的简单代码中,您尚未初始化语言环境支持,因此不会发生这种情况。

假设是类Unix环境,环境变量LANG的值是多少,以及各种LC_*环境变量?

环境 | grep -e ^LANG -e ^LC_

对于一些背景阅读,尝试一些 GNU Libc 手册(语言环境和国际化)

http://www.gnu.org/software/libc/manual/html_node/Locales.html#Locales

【讨论】:

    【解决方案3】:

    我的猜测是应用程序正在将语言环境设置为 用户偏好,std::locale::global( std::locale( "" ) )。控制台应用程序应该做什么 做,永远;他们还应该灌输std::cinstd::coutstd::cerr 使用此语言环境。大多数语言社区使用 小数点的逗号,而不是点。 (对于恶魔 进程,通常更适合使用 "C" 语言环境, 或 Unix 下的 "Posix" 语言环境,无论在哪里 服务器实际上正在运行。由于 "C" 语言环境是 默认情况下,什么都不做通常对恶魔和 服务器。)

    全局语言环境影响所有 C 风格的输入和输出,这 是使用 C++ 的 iostream 的另一个原因。和 std::ifstream,只需将流中的语言环境注入其中 该文件是在进行第一次输入之前编写的。为了 机器生成的文件,"C" 语言环境是通常的默认值, 所以你的代码会变成这样:

    std::ifstream file3( "test.dat" );
    if ( ! file3.is_open() ) {
        //  error handling...
    }
    file3.imbue( std::locale( "C" ) );
    float test1;
    file3 >> test1;
    //  ...
    

    对于终端的输出,期望语言环境约定是 跟着。并设置环境变量指定 您想查看的语言环境。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-05-26
      • 2015-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-12-06
      • 1970-01-01
      相关资源
      最近更新 更多