【问题标题】:Stop reading at format mismatch在格式不匹配时停止阅读
【发布时间】:2011-03-31 12:07:23
【问题描述】:

我有一个文件,例如:

 1.0000000e+01   8.0123000e+01   1.0000000e+01   1.0000000e+01   1.0000000e+01
-1.0000000e+01   1.0000000e+01   1.0001110e+01   1.0000000e+01   1.0000000e+01
 1.0000000e+01   1.0000000e+01  -5.0000000e+01   1.0000000e+01   1.0000000e+01
 //... (repeated scientific numbers)
 1 2 3 4
 2 4 5 60
 100 3 5 63
 //... (repeated integer numbers)

我想从 C++ 文件中读取这些数字,但只有科学格式的数字,所以我需要在数字格式更改时停止代码。我还有一个优点是浮点数有 5 列,而整数有 4 列。

那么,在 C++ 中最好的方法是什么?

【问题讨论】:

    标签: c++ io formatted-input


    【解决方案1】:

    忽略 EOL(继续读取整数):

    typedef double d[5] Datum;
    Datum d;
    vector<Datum> data;
    while (true) {
      Datum t;
      istr >> t[0] >> t[1] >> t[2] >> t[3] >> t[4];
      if (!istr) break;
      data.push_back(t);
    }
    

    使用列数和 EOL:

    while (istr) {
      string line;
      getline(istr, line);
      Datum t;
      istringstream temp(line);
      temp >> t[0] >> t[1] >> t[2] >> t[3] >> t[4];
      if (temp.fail()) break;
      data.push_back(t);
    }
    

    【讨论】:

    • Lines typedef double d[5] Datum; Datum d; 给我编译错误,所以我无法测试。无论如何,我明白了,而且看起来很完美。
    • 以下命令temp &gt;&gt; t[0] &gt;&gt; t[1] &gt;&gt; t[2] &gt;&gt; t[3] &gt;&gt; t[4]; 无法正确读取浮点数。应该格式化吗?
    • 不是浮点数,是科学格式的数字!我猜它不适用于科学格式。
    • 这很奇怪。您是否尝试过将“e”替换为“E”来解析您的输入?
    • 错误是istringstream temp; 显然应该是istringstream temp(line);。所以,数字格式实际上没有问题。
    【解决方案2】:

    您可以使用 strstr 在每一行中搜索“e+”。

    http://www.cplusplus.com/reference/clibrary/cstring/strstr/

    如果您想更花哨,可以使用正则表达式库(例如 boost::regex),它还可以帮助您从每一行中提取字符串。

    【讨论】:

      【解决方案3】:

      恐怕没有直接的方法可以做到这一点。也就是说,您不能以特定格式输入(&gt;&gt;)浮点数。因此,如果您需要该功能,则必须将这些行作为字符串读取,然后手动解析它们。当然,这并不意味着您必须逐位构建浮点数。一旦确定了要从中读取浮点数的输入文件的边界,请使用stringstreams 来读取它们。

      【讨论】:

      • 那为什么不使用列数呢?
      【解决方案4】:

      您可以使用正则表达式仅匹配您关心的内容:-?\d+\.\d+e[+-]\d+

      我确信这不是最好的方法,但如果性能不是一个大问题,那么它是一个简单的方法

      警告:RegexBuddy 自动生成的代码

      pcre *myregexp;
      const char *error;
      int erroroffset;
      int offsetcount;
      int offsets[(0+1)*3]; // (max_capturing_groups+1)*3
      myregexp = pcre_compile("-?\\d+\\.\\d+e[+-]\\d+", 0, &error, &erroroffset, NULL);
      if (myregexp != NULL) {
          offsetcount = pcre_exec(myregexp, NULL, subject, strlen(subject), 0, 0, offsets, (0+1)*3);
          while (offsetcount > 0) {
              // match offset = offsets[0];
              // match length = offsets[1] - offsets[0];
              if (pcre_get_substring(subject, &offsets, offsetcount, 0, &result) >= 0) {
                  // Do something with match we just stored into result
              }
              offsetcount = pcre_exec(myregexp, NULL, subject, strlen(subject), 0, offsets[1], offsets, (0+1)*3);
          } 
      } else {
          // Syntax error in the regular expression at erroroffset
      }
      

      【讨论】:

      • 在字段中分割行要有效和简单得多。此外,使用正则表达式测试数字有点过头了,毕竟只有 10 个(你可以用 string::find_first_of() 找到它们中的任何一个)
      • 如何在字段中进行分隔?
      【解决方案5】:

      regex 是最好的方法,您也可以尝试使用 fscanf()

      【讨论】:

        猜你喜欢
        • 2010-12-10
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2016-10-01
        • 2022-12-03
        相关资源
        最近更新 更多