using an integer number as the outstream file name? - c++

I'm trying to write an mpi program where each node knows its own rank, which is an integer.
I this program I hope each node to create a .txt file with its rank as the file name. That is, I hope the program to generate a file called rank.txt where rank is an integer.
I know how to convert an int to string, but I am quite confused about how I can combine that string with .txt and put it into a filename. What is the easiest way to do it?
Thanks in advance.
EDIT
I have combined the number with .txt and put them into a string filename but when I typed std::ofstream out_stream(filename) the compiler tells me that
no matching constructor for initialization `std::outstream`
How can I put the string into a filename?

The problem is that there's no constructor for std::ofstream that takes a std::string. You need to pass const char*, so just say:
std::ofstream out_stream(filename.c_str());
Things have changed with the latest standard revision, though, so check your compiler documentation for how to enable C++11.

If you've already converted the int to an std::string, say rank_s, then rank_s + ".txt" should be enough.

use fstream and the << operator.
For string concatenation:
std::stringstream vIndex;
vIndex << i;
std::string index = vIndex.str() + ".txt";

If you can use boost:
std::string filename = boost::lexical_cast<std::string>(rank) + ".txt";
Otherwise (for example):
std::ostringstream s;
s << rank;
std::string filename = s.str() + ".txt";

std::string filename = std::to_string(i) + ".txt";
Needs an up to date compiler that supports c++11 for this
edited to answer question :-
If you have c++11 just do
std::ofstream out_stream(std::to_string(i) + ".txt");
If you don't then you're best looking at the other answers

Related

C++ syntax to name file via variable and text

I have a program that takes in the name of a file as an argument (example: books.txt), runs, and then outputs the results to a new text file. I need to name the output file with an addendum (example: books_output.txt).
The method that I tried was
ofstream outputFile;
outputFile.open(argv[1] + "_output.txt", ofstream::out);
but this didn't compile.
How can I make this work?
Your statement should look like this (as mentioned in my comment):
outputFile.open(std::string(argv[1]) + "_output.txt", ofstream::out);
// ^^^^^^^^^^^^ ^
assumed argv[1] comes from the standard main() signature
int main(int argc, char* argv[])
argv[1] is a char* pointer and you can't concatenate char* pointers that way.
As some people bother regarding support of obsolete C++ standard versions, the std::ofstream::open() signatures of earlier versions didn't support a const std::string parameter directly, but only const char*. In case you have that situation your statement should look like
outputFile.open((std::string(argv[1]) + "_output.txt").c_str(), ofstream::out);
you cannot put a + between 2 C strings. Use std::string instead. Do this
ofstream outputFile;
std::string fname = std::string(argv[1]) + "_output.txt";
outputFile.open(fname.c_str(), ofstream::out);
More recent c++ versions allow
outputFile.open(fname, ofstream::out);
which reads nicer but means the same thing

Use string or array of char for filename?

I have come across something online about strings. It says to use an array of chars for a filename input and not string. Why is that?
You seem to be using an older version of C++, where std::ifstream::open accepts only a const char *, not a std::string (see docs):
void open (const char* filename, ios_base::openmode mode = ios_base::in);
As you can see, you cannot pass a std::string here.
In C++11 and newer, you can pass a std::string as well:
void open (const string& filename, ios_base::openmode mode = ios_base::in);
A better approach: use std::string to input the file name and the do File.open(filename.c_str()); to open the file.
That advice is basically wrong. The problem it is attempting to get around is that back in the olden days, file streams took const char* as the argument for the file name, so you couldn't directly use a std::string for the name. Of course, the answer to that is to use std::string, and call c_str() to pass the file name:
std::string name = "test.txt";
std::ofstream out(name.c_str());
These days, file streams also have a constructor that takes std::string, so you can do this:
std::string name = "test.txt";
std::ofstream out(name);
I suspect it is because of the prototype of ifstream::open(const char*). Personally, I would have written the code as:
string filename;
cin >> filename;
ifstream testmarks;
testmarks.open(filename.c_str());
But that is yet more complexity to explain, and this is obviously aimed at someone very new to C++.
This is wrong, and it's a wonderful way to write programs vulnerable to buffer overflows, at least as written in the example.
The "open" function expect char pointer.
However it is fine to do this:
std::string filename;
std::cin >> filename;
std::ifsteam f;
f.open(filename.c_str());

