У меня есть исследовательский проект, над которым я работаю. Я новичок в 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 generatorCell* 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) Повторите.
Любая помощь будет оценена. Спасибо за ваше время!
Использование 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 (), который существует только для этой цели.
Других решений пока нет …