C++ syntax to name file via variable and text - c++

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

Related

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());

C++: cin >> *char

So, I'm currently writing a line editor as a learning project on I/O, writing files, and the like. It is written in C++, and I am currently trying to write out to a file of the user's choosing. I have CLI arguments implemented, but I currently have no idea how to implement an in program way of specifying the file to write to.
char *filename;
if (argc >= 2){
filename = argv[1];
} else{
cout << "file>";
cin >> filename;
cin.ignore();
}
This works perfectly well when I use command line arguments; however, whenever I do not, as soon as I start the program, it Segmentation Faults. The place where I use the actual filename is in the save command:
void save(char filename[], int textlen, string file[]){
ofstream out(filename);
out << filestring(textlen, file);
out.close();
}
Which also works perfectly well. Is there any way you can help me? Full source code, for review, is up on https://github.com/GBGamer/SLED
The problem is that char* filename is just a pointer to some memory containing characters. It does not own any memory itself.
When you use the command line argument, the program handles storing that string somewhere, and you get a pointer to it. When you try to read using cin >> filename there isn't actually anywhere to store the read data.
Solution: Replace char* filename with std::string filename (and #include <string>).
Then to open the output file, you need a c-style string (null terminated char array). std::string has a function for this. You would write
std::ofstream out(filename.c_str());
^^^^^
Or, in fact, if you can use a recent compiler with c++11 features, you don't even need to use c_str(). A new std::ofstream constructor has been added to accept a std::string.
Your filename variable points to argv[1] when command line argument is provided, it does not need memory to be allocated but when going in else block, you have not allocated memory to filename. Its just a pointer.
Use malloc to assign filename some memory then take user input.
filename = (char *)malloc(sizeof(char)*(FILE_NAME_LENGTH+1))

using an integer number as the outstream file name?

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

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());

Pass path to file / filename as argument to a function that prints the file to screen in C++

As the title says, is there any way to pass the path to the file / filename to open as an argument in the function?
I've written a short code for printing a .txt-file to the screen in C++, but instead of having all the code in the main(), I'd rather have it as an own function that I can call with the filename of the file to open as the only input argument.
Basically the beginning of the function would look like
void printFileToScreen()
{
ifstream fin;
char c;
fin.open("FILE_TO_OPEN.txt", ios::in);
blablabla
}
Now is there any way to pass "FILE_TO_OPEN.txt" when I call the function?
I've tried
void printFileToScreen(string str)
{
ifstream fin;
char c;
fin.open(str, ios::in);
blablabla
}
where I call the function like printFileToScreen("FILENAME.txt"), but with no luck, so I'm not sure how to do this.
Hope anyone can help :)
Unfortunately, the iostream functions deal with const char* types rather than with std::string (the iostream functions were developed independently of the STL). You instead could use std::string::c_str() to obtain a const char*:
fin.open(str.c_str(), ios::in);
As a general design rule, I would not pass the file name to the called function. I would pass the already opened std::istream object to read from. This allows you to do the job of printing in a function, and to do the job of opening the file and dealing with non-existent files in another. This has the bonus of being able to pass std::cin to your function!
Try changing your function to look like this :
void printFileToScreen(const string &str);
//If you pass a const char*, a string will be constructed
or this :
void printFileToScreen(const char *);
The function you wrote expects an instance of std::string to be passed by value.
Never mind, after some more trying and failing I found out that I needed to pass a char pointer, and not a string. :)
Of course you can pass the filename as a function parameter. If in doubt, pass a "const char*" rather than a string. I should work.