Faster File Operations C++ - c++

So I am making a renderer in c++ and opengl for a class of mine. I am making an animation program for extra credit that will change values in a text file right before my renderer reads them in each frame. My problem is that this section of code isn't writing fast enough
while (clock() < time_end)
{
timeStep = clock() + fps * CLOCKS_PER_SEC;
for(int k=0; k < currOps.size(); k++)
{
// increase/decrease each set once for the current timestep
// a case for each operation
int pos = currAxis[k];
if(currOps[k] == "loc")
{
opsFile[8+pos] = patch::to_string(atof(opsFile[8+pos].c_str()) + locScale[pos-1]*timeAdjust);
//edit this value by loc adjust
}
else if(currOps[k] == "rot")
{
opsFile[4+pos] = patch::to_string(atof(opsFile[4+pos].c_str()) + rotScale[pos-1]*timeAdjust);
//edit this value by rot adjust
}
else if(currOps[k] == "scl")
{
opsFile[pos] = patch::to_string(atof(opsFile[pos].c_str()) + sclScale[pos-1]*timeAdjust);
//edit this value by scl adjust
}
}
currFile.close(); //save file and restart so we don't append multiple times
currFile.open(files[location[0]].c_str(), ofstream::out); // so we can write to the file after closing
for(int j=0; j <opsFile.size(); j++)
{
// update the file
currFile << opsFile.at(j);
currFile << "\n";
}
while(clock() < timeStep)
{
//wait for the next time steps
}
}
Specifically currFile operations at the end. If I take the currFile operations out it will run at the desired fps. FPS is set to .033 so that it does 30 fps. Also it will run fast enough when fps = 0.1. Any optimizations would be great. If need to see any other part of my code let me know and I will upload. The whole thing is around 170 lines.
currOps, files, and opsFile are vectors of strings
sclScale, rotScale, and locScale are vectors of doubles
currAxis is vectors of ints

