C++: file output with a random name - c++

I'm new to C++ so this might be a very naive question.
I'm trying to output data to a file by calling a function from my main file. I am calling this function multiple times within my main functions and that's why I need to switch on the append mode for writing the files. This line of code writes my output file and works fine:
ofstream outFile("result_col2.plt",ios::app);
.
.
outFile.close();
However, I want to make my output file's name random, and I am trying this:
int number = 1; // let's say
ostringstream convert;
convert << number;
string iLevel_str = convert.str();
string fname = "result_col2" + iLevel_str + ".plt";
ofstream outFile(fname.c_str(),ios::app);
.
.
outFile.close();
But when I do this, my data files are becoming double the size after every run. Why is it that it doesn't work in the latter case, but works well in my previous case? Any suggestions?
To make it more understandable, the file named "result_col2.plt" remains the same size after every run of the main function. Whereas the file named "result_col21.plt" is doubling in size (first run - 85 kb, then 170 kb, and so on.)

unless you change that int number =1 it will keep opening and appending result_col21.plt over and over hence the doubling you need to do a for loop incrementing the number every iteration

If you need just a random file name you can use std::tmpnam() standard function, but it will generate random file name located in system "temp" directory.
For details please refer to: http://en.cppreference.com/w/cpp/io/c/tmpnam

Related

How to writte a file in c++, considering that everytime you run the code, the file keeps storing the previous data?

I'm working in creating a file that contains the data that describes the position of a cell in fuction of time. I was adviced to use snprintf. These were the lines of code that I used to introduce the function:
int n_sample = 50;
char filename[101];
snprintf(filename, sizeof(filename),"dados_movimento_celula_%d.dat", n_sample);
The code runs, showing no errors, however, it keeps alterating the file by replacing the previous data with the new one, instead of just adding the new one set of data. How to fix this?
You can use ofstream and open the file in append mode:
std::ofstream outFile;
outfile.open(fileName, std::ios_base::app);
outFile << content;

What does this code mean "ofstream fout(getenv("OUTPUT_PATH"));"

I'm still new to cpp, and I will appericate if someone can help me to understand this line of code:
ofstream fout(getenv("OUTPUT_PATH"));
This code I saw almost every single Hacker Rank challange. What is the purpose of this code?
I say, when in doubt, simplify.
When something seems too complex and does not make sense at first glance, find ways to break it into smaller pieces that make sense to you.
ofstream fout(getenv("OUTPUT_PATH"));
can be broken into two pieces.
auto res = getenv("OUTPUT_PATH");
ofstream fout(res);
You can look up the documentation of getenv() to understand what the first line does. In your case, it returns the value of the environment variable OUTPUT_PATH. After the line is executed, res will be that value.
You can lookup the documentation for the constructors of ofstream to understand what the second line does. In your case, it constructs an ofstream object using the value of the environment variable OUTPUT_PATH.
After that line, you can use the fout object to write to the stream. The output will be available in the file defined by the environment variable OUTPUT_PATH.
The reason that Hacker Rank does this is because they have 100's or 1000's of users running the same pieces of code at the same time. To make sure each run uses a unique output file they set OUTPUT_PATH to a unique name before running the code. This will result in the output will be placed into a unique file. The wrapper code on Hacker Rank will then compare the output from your file against the expected output.
It's creating an output file stream with the filename of whatever the environment variable "OUTPUT_PATH" is set to.
it's an easy stuff. It is taking the output environment path and passing
that to the object of output stream i.e fout.
Hope you remember
ios_base -> ios -> ostream -> ofstream
As Per cppreference ,
std::ofstream
typedef basic_ofstream ofstream;
Output stream class to operate on files
std::getenv
Defined in header cstdlib
char* getenv( const char* env_var );
Searches the environment list provided by the host environment (the OS), for a string that matches the C string pointed to by env_var and returns a pointer to the C string that is associated with the matched environment list member.
check out your home path using:
#include <iostream>
#include <cstdlib>
int main()
{
if(const char* env_p = std::getenv("PATH"))
std::cout << "Your PATH is: " << env_p << '\n';
}
you are going to see all the paths you have set in your environment
environment has the location of the compiler or other executable stuff.

I am trying to write some file in binary, where I need to overwrite the file contents, how to over write instead of inserting

I am writing a binary file in C++, where I traverse to a particular location and need to over-write the contents with the new one. I know the contents of the integer size, so I keep track of the location and over write it. Seems like, ofstream write function inserts or appends the variable. Is there a way, where I can over write, instead of appending or inserting in a file
long word = sizeof(int) + sizeof(long) + sizeof(long);
std::ofstream file_write(filename, std::ios::out|std::ios::binary);
file_write.seekp(word);
long pos = file_write.tellp();
file_write.write((char *)&some_integer,sizeof(int));
file_write.close()
//some other location
file_write.seekp(pos);
file_write.write((char *)&some_other_integer,sizeof(int));
//Here some_integer should be over written by some_other_integer. Is there a way to do it?
That will be like
value1,value2,value3
I might be able to replace value 2 with value 5.
then it should look like
value1,value5,value3
You need to add std::ios::trunc to your open parameters, as in:
std::ofstream file_write(filename, std::ios::out|std::ios::binary|std::ios::trunc);
That will truncate the file, discarding any existing content.
the relevant flag is truncate
(truncate) Any current content is discarded, assuming a length of
zero on opening.
I sorted it out. We need to use fstream instead of ofstream. Thanks for you help everyone

C++ filestream problem

