【问题标题】:How do i read a float value when this value have comma instead of dot?当这个值有逗号而不是点时,我如何读取浮点值?
【发布时间】:2013-11-15 18:15:29
【问题描述】:

我有一个 CSV 文件,其中的值用逗号分隔,如下所示:

224,321,345,56.6
225,322,245,46.7
etc,etc,etc.....

所有值都必须被视为浮点数。

问题是当我尝试将值读取为浮点数时:

fscanf(file,%f,&value);

如果我打印结果

printf("The first value is: %f",value) 

我明白了:

The first value is 224,321

当这个值有逗号而不是点时,我如何读取浮点值?

【问题讨论】:

    标签: c++ c csv scanf


    【解决方案1】:

    C 解决方案

    OP 的 scanf() 显然使用了 decimal_point"," 的浮点数。不幸的是,数据使用了decimal_point"."

    C 解决方案有 4 个步骤:1) 确定当前语言环境 2) 更改语言环境 3) 调用 sscanf() 4) 恢复语言环境。

    #include <locale.h>
    
    // Maybe CurrentLocaleName = "" will work.
    // That's the locale-specific native environment.
    // Otherwise the value may be available in preceding code.
    const char *CurrentLocaleName = TBD();  
    
    // In the "C" locale, a decimal_point is ".".
    if (NULL == setlocale(LC_NUMERIC, "C")) {
      handle_local_change_error();
    }
    
    if (first_in_line) {
      if (1 != fscanf(file, "%f", &value)) {
        handle_scan_error();
      }
    }
    else {
      if (1 != fscanf(file, " ,%f", &value)) {
        handle_scan_error();
      }
    }
    
    if (NULL == setlocale(LC_NUMERIC, CurrentLocaleName)) {
      handle_local_change_error();
    }
    

    【讨论】:

      【解决方案2】:

      简单的回答:格式不明确。以太引用值或通过选择不同的分隔符(可能是分号)来消除歧义

      另一个答案(如果浮点值没有逗号):切换到“C”语言环境。

      【讨论】:

        【解决方案3】:

        我对编码有点陌生,但是您不能简单地先删除逗号然后再阅读吗?只需使用贯穿该行并消除所有逗号的函数。这对我来说似乎是最简单的解决方案。

        【讨论】:

          【解决方案4】:

          CVS 格式包含一堆用逗号分隔的数据。因此,当您尝试解析 cvs 文件时,您必须将逗号符号作为您的格式参数的一部分放在 scanf 函数中。我相信下面的代码会有所帮助。

          #include <stdlib.h>
          #include <stdio.h>
          #include <iostream>
          
          using namespace std;
          
          int main(int argc, char * argv[]) {
              if(argc <= 1) {
                  printf("No file specified!\n");
                  exit(0);
              }
              char * filename = argv[1];
              FILE *file = fopen(filename,"rb");
              if(0 != file) {
                  float value = 0;
                  while(!feof(file)) {
                      fscanf(file, "%f,", &value);
                      printf("%f ",value);
                  }
                  printf("\n");
              }
              fclose(file);
              return 0;
          }
          

          【讨论】:

          • 是的,我尝试了这个程序的一些测试用例,发现如果数据文件最后有一些空行会导致问题。但我相信这可以通过严格的 cvs 格式或在解析之前进行一些修剪过程来解决。
          【解决方案5】:

          您的帖子有点模棱两可。 你说在你的文件中你有用逗号分隔的值,然后你说你想读取一个带有逗号而不是点的浮点值。

          无论如何,默认行为是将逗号作为分隔符,因此 123,324 读作 123.00。但是,在接下来的阅读中,您将获得相同的值。所以,你可能想这样写:

          fscanf(file,"%f, ",&value);
          

          如果您想使用逗号而不是点作为分隔符(尽管我看到您有一些使用点的值),那么您需要在文件中使用另一个分隔符(例如空格)来分隔 2 个连续值。您指定的文件不能这样使用。

          【讨论】:

          • 谢谢,也许我没有清楚地解释自己。我说在我拥有的文件中,浮点值就像,例如,“34.56”,而不是“34,56”。此外,文件中的所有值都用逗号分隔。所以文件的第一行可能是这样的:34.67,56.000,-89.08479....等
          • 那么它应该可以工作。浮点数默认使用点,而不是逗号。另外,我在代码中进行了编辑以忽略分隔逗号。
          • 没有男人不是那样的。如果你 fscanf 一个像 56.6 这样的值,你会得到 56,000000
          • 使用scanf,而不是fscanf。也许当控制台读取数据时会有所不同。
          • 现在它使用 fscanf:ideone.com/crI7HQ。请注意,stdin 就像任何其他文件一样。实际上,它有 FILE* 类型。
          【解决方案6】:

          逗号是否被视为小数分隔符 取决于语言环境。您已经为 C 和 C++ 标记了这个; 在这种情况下,解决方案是不同的。

          在 C++ 中,忘记 fscanf 并使用 std::istream。然后 用std::locale("C") 为您的信息流灌输。

          在 C 中,这要困难得多,因为您必须更改全局 语言环境。几乎可以肯定地恢复它。如果你是 多线程,在关键部分这样做,受保护 其他任何可能想要修改语言环境的人。

          【讨论】:

            【解决方案7】:

            一种方法是将其读取为整数,然后转换为浮点数。

            另一种是逐行读取,以逗号分隔,并将每个数字一一转换为浮点值。

            这两个解决方案都有非常好的和非常简单的 C++ 实现。用 C 做更多的工作。

            【讨论】:

            • 您的第一个解决方案不会导致精度损失吗?
            猜你喜欢
            • 2015-07-20
            • 1970-01-01
            • 1970-01-01
            • 2012-05-17
            • 1970-01-01
            • 1970-01-01
            • 2012-02-27
            • 2014-09-17
            • 1970-01-01
            相关资源
            最近更新 更多