Here are some general changes which may help:
I would convert the curOps to an enum rather than a string (save you the string comparisons.) Looks like you should pre-process that container and build a sequence of enums (then your code in the loop becomes a switch)
Don't use vector<string> for curOps, simply read the floats from the file and write the floats out - this will save you all those pointless conversions to and from string. If you wanted to take it further, convert the file to binary (if you are allowed by the exercise), and store a simple structure which contains the floats you need and use memory mapped files (you don't need boost for that, it's straight forward just using mmap!)
Before going down the mmap route - try the float read/write from file. For example, let's say that each "row" in your file corresponds to something like the following:
struct transform {
double x, y, z;
};
struct op {
transform scale, rot, loc;
};
Declare a bunch of stream in/out operators for these (for example:
std::ostream& operator<<(std::ostream& os, const transform& tx) {
return os << tx.x << ' ' << tx.y << ' ' << tx.z;
}
std::istream& operator>>(std::istream& is, transform& tx) {
return is >> tx.x >> tx.y >> tx.z;
}
(a similiar set will be required for op)
Now your vector is std::vector<op>, which you can easily stream in and out from your file, for example, to read:
op i;
while(file >> i) { curOps.push_back(i); }
To write:
for (auto o : curOps) file << o << '\n';
If this is still not enough, then mmap (btw - it's possible on windows too: Is there a memory mapping api on windows platform, just like mmap() on linux?)

Try using the functions in stdio.h instead. iostreams are terribly inefficient.
In your case all you will need is fseek() ... fputs(). Avoiding reopening the file each time should actually help quite a lot.

Related

C++ How to handle user input given in contests/problems format

Recently I have been starting to participate in c++ contests but I cannot find the best way to handle user input when given in this format.
E.g. 4 and 3 are the dimensions of the next block of input
4 3
1 2 4 5
1 6 7 4
1 5 0 0
The problem I've been having is that sometimes the automatic testing machine successfully can test its inputs and sometimes no, so far the method I've been using is the next
std::vector<std::vector<char>> vec;
void get_lines(std::string in) {
std::vector<char> line(in.begin(), in.end());
vec.push_back(line);
}
std::cin >> height >> width;//this is in main()
std::cin.ignore();
for (int i = 0; i < height; i++)
{
std::getline(std::cin, input);
get_lines(input);
input = "";
}
But I'm sure it's not the most efficient nor the more stable way to handle this type of input.
How can I handle user input in the above-mentioned format so that the testing machine can easily input its values?
First of all, I am sorry for you that you made the decision to participate in such contests. It will help you to learn on how to solve algorithms, but they usually use an extremely bad programming style.
Anyway. Back to your question. As always. It depends. If you have data that are just separated by white space, you can use nearly always formatted input functions with the extractor operator ´>>´. This operator will ignore (skip) all white space in standard mode, including the "new line" at the end of a line. So, no need to read line by line.
The good point ofthis "contest pages" is that input is always be considered correct. So, you do not need to do input-error checking or data plausibilisation. The will always use some test environment, where they "push" the data in your code via input redirection. In real life, user input is always very error prone and must be checked carefully.
And you see that, although not necessary, they give the dimensions of the matrix, to ease up data input (this would normally not be necessary, because we can find out by ourselves).
So, first read the dimensions.
With that, construct your ´std::vector´
Then use 2 nested range based for loops to read the values
One of many possible examples could look like this:
#include <iostream>
#include <vector>
int main() {
// Define variables that will hold the dimension of the matrix
size_t numberOfRows{}, numberOfColumns{};
// Get user input, the dimension of the matrix
std::cin >> numberOfRows >> numberOfColumns;
// Define our container, including its size
std::vector<std::vector<int>> matrix(numberOfRows, std::vector<int>(numberOfColumns, 0));
// Read values from user input
for (std::vector<int>& row : matrix) for (int& i : row)
std::cin >> i;
// Show output
for (const std::vector<int>& row : matrix) {
for (const int& i : row) std::cout << i << ' ';
std::cout << '\n';
}
}
Also the use of std::istream_iterators in conjunction with range constructors can be used here. But, as said. It depends.
If they have Comma Separated Values, or white space within values, like strings, then you need to use other mechanisms.
You can do it like this:
std::cin >> height >> width;
std::vector<std::vector<int>> vec;
vec.resize(height, vector<int>(width)); // resize
for(int i {0}; i < height; ++i)
{
for(int j {0}; j < width; ++j)
{
std::cin >> vec[i][j];
}
}

How to use ifstream

I have a problem with my program which basically is a simple math program. It does some vector multiplication and vector matrix multiplication and it does work fine until i try to read data from a text. I can compile the program but when i try to execute it, I get the fault:" Dataname.exe does not work".
Here's my code. Do not consider the cins and couts
#include<iostream>
#include<cmath>
#include<vector>
#include"header.hpp"
#include<fstream>
using namespace std;
int main()
{
ifstream einlesen ("Zahlen.dat"); //function "einlesen" opens the file "Zahlen.dat".
if (einlesen) // Message if the file has been opend
cout<<"Daten wurden eingelesen"<<endl;
else {
cout<<"Konnte Daten nicht einlesen"<<endl;
return 99;
}
double a;
int n{0};
while ( einlesen >>a>>a>>a>>a>>a>>a>>a) n++;//Loop copys datas on a
einlesen.clear();//stops the loop after the last data is copied.
einlesen.seekg(0, ios_base::beg);//??
vector<double> vecein(n), vecein1(n),Matrixein(n);
for (a = 0;a<n;a++);//copys datas to a vector further calculations
{
einlesen>>vecein.at(a);
einlesen>>vecein1.at(a);
einlesen>>Matrixein.at(a);
}
double Matrix1[9]; //defining my Matrix and the coordinates of my vectors.
double x,y,z,x_1,x_2,x_3;
vector<double> vec(3);
vector<double> vec1(3);
// Old code where I read the data with `cin`:
/*cout<<"Geben Sie die x Koordinaten ein:"<<endl;
cin>>vec[0];
cin>>vec1[0];
cout<<"Geben Sie die y Koordinaten ein:"<<endl;
cin>>vec[1];
cin>>vec1[1];
cout<<"Geben Sie die z Koordinaten ein:"<<endl;
cin>>vec[2];
cin>>vec1[2];
cout<<"Geben Sie eine Matrix ein"<<endl;
cin>>Matrix1[0]>>Matrix1[1]>>Matrix1[2]>>Matrix1[3]>>Matrix1[4]>>Matrix1[5]>>Matrix1[6]>>Matrix1[7]>>Matrix1[8];
cout<<"Vektor1:<"<<vec[0]<<","<<vec[1]<<","<<vec[2]<<">"<<endl;
cout<<"Vektor2:<"<<vec1[0]<<","<<vec1[1]<<","<<vec1[2]<<">"<<endl;
vector<double> Addition(3);
Addition = Vektoraddition(vec,vec1);
cout<<"Addition:"<<"<"<<Addition[0]<<","<<Addition[1]<<","<<Addition[2]<<">"<<endl;
double Skalarprodukt;
Skalarprodukt = Skalarpr(vec,vec1);
cout<<"Skalarprodukt:"<<Skalarprodukt<<endl;
vector<double> kreuzprodukt(3);
kreuzprodukt = Kreuzprodukt (vec,vec1);
cout<<"Kreuzprodukt:"<<"<"<<kreuzprodukt[0]<<","<<kreuzprodukt[1]<<","<<kreuzprodukt[2]<<">"<<endl;
vector<double> MatrixVektor(3);
MatrixVektor = Matrix_vektor (Matrix1, vec);
cout<<"Matrix*Vektor:"<<"<"<<MatrixVektor[0]<<","<<MatrixVektor[1]<<","<<MatrixVektor[2]<<">"<<endl;*/
ofstream ausgabe ("Ausgabe.dat");//write the data on Ausgabe.dat
for (int i = 0; i < a; i++)
{
ausgabe << "(" << vecein[i] << "," << vecein1[i] << "," << Matrixein[i]<<")" << endl;
}
return 0;
}
it's written in German so I don't wonder about the variable names. My problem is that I don't really understand what I'm doing in the while loop. Zahlen.dat is a file similar to 1 2 3 4 5 6 7... and Ausgabe.dat is an empty file. Actually it does write in Ausgabe.dat because it tells me that the content has changed but when I reload the file it's still empty.
I've tried your advice but it still doesn't work. I did not change the way I read my datas because I wanted to see if it works first.
Here is my error message:
terminate called after throwing an instance of 'std::out_of_range'
what(): vector::_M_range_check: __n (which is 10) >= this->size() (which is 10)
This application has requested the Runtime to terminate it in an unusual way.
Please contact the application's support team for more information.
My code looks like this right now:
int main()
{
ifstream einlesen ("Zahlen.dat");
if (einlesen)
cout<<"Daten wurden eingelesen"<<endl;
else
{
cout<<"Konnte Daten nicht einlesen"<<endl;
return 99;
}
double a;
int n{0};
while ( einlesen >>a>>a>>a>>a>>a>>a>>a) n++;
{
einlesen.clear();
einlesen.seekg(0, ios_base::beg);
vector<double> vecein(n), vecein1(n),Matrixein(n);
int b;// new variable of type int.
for (b = 0;b<n;b++);
{
einlesen>>vecein.at(b);
einlesen>>vecein1.at(b);
einlesen>>Matrixein.at(b);
}
ofstream ausgabe ("Ausgabe.dat");
for (int i = 0; i < b; i++)
{
ausgabe << "(" << vecein[i] << "," << vecein1[i] << "," << Matrixein[i] <<")" << endl;
}
}
return 0;
So I basically only changed the variable of the loop.
Yes the programm did work when I used to get the Data with cin.
I really have no idea why the programm is not working!
There are several things in the first code sample that should be done differently. The program first opens the file, and counts the number of blocks of 7 numbers in the file in variable n. Then the file pointer is reset, three vectors are created with a size of n, and the first n numbers are read into the vector from the file. But: You don't have to know the number of entries in a vector beforehand, so there is no need to read the file twice. Just use vector::push_back to add the numbers.
Second problem: In the loop to read the numbers, a is used as the loop variable, which is a double. The incrementing of a double could result in a one-off error, thus explaining your crash.
I'm also not sure the logic is correct: It seems you expect the file to have several (n) lines of numbers with 7 numbers each, but you then read the first n numbers. Say you have 10 lines, then you read the first line and three numbers of the second line into your vectors, also you might have wanted to read all numbers or maybe the first of each line (or even a 3d structure).
What about the second code sample, where you read from cin? Did that one work? It might help if you explained what you are trying to do, it seems there are vectors in the file, that you want to take the vector product (Kreuzprodukt) of? What is their layout in the file, are they written in lines or columns?
EDIT: The cause for the crash seems to be this line:
for (a = 0;a<n;a++);
{
einlesen>>vecein.at(a);
...
Notice the ; after the loop. This causes the loop to first run without any statement, and the part within brackets runs afterwards, when the loop condition is no longer fulfilled, i.e. a is already equal to n.

C++ fastest cin for reading stdin?

I've profiled a computationally-heavy C++ program on Linux using cachegrind. Surprisingly, it turns out the bottleneck of my program is not in any sorting or computational method ... it's in reading the input.
Here is a screenshot of cachegrind, in case I'm mis-interpreting the profiler results (see scanf()):
I hope I'm right in saying that scanf() is taking 80.92% of my running time.
I read input using cin >> int_variable_here, like so:
std::ios_base::sync_with_stdio (false); // Supposedly makes I/O faster
cin >> NumberOfCities;
cin >> NumberOfOldRoads;
Roads = new Road[NumberOfOldRoads];
for (int i = 0; i < NumberOfOldRoads; i++)
{
int cityA, cityB, length;
cin >> cityA;
//scanf("%d", &cityA); // scanf() and cin are both too slow
cin >> cityB;
//scanf("%d", &cityB);
cin >> length;
//scanf("%d", &length);
Roads[i] = Road(cityA, cityB, length);
}
If you don't spot any issues with this input reading code, could you please recommend a faster way to read input? I'm thinking of trying getline() (working on it while I wait for responses). My guess is getline() may run faster because it has to do less conversion and it parses the stream a less total number of times (just my guess, though I'd have to parse the strings as integers eventually too).
What I mean by "too slow" is, this is part of a larger homework assignment that gets timed out after a certain period of time (I believe it is 90 seconds). I'm pretty confident the bottleneck is here because I purposely commented out a major portion of the rest of my program and it still timed out. I don't know what test cases the instructor runs through my program, but it must be a huge input file. So, what can I use to read input fastest?
The input format is strict: 3 integers separated by one space for each line, for many lines:
Sample Input:
7 8 3
7 9 2
8 9 1
0 1 28
0 5 10
1 2 16
I need to make a Road out of the integers in each line.
Also please not that input is redirected to my program to the standard input (myprogram < whatever_test_case.txt). I'm not reading a specific file. I just read from cin.
Update
Using Slava's method:
Input reading seems to be taking less time, but its still timing out (may not be due to input reading anymore). Slava's method is implemented in the Road() ctor (2 down from main). So now it takes 22% of the time as opposed to 80%. I'm thinking of optimizing SortRoadsComparator() as it's called 26,000,000 times.
Comparator Code:
// The complexity is sort of required for the whole min() max(), based off assignment instructions
bool SortRoadsComparator(const Road& a, const Road& b)
{
if (a.Length > b.Length)
return false;
else if (b.Length > a.Length)
return true;
else
{
// Non-determinism case
return ( (min(a.CityA, a.CityB) < min(b.CityA, b.CityB)) ||
(
(min(a.CityA, a.CityB) == min(b.CityA, b.CityB)) && max(a.CityA, a.CityB) < max(b.CityA, b.CityB)
)
);
}
}
Using enhzflep's method
Considering solved
I'm going to consider this problem solved because the bottleneck is no longer in reading input. Slava's method was the fastest for me.
Streams pretty well know to be very slow. It is not a big surprise though - they need to handle localizations, conditions etc. One possible solution would be to read file line by line by std::getline( std:::cin, str ) and convert string to numbers by something like this:
std::vector<int> getNumbers( const std::string &str )
{
std::vector<int> res;
int value = 0;
bool gotValue = false;
for( int i = 0; i < str.length(); ++i ) {
if( str[i] == ' ' ) {
if( gotValue ) res.push_back( value );
value = 0;
gotValue = false;
continue;
}
value = value * 10 + str[i] - '0';
gotValue = true;
}
if( gotValue ) res.push_back( value );
return res;
}
I did not test this code, wrote it to show the idea. I assume you do not expect to get anything in input but spaces and numbers, so it does not validate the input.
To optimize sorting first of all you should check if you really need to sort whole sequence. For comparator I would write methods getMin() getMax() and store that values in object (not to calculate them all the time):
bool SortRoadsComparator(const Road& a, const Road& b)
{
if( a.Length != b.Length ) return a.Length < b.length;
if( a.getMin() != b.getMin() ) return a.getMin() < b.getMin();
return a.getMax() < b.getMax();
}
if I understood how you current comparator works correctly.
As Slava says, streams (i.e cin) are absolute pigs in terms of performance (and executable file size)
Consider the following two approaches:
start = clock();
std::ios_base::sync_with_stdio (false); // Supposedly makes I/O faster
cin >> NumberOfCities >> NumberOfOldRoads;
Roads = new Road[NumberOfOldRoads];
for (int i = 0; i < NumberOfOldRoads; i++)
{
int cityA, cityB, length;
cin >> cityA >> cityB >> length;
Roads[i] = Road(cityA, cityB, length);
}
stop = clock();
printf ("time: %d\n", stop-start);
and
start = clock();
fp = stdin;
fscanf(fp, "%d\n%d\n", &NumberOfCities, &NumberOfOldRoads);
Roads = new Road[NumberOfOldRoads];
for (int i = 0; i < NumberOfOldRoads; i++)
{
int cityA, cityB, length;
fscanf(fp, "%d %d %d\n", &cityA, &cityB, &length);
Roads[i] = Road(cityA, cityB, length);
}
stop = clock();
printf ("time: %d\n", stop-start);
Running each way 5 times (with an input file of 1,000,000 entries + the first 2 'control' lines) gives us these results:
Using cin without the direction to not sync with stdio
8291, 8501, 8720, 8918, 7164 (avg 8318.3)
Using cin with the direction to not sync with stdio
4875, 4674, 4921, 4782, 5171 (avg 4884.6)
Using fscanf
1681, 1676, 1536, 1644, 1675 (avg 1642.4)
So, clearly, one can see that the sync_with_stdio(false) direction does help. One can also see that fscanf beats the pants off each approach with cin. In fact, the fscanf approach is nearly 3 times faster than the better of the cin approaches and a whopping 5 times faster than cin when not told to avoid syncing with stdio.
inline void S( int x ) {
x=0;
while((ch<'0' || ch>'9') && ch!='-' && ch!=EOF) ch=getchar_unlocked();
if (ch=='-')
sign=-1 , ch=getchar_unlocked();
else
sign=1;
do
x = (x<<3) + (x<<1) + ch-'0';
while((ch=getchar_unlocked())>='0' && ch<='9');
x*=sign;
}
you can use this function for any type of number input, just change the paramater type.
This will run pretty faster than std scanf.
If you want to save more time best thing will be to use fread() and fwrite() but in that case you have to manipulate the input by yourself.
To save time you should use fread() to read a large chunk of data from standard input stream in one call.That will decrease the number of I/O calls hence you will see a large difference in time.

grabbing data sets from a file with an arbitrary amount of spaces

**No direct answers or code examples please, this is my homework which i need to learn from. I'm looking for help concerning the algorithm i need to develop.
I seem to be having a logic error in coming up with a solution for a portion of my class work, the program involves multiple files, but here is the only relevant portion:
I have a file PlayerStats that holds the stats for a basketball player in:
rebounds
points
assists
uniform #
my initial reaction would be to create a while loop and read these into a temporary struct that holds these values, then create a merge function that merges the values of the temp struct with the inital array of records, simple enough?
struct Baller
{
//other information on baller
int rebounds;
int assists;
int uniform;
int points;
void merge(Baller tmp); //merge the data with the array of records
}
//in my read function..
Baller tmp;
int j = 0;
inFile << tmp.uniform << tmp.assists << tmp.points << tmp.rebounds
while(inFile){
ArrayRecords[j].merge(tmp);
j++;
//read in from infile again
}
The catch:
The file can have an arbitrary number of spaces between the identifiers, and the information can be in any order(leaving out the uniform number, that is always first). e.g.
PlayerStats could be
11 p3 a12 r5 //uniform 11, 3 points 12 assists 5 rebounds
//other info
OR
11 p 3 r 5 a 12 //same exact values
What I've come up with
can't seem to think of an algorithm to grab these values from the file in the correct order, i was thinking of something along these lines:
inFile << tmp.uniform; //uniform is ALWAYS first
getline(inFile,str); //get the remaining line
int i = 0;
while(str[i] == " ") //keep going until i find something that isnt space
i++;
if(str[i] == 'p') //heres where i get stuck, how do i find that number now?
else if(str[i] == 'a')
eles if(str[i] = 'r'
If you're only going to check one letter, you could use a switch statement instead of if / else, that would make it easier to read.
You know where the number starts at that point, (hint: str[i+1]), so depending on what type your str[] is, you can either use atoi if its a char array, or std::stringstream if it's an std::string.
I'm tempted to give you some code, but you said not too. If you do want some, let me know and I'll edit the answer with some code.
Instead of using a 'merge' function, try using an std::vector so you can just push_back your structure instead of doing any 'merging'. Besides, your merge function is basically a copy assignment operator, which is created by the compiler by default (you don't need to create a 'merge' function), you just need to use = to copy the data across. If you wanted to do something special in your 'merge' function, then you should overload the copy assignment operator instead of a 'merge' function. Simples.
Do something like that:
int readNumber () {
while isdigit (nextchar) -> collect in numberstring or directly build number
return that number;
}
lineEater () {
Read line
skip over spaces
uniform=readNumber ();
haveNum=false;
haveWhat=false;
Loop until eol {
skip over spaces
if (isdigit)
number=readNumber ();
skip over spaces
haveNum=true;
else
char=nextChar;
haveWhat=true;
if (haveChar and haveNum) {
switch (char) {
case 'p' : points=number; break;
...
}
haveNum=false;
haveWhat=false;
}
}
or, if you are more ambitous, write a grammar for your input and use lex/yacc.

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