C++: как вывести данные в несколько файлов.dat?

У меня есть исследовательский проект, над которым я работаю. Я новичок в C++ и программировании в целом. Я уже создал программу, которая генерирует взаимодействующие частицы, которые движутся в непрерывном пространстве с течением времени. Единственное, что выводит моя программа, это координаты XY для каждой частицы на каждом временном шаге.

Я хочу визуализировать свои выводы, чтобы знать, движутся ли мои частицы так, как они должны. Мой профессор сказал, что я должен использовать gnuplot, Так как я не мог найти способ вывести свои данные в один файл, чтобы gnuplot узнав это, я подумал о следующей стратегии:

а) Для каждого временного шага генерируем один файл с координатами XY видаoutput_#.dat".

б) создать .png файл для каждого из них в gnuplot,

в) сделать фильм движущихся частиц со всеми .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.dat а также output01.dat первый содержит начальные случайно сгенерированные позиции, а второй содержит все мои результаты.

Я чувствую, что во вложенном for цикл, где я обновляю скорость и положение для координат XY, я могу иметь FILE* это будет хранить координаты для каждого временного шага и затем закрывать его, прежде чем увеличивать время. Таким образом, мне не нужно будет открывать несколько указателей одновременно. По крайней мере, это моя интуиция.

Я не знаю, как генерировать увеличивающиеся имена файлов. Я наткнулся на ofstream, но я не понимаю, как это работает...

Я думаю, что я хотел бы, чтобы моя программа сделала на этом этапе:

1) Создать новое имя файла, используя базовое имя и текущее значение счетчика цикла.

2) Откройте этот файл.

3) Запишите координаты для этого временного шага.

4) Закройте файл.

5) Повторите.

Любая помощь будет оценена. Спасибо за ваше время!

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:: string, поэтому мы используем член.c_str(), который существует только для этой цели.

Другие вопросы по тегам