[英]C++: how to output data to multiple .dat files?
I have a research project I'm working on.我正在做一个研究项目。 I am a beginner in C++ and programming in general.
我是 C++ 和一般编程的初学者。 I have already made a program that generates interacting particles that move on continuous space as time progresses.
我已经制作了一个程序,可以生成随着时间的推移在连续空间上移动的相互作用粒子。 The only things my program outputs are the XY coordinates for each particle in each time-step.
我的程序输出的唯一内容是每个时间步中每个粒子的 XY 坐标。
I want to visualize my findings, to know if my particles are moving as they should.我想将我的发现可视化,以了解我的粒子是否按应有的方式移动。 My professor said that I must use
gnuplot
.我的教授说我必须使用
gnuplot
。 Since I could not find a way to output my data in one file so that gnuplot
would recognize it, I thought of the following strategy:由于我找不到一种方法将我的数据输出到一个文件中以便
gnuplot
能够识别它,因此我想到了以下策略:
a) For each time-step generate one file with XY coordinates of the form " output_#.dat
". a) 对于每个时间步,生成一个格式为“
output_#.dat
”的 XY 坐标文件。
b) Generate a .png
file for each one of them in gnuplot
. b) 为
gnuplot
每一个生成一个.png
文件。
c) Make a movie of the moving particles with all the .png
files. c) 使用所有
.png
文件制作移动粒子的电影。
I am going to worry about b and c later, but up to now, I am able to output all my data in one file using this code:我稍后会担心 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);
}
This indeed generates 2 files, output_00.dat
and output01.dat
with the first one containing the initial randomly generated positions and the second one containing all my results.这确实生成了 2 个文件
output_00.dat
和output01.dat
,第一个包含初始随机生成的位置,第二个包含我的所有结果。
I can feel that in the nested for
loop, where I'm updating the speed and position for the XY coordinates, I can have a FILE*
that will store the coordinates for each time step and then close it, before incrementing time.我可以感觉到,在嵌套的
for
循环中,我正在更新 XY 坐标的速度和位置,我可以有一个FILE*
来存储每个时间步的坐标,然后在增加时间之前关闭它。 In that way, I will not need multiple pointers to be open at the same time.这样,我就不需要同时打开多个指针。 At least that is my intuition.
至少这是我的直觉。
I do not know how to generate incrementing filenames.我不知道如何生成递增的文件名。 I have stumbled upon
ofstream
, but I don't understand how it works...我偶然发现了
ofstream
,但我不明白它是如何工作的......
I think what I would like my program to do at this point is:我认为此时我希望我的程序做的是:
1) Generate a new file name, using a base name and the current loop counter value. 1) 使用基本名称和当前循环计数器值生成新文件名。
2) Open that file. 2)打开那个文件。
3) Write the coordinates for that time-step. 3) 写出该时间步长的坐标。
4) Close the file. 4) 关闭文件。
5) Repeat. 5) 重复。
Any help will be greatly appreciated.任何帮助将不胜感激。 Thank you for your time!
感谢您的时间!
Using ofstream instead of fopen would be a better use of the C++ standard library, whereas now you are using C standard library calls, but there is nothing wrong per se with what you are doing doing now.使用 ofstream 而不是 fopen 会更好地使用 C++ 标准库,而现在您使用的是 C 标准库调用,但您现在所做的事情本身并没有错。
It seems like your real core question is how to generate a filename from an integer so you can use it in a loop:看起来您真正的核心问题是如何从整数生成文件名,以便您可以在循环中使用它:
Here is one way:这是一种方法:
// 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);
}
This uses a std::ostringstream" to build a filename using stream operations, and returns the built std::string. When you pass it to fopen, you have to give it a const char * rather than a std::string, so we use the .c_str() member which exists just for this purpose.这使用 std::ostringstream" 使用流操作构建文件名,并返回构建的 std::string。当你将它传递给 fopen 时,你必须给它一个 const char * 而不是 std::string,所以我们使用仅用于此目的的 .c_str() 成员。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.