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(), который существует только для этой цели.