1

所以我有一个文件 data3.txt,它基本上看起来像这样:

#file:data.txt
#data inputs
1 1234 +0.2 23.89 6.21
2 132 -0.03 3.22 0.1
3    32 0.00 31.50   4.76

我想使用 stringtreams 将前 3 列写入一个新文件

#include <cctype>
#include <sstream>
#include <iostream>
#include <fstream>
#include <cstdlib>
#include <string>
using namespace std;
int main(){
  string line;
  float curr_price, change;
  int stock_number;
  ifstream fin("data3.txt");
  istringstream iss;
  ostringstream oss;
  if(!fin){
    cerr<<"Can't open a file";
  }
  ofstream outfile("data2.txt");
  while (getline(fin,line)){
    iss.clear();
    iss.str(line);
    iss>>stock_number>>curr_price>>change;
    while(isspace(iss.peek()))
      iss.ignore();
    while(iss.str() == "#")
      iss.ignore();
    if( iss.str()==""){
      break;
    }
    oss<<stock_number<<"\t"<<curr_price<<"\t"<<change<<"\n";
    outfile<<oss.str();
  }
}

但我的输出文件看起来很糟糕:

0   0   0
0   0   0
0   0   0
0   0   0
0   0   0
1   1234    0.2
0   0   0
0   0   0
1   1234    0.2
2   132 -0.03
0   0   0
0   0   0
1   1234    0.2
2   132 -0.03
3   32  0

我不知道零是从哪里来的,如果我将 ofstream 放在 while 循环之外,那么它只会打印最后一个数据行

4

2 回答 2

2

一个问题是你总是输出数字,即使你得到了评论。此外,窥视和忽略的东西不应该是必要的。要检查数字是否被成功读取,只需在读取后将流评估为布尔值,就像我在此示例中所做的那样:

#include <fstream>
#include <sstream>
using namespace std;

int main(int argc, char ** argv)
{
    ifstream in(argv[1]);
    ofstream out(argv[2]);
    string line;
    while(getline(in,line))
    {
        if(line.empty() || line[0] == '#') continue;
        double number, price, change;
        stringstream ss(line);
        if(ss >> number >> price >> change)
            out << number << "\t" << price << "\t" << change << "\n";
    }
    return 0;
}

顺便说一下,这是一个使用一些 C 函数会使事情变得更简单和更漂亮的例子:

#include <stdlib.h>
#include <stdio.h>
#include <iostream>
using namespace std;

int main(int argc, char ** argv)
{
    string line;
    int number;
    double price, change;
    while(getline(cin,line))
        if(sscanf(line.c_str(), "%d %lf %lf", &number, &price, &change)==3)
            printf("%3d %8.2f %8.2f\n", number, price, change);
    return 0;
}

此示例使用标准输入和输出而不是文件。这些被称为“标准”的原因是:它们非常灵活,可以非常简单地重定向到文件和其他进程/从文件和其他进程中重定向。但是该程序与文件非常相似。

于 2012-10-30T19:36:59.527 回答
1

您需要始终检查您的输入是否成功!此外,您很少需要求助于基于奇怪字符的阅读技巧。例如,有一个操纵器可以跳过前导空格:std::ws. 下面是一个对值的类型没有做太多假设的版本。如果一行的第一个值必须是整数,则可以使用int代替,std::string甚至可以跳过对注释行的检查!您只需检查读取三个值是否成功。

#include <sstream>
#include <fstream>
#include <string>

int main()
{
    std::ifstream      in("input.txt");
    std::ofstream      out("output.txt");
    std::istringstream lin;
    std::string        tmp0, tmp1, tmp2;
    for (std::string line; std::getline(in, line); ) {
        lin.clear();
        lin.str(line);
        if ((lin >> std::ws).peek() != '#'
            && lin >> tmp0 >> tmp1 >> tmp2) {
            out << tmp0 << '\t' << tmp1 << '\t' << tmp2 << '\n';
        }
    }
}
于 2012-10-30T19:49:35.480 回答