如何从ASCII文件中读取数字(C++)

and*_*s-h 18 c++ io iostream input

我需要读入如下所示的数据文件:

* SZA: 10.00
 2.648  2.648  2.648  2.648  2.648  2.648  2.648  2.649  2.650  2.650
 2.652  2.653  2.652  2.653  2.654  2.654  2.654  2.654  2.654  2.654
 2.654  2.654  2.654  2.655  2.656  2.656  2.657  2.657  2.657  2.656
 2.656  2.655  2.655  2.653  2.653  2.653  2.654  2.658  2.669  2.669
 2.667  2.666  2.666  2.664  2.663  2.663  2.663  2.662  2.663  2.663
 2.663  2.663  2.663  2.663  2.662  2.660  2.656  2.657  2.657  2.657
 2.654  2.653  2.652  2.651  2.648  2.647  2.646  2.642  2.641  2.637
 2.636  2.636  2.634  2.635  2.635  2.635  2.635  2.634  2.633  2.633
 2.633  2.634  2.634  2.635  2.637  2.638  2.637  2.639  2.640  2.640
 2.639  2.640  2.640  2.639  2.639  2.638  2.640  2.640  2.638  2.639
 2.638  2.638  2.638  2.638  2.637  2.637  2.637  2.634  2.635  2.636
 2.637  2.639  2.641  2.641  2.643  2.643  2.643  2.642  2.643  2.642
 2.641  2.642  2.642  2.643  2.645  2.645  2.645  2.645
Run Code Online (Sandbox Code Playgroud)

将此文件读入浮点数组的最优雅方法是什么?

我知道如何将每一行读入一个字符串,我知道如何将字符串转换为浮点数atof().但我如何做最简单的休息呢?

我听说过字符串缓冲区,这对我有帮助吗?

小智 18

字符串工具包库(Strtk)具有以下问题的解决方案:

#include <iostream>
#include <string>
#include <deque>
#include <iterator>

#include "strtk.hpp"

int main()
{
    std::deque<float> flist;
    strtk::for_each_line("file.txt",
                         [&flist](const std::string& line)
                         { strtk::parse(line," ",flist); }
                         );
    std::copy(flist.begin(),flist.end(),
              std::ostream_iterator<float>(std::cout,"\t"));
    return 0;
}
Run Code Online (Sandbox Code Playgroud)

更多示例可以在C++ String Toolkit(StrTk)Tokenizer中找到.

  • 非常正确,但lambda可以很容易地放入struct style谓词中.我想到风格和未来的参考(让我们面对它,从现在起1 - 2年,上面的代码和类似的将是常态),对于如何完成事情有不同的看法是个好主意. (18认同)
  • 我喜欢这个.很好用的新lambdas,即使这不是答案. (12认同)

sbi*_*sbi 11

由于这被标记为C++,最明显的方式是使用流.在我的头顶,这样的事情可能会做:

std::vector<float> readFile(std::istream& is)
{
  char chdummy;
  is >> std::ws >> chdummy >> std::ws; 
  if(!is || chdummy != '*') error();
  std::string strdummy;
  std::getline(is,strdummy,':');
  if(!is || strdummy != "SZA") error();

  std::vector<float> result;
  for(;;)
  {
    float number;
    if( !is>>number ) break;
    result.push_back(number);
  }
  if( !is.eof() ) error();

  return result;
}
Run Code Online (Sandbox Code Playgroud)

为什么float,BTW?通常double情况要好得多.

编辑,因为有人质疑是否返回副本vector是一个好主意:

对于第一个解决方案,我肯定会做到这一点.该函数正在将文件读入a vector,而函数最明显的事情就是返回其结果.这是否会导致明显的减速取决于很多事情(向量的大小,函数调用的频率以及从哪里读取的磁盘速度,编译器是否可以应用RVO).我不想通过优化破坏显而易见的解决方案,但如果分析确实表明这是慢的,则应该按照非const引用传递向量.

(另请注意,带有右值支持的C++ 1x,希望很快就可以通过你附近的编译器获得,这将使得这个讨论没有实际意义,因为它会阻止向量从函数返回时复制向量.)