Deleting a file with name created using a string variable

I am writing a function which will give users an opportunity to change their username. To do this I was trying to rename the file in which their data is stored. I have come up with a way of doing this, which doesn't quite work but I think I am close.
The filename is originally created like this -
std::cout << "Please enter a username: ";
std::getline (std::cin, username);
std::ofstream fout (username + ".txt");
which works fine. And then if they later choose to change their username
std::cout << "Please type in your new username." << std::endl;
std::getline (std::cin, newUsername);
std::ofstream fout (newUsername + ".txt");
// I copied the contents of username.txt to newUsername.txt here
which again works fine.
The problem lies below.
the problem lies in deleting the original file, more specifically when adding the file extension .txt
I have included #include for the remove() functionality
And added .c_str() to username as I believe remover () will only take a C string (char*), not a C++ string.
remove(username.c_str() + ".txt"); // error expression must have integral or enum type referring to ".txt".
Thanks in advance for everyones time
Simple enough
remove((username + ".txt").c_str());
The return value from username + ".txt" is called a temporary (because it is an unnamed value) but there is nothing that says you can't call a method (like c_str) on a temporary object.
remove takes a const char* as an argument, and you cannot add two const char*s together using the + operator. Therefore, the solution is to add them as strings then call c_str() on the result.
remove((username + std::string(".txt")).c_str());
Your problem lies here:
remove(username.c_str() + ".txt"); // error expression must have integral or enum type referring to ".txt".
Adding two char*s doesn't produce a string.
This may be a better approach:
auto filename = username + ".txt"
remove(filename.c_str())
Your problem lies here:
remove(username.c_str() + ".txt"); // error expression must have integral or enum type referring to ".txt".
Adding two const char*s doesn't produce a (std::)string.
This may be a better approach:
auto filename = username + ".txt"
remove(filename.c_str())
Note that this produces a relative filename whereas an absolute filename may be preferable depending on how this is called.

how can i add this variable to my path for ifstream?

I'm trying to append my path and contain a variable as part of the path but I'm getting an error.
What's wrong with it?
fstream fin("E:\\Games\\maps\\" + this->MapNumber + ".map", ios::in|ios::binary|ios::ate);
this->MapNumber is a USHORT
error: 13 IntelliSense: expression must have integral or unscoped enum type
In C++ you can't use + to concatenate literal strings. You can use + with std::strings to concatenate them, but that won't work with integer or other types. You need to use a stream instead. Insertion and extraction into a stream will cause the types that support it to represent themselves as text, but you probably already knew this from general I/O.
Try with something like this:
std::stringstream filename;
filename << "E:\\Games\\maps\\" << this->MapNumber << ".map";
std::fstream fin(filename.str().c_str(), ios::in|ios::binary|ios::ate);
Just like with everything else, to use something you need to include the header that declares it first. In order to use std::stringstream you need to include <sstream>.
You can't use operator+ on a string and another type like string or so you can either:
Option1: turn all variables into strings to append them
string s = string("E:\\Games\\maps\\") + string(itoa(this->MapNumber)) + string(".map");
option2: use stringstream as #k-ballo explained
option3: use the good old C fprintf (my personal favourite)
char str[100];
fprintf(str, "E:\\Games\\maps\\ %d .map", this->MapNumber);

Concatenate write parameters in C++

I need to concatenate the parameters in the write function. How would I do this?
Example: ofstream write(newFolder concat "/newfile.txt");
mkdir(newFolder);
ofstream write (wantTo "concat here");
write << "Sup mo fo";
write.close();
If newFolder is a std::string, you can simply use newFolder + "/newfile.txt". You'd have to make sure newFolder does not end with a / or a \ though. You may need to use the c_str() function on your std::string if you require a char* in your write function.
While using std::string is the preferred way, be careful because older versions of the standard library doesn't support an open method that takes a std::string as argument.
If you get an error in the call to open when using std::string, then you have to do it in two steps:
std::string newFolder = "/path/to/folder";
mkdir(newFolder.c_str(), 0644); // The 'mkdir' function wants 'const char *'
// Has to concatenate strings here if your standard library is too old
std::string folderAndFile = newFilder + "/filename";
std::ofstream output(folderAndfile.c_str());