【问题标题】:formatted output: columns格式化输出:列
【发布时间】:2012-05-09 09:58:26
【问题描述】:

我正在拼命尝试使用 fstream: columns 生成格式化输出。

有两个函数(无论函数 Func1、Func2)产生输出(写入同一个文件,“example.dat”):

#include <fstream>

int main()
{
    std::ofstream fout;    
    fout.open("example.dat");

    for (int i=0; i<10; i++)
    {
        fout << Func1(i) << std::endl;
    };

    // Func2 depends on Func1, thus them **cannot** be written at the same time: 
    // fout << Func1() << " " << Func2() << std::endl;

    for (int i=0; i<10; i++)
    {
        fout << Func2(i) << std::endl;
    };

    return 0;
}

输出将类似于:

Func1(0)

Func1(1)

.

。 .

Func1(9)

Func2(0)

Func2(1)

.

.

.

Func2(9)

我的问题是:如何将此输出生成为两列:

Func1(0) Func2(0)

Func1(1) Func2(1)

.

.

.

虽然它们不是同时写入的。

我怀疑我需要使用 seekp(),​​tellp(),但不幸的是我不是这方面的大专家。

请帮忙!

提前谢谢你。

【问题讨论】:

  • 你不能把 Func1 和 Func2 的输出缓冲到 2 vector&lt;string&gt; 中,这样你就可以输出列在一个循环中的结果了吗?
  • 您应该编辑您的问题以从标题中删除 (C++)。如果你有 c++ 标签,你不需要把它放进去。
  • Func1Func2 返回值的类型是什么?它们打印为固定大小的字符串吗?
  • @Nicolas Repiquet:双类型函数
  • Func1 是否存储了一些数据,Func2 会使用它吗?在调用所有Func1s 之前不能调用Func2?以后能找回Func1的所有结果吗?

标签: c++ fstream formatted


【解决方案1】:
vector<ostringstream> streams(10);

for (int i=0; i < 10; ++i)
{
    streams[i] << Func1(i);
}

for (int i=0; i < 10; ++i)
{
    streams[i] << " " << Func2(i);
}

ofstream fout("example.dat");

for (int i=0; i < 10; ++i)
{
    fout << streams[i].str() << endl;
}

【讨论】:

  • 不错的解决方案!但是,它是否能够在向量中存储高达 600 MB 的空间?
  • 我有 100 个“for”循环,每个循环产生约 6-7MB 的 .dat 文件。因此,为了使用您的解决方案,我必须存储 100X(6-7MB) 的信息。“矢量”是否可能?
  • 你的意思是你有 100 列?也许中间文件是要走的路。
【解决方案2】:

你为什么需要 seekp 和 tellp (而且在任何情况下,对于粗心的人来说,写入文件中间充满了陷阱)

使用 std::vector (语法可能是错误的),因此:

std::vector<std::string> res1;
std::vector<std::string> res2;
res1.reserve(10);
res2.reserve(10);
for (std::size_t i = 0; i < 10; ++i)
{
    std::stringstream s;
    s << func1(i);
    res1[i] = s.str();
}
//same for res2, func2
for (std::size_t i = 0; i < 10; ++i)
{

    cout << res1[i] << " " << res2[i] << "\n";
}

这可能是错误的格式,需要调整位。 std::list 可能会更好。

【讨论】:

  • 谢谢 Benj 和 Tom Tanner,上面的代码只是我原始代码的原型。实际上,我有大约 100 列,每列长度约为 50^4。将它们全部保存在内存中可能会杀死它。因此我有兴趣将它写入我的 .dat 文件,释放内存并再次运行(下一部分数据)。
【解决方案3】:

假设您确实无法将它们保存在内存中,您可以写入两个文件,回到开头,逐行读取它们并输出到最终文件以创建连接列。

这样的事情可能会起作用(我还没有测试过):

#include <fstream>
#include <string>
int main()
{
    std::fstream  fs_func1;
    std::fstream  fs_func2;
    std::ofstream fout;

    fs_func1.open("func1.dat")
    for (int i=0;i<10;i++)
    {
        fs_func1 << Func1(i) << std::endl;
    }
    fs_func1.seekg(0); // Set get pointer to start of file

    fs_func2.open("func2.dat");
    for (int i=0;i<10;i++)
    {
        fs_func2 << Func2(i) << std::endl;
    };
    fs_func2.seekg(0); // Set get pointer to start of file

    fout.open("example.dat");
    while (!fs_func1.eof() && !fs_func2.eof())
    {
        std::string func1_line;
        std::string func2_line;

        std::getline(fs_func1, func1_line);
        std::getline(fs_func2, func2_line);

        fout << func1_line << " " << func2_line << std::endl;
    }

    return 0;
}

可能有一个 Unix 命令行工具可以一步完成。

【讨论】:

  • 感谢铁人!但在我的情况下,连接的列应该逐渐出现。由于我处理大量数据文件,因此读取和写入将非常耗时。因此,我需要保留(打开?)主文件“example.dat”并在每次运行后添加一个新列。您提供了一个非常好的解决方案,但是如何更改为增量解决方案?
  • @Pomeron:我认为你不能轻易将我的代码更改为增量代码,除非你可以将 for 循环分成更小的部分,例如为 0...9 调用 Func1() 然后为 0...9 调用 Func2() 然后为 10...19 调用 Func1() 等等。好吧,你可以改变它,但它会完全不同。
【解决方案4】:

未经测试,但想法是将您的文件视为网格。

const int COLUMN_COUNT = 2;
const int COLUMN_WIDTH = 8;
const int ROW_WIDTH = COLUMN_COUNT * COLUMN_WIDTH + 1; // + 1 is for endl

void write_cell(std::ostream& out, int row, int column, double value) {

  // how many rows is there in the file ?
  out.seekp(0, std::ios_base::end);
  int row_count = out.tellp() / ROW_WIDTH;

  // Do we need to create more rows ?
  for(int i = row_count; i <= row; i++) {
    out.seekp(ROW_WIDTH - 1, std::ios_base::cur);
    out << endl;
  }

  // compute cell position
  int pos = row * ROW_WIDTH + column * COLUMN_WIDTH;

  // move to cell position
  out.seekp(pos);

  // write the cell content
  out << std::setw(COLUMN_WIDTH) << value;
}

int main()
{
  std::ofstream fout;    
  fout.open("example.dat");

  for (int i=0; i<10; i++)
  {
    write_cell(fout, i, 0, Func1(i));
  };

  for (int i=0; i<10; i++)
  {
    write_cell(fout, i, 1, Func2(i));
  };

  return 0;
}

【讨论】:

    【解决方案5】:
    for (int i=0;i<10;i++)  
    {  
        fout << Func1(i);  
    };  
    fout<<endl;  
    
    for (int i=0;i<10;i++)  
    {  
        fout << Func2(i);  
    };  
    fout<<endl;  
    

    【讨论】:

    • 我不是反对者,但这会产生两行而不是两列的输出。如果您更改答案以显示如何将其转换为两列,那可能是一个很好的答案。
    猜你喜欢
    • 1970-01-01
    • 2016-12-19
    • 1970-01-01
    • 1970-01-01
    • 2012-10-30
    • 2011-08-21
    • 2018-07-19
    • 2021-04-11
    相关资源
    最近更新 更多