1

I have a research project I'm working on. I am a beginner in C++ and programming in general. 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.

I want to visualize my findings, to know if my particles are moving as they should. My professor said that I must use 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:

a) For each time-step generate one file with XY coordinates of the form "output_#.dat".

b) Generate a .png file for each one of them in gnuplot.

c) Make a movie of the moving particles with all the .png files.

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:

    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.

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. 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...

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.

2) Open that file.

3) Write the coordinates for that time-step.

4) Close the file.

5) Repeat.

Any help will be greatly appreciated. Thank you for your time!

wjl
  • 7,519
  • 2
  • 32
  • 41
Dima1982
  • 189
  • 3
  • 18
  • 5
    so you written a code which "generates interacting particles that move on continuous space as time progresses", and still don't know how to use loops?? –  Nov 16 '12 at 17:15
  • Dear _aleguna_, I know how to use loops (I guess), but I'm learning as I go and I'm self-taught. If you can look back to when you begun programming, you may understand my predicament, as I'm doing this without any help whatsoever. Of course, countless others have done so as well, but asking questions is the only way to learn. _wjl_ was kind enough to provide code in his answer, but even if he had pointed me to c_str() and to creating a new method, I would be just as happy. Thanks for understanding. – Dima1982 Nov 16 '12 at 17:56
  • 1
    +1 because, even though it's not the best asked question, it's a valid question and didn't deserve so many down-votes. – wjl Nov 16 '12 at 17:56

1 Answers1

2

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.

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.

wjl
  • 7,519
  • 2
  • 32
  • 41
  • Thank you so much for your quick reply. I am reading Absolute C++ by Savitch and searching the internet as I go, but my progress is slow. I don't know what I did wrong to get voted down twice. What you answered is something that I feel I could not have found by myself. Thanks again for your time and energy! – Dima1982 Nov 16 '12 at 17:42
  • 1
    @Dima1982 to avoid being down-voted in the future, I'd just suggest to try to make your questions as clear as possible up front, so readers don't have to read through the entire post to figure out what you are really asking. For example, your question wasn't *really* about your algorithm or looping, but it took some effort to see what your real problem was (string building with an integer). I didn't mind in this case, but in general poorly-asked questions can raise the ire of the community a little bit. =) – wjl Nov 16 '12 at 18:03
  • Thank you very much for your support. I really appreciate it. I will keep that in mind in the future. – Dima1982 Nov 16 '12 at 18:07