I'm making a simple game in C++ and I want the highest score at the end of the game to be written in a text file. I'm using fstream to first read the last saved highscore and compare it to the new highscore. The output in the text file looks like this (0НН) and it shouldn't. I'm realy frustrated with this.
Here's a part of my code.
double score_num=0;
fstream datafile("score.pon"); //Declaration of variables
...
if(SPEED>score_num)
{
score_num=SPEED;
}
//getting the score
...
datafile<<score_num; //Writing it to the file
#include <iostream>
#include <fstream>
using namespace std;
#define SPEED 12
int main()
{
double score_num=0;
ofstream datafile("score.pon"); //Declaration of variables
if(SPEED>score_num)
{
score_num=SPEED;
}
//getting the score
datafile<<score_num; //Writing it to the file
return 0;
}
Replaced fstream by ofstream works like a charm. Perhaps you should show more code? Also, closing the file is good habit:
datafile.flush();
datafile.close();
I'll leave errorhandling to you
Hacky solution - open the file as an ifstream, read existing value, close it, adjust score, open file as an ofstream, write score, close it. Alternatively, investigate the use of the seekp() function, and write the score as a binary value, not as text.
My best guess as to why the original was failing is that when you read the last character from a file, the EOF bit is set. In this state, all read & write operations fail. You can write to a file stream that's reached its end by calling clear first.
// the following doesn't truncate file, or handle other error conditions.
if (datafile.eof()) {
datafile.clear();
}
datafile.seekp(0, std::ios_base::beg);
datafile << score_num;
However, this won't solve all your problems. If you write less to the file than its current length (e.g. the old high score was "1.5" and the new high score is "2"), part of the old data will still be present at the end of the file. As long as scores never have a fractional part (in which case you should probably be using an integer type, such as unsigned long), you won't notice the bug, since a < b ⇒ len(a) ≤ len(b). To handle this properly, you'll need to use unapersson's recommended approaches (which will either truncate the file or always write the same amount of data to the file), or use a different I/O library (such as your platform's C library or boost) which provide a way to truncate files (such as the POSIX ftruncate).

how to create files named with current time?

I want to create a series of files under "log" directory which every file named based on execution time. And in each of these files, I want to store some log info for my program like the function prototype that acts,etc.
Usually I use the hard way of fopen("log/***","a") which is not for this purpose.And I just write a timestamp function:
char* timeStamp(char* txt){
char* rc;
char timestamp[16];
time_t rawtime = time(0);
tm *now = localtime(&rawtime);
if(rawtime != -1) {
strftime(timestamp,16,"%y%m%d_%H%M%S",now);
rc = strcat(txt,timestamp);
}
return(rc);
}
But I don't know what to do next. Please help me with this!
Declare a char array big enough to hold 16 + "log/" (so 20 characters total) and initialize it to "log/", then use strcat() or something related to add the time string returned by your function to the end of your array. And there you go!
Note how the string addition works: Your char array is 16 characters, which means you can put in 15 characters plus a nul byte. It's important not to forget that. If you need a 16 character string, you need to declare it as char timestamp[17] instead. Note that "log/" is a 4 character string, so it takes up 5 characters (one for the nul byte at the end), but strcat() will overwrite starting at the nul byte at the end, so you'll end up with the right number. Don't count the nul terminator twice, but more importantly, don't forget about it. Debugging that is a much bigger problem.
EDIT: While we're at it, I misread your code. I thought it just returned a string with the time, but it appears that it adds the time to a string passed in. This is probably better than what I thought you were doing. However, if you wanted, you could just make the function do all the work - it puts "log/" in the string before it puts the timestamp. It's not that hard.
What about this:
#include <stdio.h>
#include <time.h>
#define LOGNAME_FORMAT "log/%Y%m%d_%H%M%S"
#define LOGNAME_SIZE 20
FILE *logfile(void)
{
static char name[LOGNAME_SIZE];
time_t now = time(0);
strftime(name, sizeof(name), LOGNAME_FORMAT, localtime(&now));
return fopen(name, "ab");
}
You'd use it like this:
FILE *file = logfile();
// do logging
fclose(file);
Keep in mind that localtime() is not thread-safe!
Steps to create (or write to) a sequential access file in C++:
1.Declare a stream variable name:
ofstream fout; //each file has its own stream buffer
ofstream is short for output file stream
fout is the stream variable name
(and may be any legal C++ variable name.)
Naming the stream variable "fout" is helpful in remembering
that the information is going "out" to the file.
2.Open the file:
fout.open(filename, ios::out);
fout is the stream variable name previously declared
"scores.dat" is the name of the file
ios::out is the steam operation mode
(your compiler may not require that you specify
the stream operation mode.)
3.Write data to the file:
fout<<grade<<endl;
fout<<"Mr";
The data must be separated with space characters or end-of-line characters (carriage return), or the data will run together in the file and be unreadable. Try to save the data to the file in the same manner that you would display it on the screen.
If the iomanip.h header file is used, you will be able to use familiar formatting commands with file output.
fout<<setprecision(2);
fout<<setw(10)<<3.14159;
4.Close the file:
fout.close( );
Closing the file writes any data remaining in the buffer to the file, releases the file from the program, and updates the file directory to reflect the file's new size. As soon as your program is finished accessing the file, the file should be closed. Most systems close any data files when a program terminates. Should data remain in the buffer when the program terminates, you may loose that data. Don't take the chance --- close the file!
Sounds like you have mostly solved it already - to create a file like you describe:
char filename[256] = "log/";
timeStamp( filename );
f = fopen( filename, "a" );
Or do you wish do do something more?