【问题标题】:C++: how to output data to multiple .dat files?C++:如何将数据输出到多个 .dat 文件?
【发布时间】:2012-11-16 17:03:40
【问题描述】:

我正在从事一个研究项目。我是 C++ 和一般编程的初学者。我已经编写了一个程序,可以生成随着时间的推移在连续空间上移动的相互作用粒子。我的程序唯一输出的是每个时间步中每个粒子的 XY 坐标。

我想将我的发现可视化,以了解我的粒子是否按照应有的方式移动。我的教授说我必须使用gnuplot。由于找不到将数据输出到一个文件中以便gnuplot 识别的方法,因此我想到了以下策略:

a) 为每个时间步生成一个 XY 坐标格式为“output_#.dat”的文件。

b) 为gnuplot 中的每一个生成一个.png 文件。

c) 使用所有 .png 文件制作移动粒子的电影。

我稍后会担心 b 和 c,但到目前为止,我可以使用以下代码将我的所有数据输出到一个文件中:

    void main()
{
    int i = 0;
    int t = 0; // time
    int j = 0; 
    int ctr = 0;
    double sumX = 0;
    double sumY = 0;
    srand(time(NULL)); // give system time as seed to random generator


    Cell* particles[maxSize]; // create array of pointers of type Cell.

    for(i=0; i<maxSize; i++) 
    {
        particles[i] = new Cell(); // initialize in memory
        particles[i]->InitPos(); // give initial positions
    }

    FILE *newFile = fopen("output_00.dat","w"); // print initial positions
    for(i=0; i<maxSize; i++)
    {
        fprintf(newFile, "%f %3 ", particles[i]->getCurrX());
        fprintf(newFile, "%f %3 \n", particles[i]->getCurrY());
    }
    fclose(newFile);

    FILE *output = fopen("output_01.dat","w");
    for(t = 0; t < tMax; t++)
    {
        fprintf(output, "%d ", t);
        for(i=0; i<maxSize; i++) // for every cell
        {
            sumX = 0;
            sumY = 0;
            for(j=0; j<maxSize; j++) // for all surrounding cells
            {
                sumX += particles[i]->ForceX(particles[i], particles[j]);
                sumY += particles[i]->ForceY(particles[i], particles[j]);
            }
            particles[i]->setVelX(particles[i]->getPrevVelX() + (sumX)*dt); // update speed
            particles[i]->setVelY(particles[i]->getPrevVelY() + (sumY)*dt);
            particles[i]->setCurrX(particles[i]->getPrevX() + (particles[i]->getVelX())*dt); // update position
            particles[i]->setCurrY(particles[i]->getPrevY() + (particles[i]->getVelY())*dt);

            fprintf(output, " ");
            fprintf(output, "%f %3 ", particles[i]->getCurrX());
            fprintf(output, "%f %3 \n", particles[i]->getCurrY());
        }
    }
    fclose(output);
}

这确实生成了 2 个文件,output_00.datoutput01.dat,第一个包含初始随机生成的位置,第二个包含我的所有结果。

我可以感觉到在嵌套的for循环中,我正在更新XY坐标的速度和位置,我可以有一个FILE*,它将存储每个时间步的坐标然后关闭它,在增加时间之前。这样,我将不需要同时打开多个指针。至少这是我的直觉。

我不知道如何生成递增的文件名。我偶然发现了ofstream,但我不明白它是如何工作的......

我想我现在希望我的程序做的是:

1) 使用基本名称和当前循环计数器值生成新文件名。

2) 打开该文件。

3) 写出该时间步的坐标。

4) 关闭文件。

5) 重复。

任何帮助将不胜感激。感谢您的宝贵时间!

【问题讨论】:

  • 所以你写了一段代码,“生成随着时间的推移在连续空间上移动的相互作用粒子”,但仍然不知道如何使用循环??
  • 亲爱的 aleguna,我知道如何使用循环(我猜),但我边走边学,而且是自学成才。如果你能回顾一下你开始编程的时候,你可能会理解我的困境,因为我在没有任何帮助的情况下这样做。当然,无数其他人也这样做了,但提问是学习的唯一途径。 wjl 很友好地在他的回答中提供了代码,但即使他向我指出 c_str() 并创建一个新方法,我也会很高兴。感谢理解。
  • +1,因为尽管这不是最好的问题,但它是一个有效的问题,不值得这么多反对。

标签: c++ c gnuplot string-building


【解决方案1】:

使用 ofstream 代替 fopen 会更好地使用 C++ 标准库,而现在您正在使用 C 标准库调用,但您现在所做的事情本身并没有错误 .

您真正的核心问题似乎是如何从整数生成文件名,以便您可以在循环中使用它:

这是一种方法:

// Include these somewhere
#include <string>
#include <sstream>

// Define this function
std::string make_output_filename(size_t index) {
   std::ostringstream ss;
   ss << "output_" << index << ".dat";
   return ss.str();
}

// Use that function with fopen in this way:
for (size_t output_file_number=0; /* rest of your for loop stuff */)  {
  FILE *file = fopen(make_output_filename(output_file_number).c_str(), "w");
  /* use the file */
  fclose(file);
}

这使用 std::ostringstream" 使用流操作构建文件名,并返回构建的 std::string。当你将它传递给 fopen 时,你必须给它一个 const char * 而不是 std::字符串,因此我们使用 .c_str() 成员,该成员仅用于此目的。

【讨论】:

  • 非常感谢您的快速回复。我正在阅读 Savitch 的 Absolute C++ 并边走边搜索互联网,但我的进度很慢。我不知道我做错了什么导致两次被否决。你回答的是我觉得我自己无法找到的东西。再次感谢您的时间和精力!
  • @Dima1982 为避免将来被否决,我只是建议尽量让你的问题尽可能清楚,这样读者就不必通读整篇文章弄清楚你真正在问什么。例如,您的问题不是真的关于您的算法或循环,但需要一些努力才能了解您的真正问题是什么(使用整数构建字符串)。在这种情况下我不介意,但总的来说,问得不好的问题可能会引起社区的一点愤怒。 =)
  • 非常感谢您的支持。对此,我真的非常感激。以后我会牢记这一点。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2018-03-22
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-09-26
  • 1970-01-01
  • 2016-10-04
相关资源
最近更新 更多