Write to user specified file in C++ - c++

Can I specify what file I want to write into in C++? I want to be able to type in the filename and write into that file. When I try making myfile.open("example.txt") myfile.open(var), I get a big error...
error: no matching function for call to ‘std::basic_ofstream >::open(std::string&)’
/usr/include/c++/4.2.1/fstream:650: note: candidates are: void std::basic_ofstream<_CharT, _Traits>::open(const char*, std::_Ios_Openmode) [with _CharT = char, _Traits = std::char_traits]
Can you make any sense of this or explain what I am doing wrong? I have a feeling this is very simple, as this is my first week using C++.

If var is an std::string, try:
myfile.open(var.c_str());
The error tells you exactly what's wrong, although the precision of the template types named doesn't help make that crystal clear. Take a look at the reference for .open(). It takes a const char * for the filename, and another optional mode parameter. What you are passing is not a const char *.

Like the error says, it is trying to match the parameters with a character pointer and std::string is not a character pointer. However std::string::c_str() will return one.
try:
myfile.open(var.c_str());

In short, yes you can specify a file to open and write into many different ways.
If you're using an fstream and want to write plain text out, this is one way:
#include <string>
#include <fstream>
int main()
{
std::string filename = "myfile.txt";
std::fstream outfile;
outfile.open( filename.c_str(), std::ios::out );
outfile << "writing text out.\n";
outfile.close();
return 0;
}

Is var a std::string? If so, you should be passing var.c_str() as there is not a variant of .open() that takes a std::string.

Is your variable a string, char[], or char*? I think the open() method wants a c-style string, which would be char[] or char*, so you'd need to call the .c_str() method on your string when you pass it in:
myfile.open(var.c_str());

There is a second parameter to the open call. it should be like myfile.open("example.txt", fstream::out)

The error message is quite clear. It says: the basic_ofstream class (your file object) does not have a member function that's called "open" and takes a single argument of type string (your var). You need to go from string to const char * - for that, you use var.c_str().

Related

C++, function that can take either ifstream or istringstream

I have a function do_something that reads unsigned characters from a stream.
The stream can be created from a file given the file name. Or it can be created from the given string by considering it as data. I would like to reuse the function in both cases.
The code below gives an error in the second case: "error C2664: 'do_something: cannot convert argument 1 from 'std::basic_istringstream' to 'std::basic_istream'".
What is the proper way to do this?
static void do_something(std::basic_istream<unsigned char>& in)
{
in.get();
}
static void string_read(unsigned char* in)
{
std::basic_ifstream<unsigned char> file(std::string("filename"));
do_something(file);
std::basic_istringstream<unsigned char> str(std::basic_string<unsigned char>(in));
do_something(str);
}
Your code is experiencing something called a vexing parse. The line:
std::basic_istringstream<unsigned char> str(std::basic_string<unsigned char>(in));
is interpreted as a function declaration. str here is a function that returns a std::istringstream and takes as its parameter a variable of type std::string called in. So when you pass it into the function there's an obvious type mismatch.
To change it into a variable declaration you can use curly braces:
std::basic_istringstream<unsigned char> str{std::basic_string<unsigned char>(in)};

Passing a string to file.open();

I am used to higher level languages (java, python etc.), where this is dead obvious. I am trying to pass a string the user inputs to cin, the name of a file to open. There appears to be some sort of pointer madness error, and my code will not compile.
I deleted some of my code to make it more clear.
#include <iostream>
#include <fstream>
using namespace std;
string hash(string filename);
int main(){
cout << "Please input a file name to hash\n";
string filename;
cin >> filename;
cout <<hash(filename);
return 0;
}
string hash(string filename){
file.open(filename);
if(file.is_open()){
file.close();
}
return returnval;
}
Here is the compile time error.
<code>
$ g++ md5.cpp
md5.cpp: In function ‘std::string hash(std::string)’:
md5.cpp:22: error: no matching function for call to ‘std::basic_ifstream<char, std::char_traits<char> >::open(std::string&)’
/usr/include/c++/4.2.1/fstream:518: note: candidates are: void std::basic_ifstream<_CharT, _Traits>::open(const char*, std::_Ios_Openmode) [with _CharT = char, _Traits = std::char_traits<char>]
</code>
(I know that there are libraries for md5 hashes, but I am trying to learn about how the hash works, and eventually hash collision)
open() takes a C-style string. Use std::string::c_str() to get this:
file.open (filename.c_str());
In order to use just a string, as pointed out below, you'll need to use a compiler with C++11 support, as the overload was added for C++11.
The reason it's not like Java etc. is that it came from C. Classes didn't exist in C (well, not nearly as well as they do in C++), let alone a String class. In order for C++ to provide a string class and keep compatibility, they need to be different things, and the class provides a conversion constructor for const char * -> std::string, as well as c_str() to go the other way.
Consider passing the argument (and maybe the return too) as const std::string & as well; no unnecessary copies. The optimization would probably catch those, but it's always good to do.

How do I fix a "No instance of overloaded function" error with cin.getline?

string add_text()
{
const int string_size(30);
string add_string;
cin.getline (add_string,string_size,'\n');
return add_string;
}
When I compile the program with the function above, I get an error. Note that I am using using namespace std; earlier in the program. If it helps I am using Code Blocks and have also tried compiling the program using the Visual Studio 11 Professional Beta.
The Error:
C:\Users\Jonathan\Documents\Code_Blocks\test_12\main.cpp|32|error: no matching function for call to 'std::basic_istream<char, std::char_traits<char> ::getline(std::string&, const int&, char)'|
Any help with this issue will be greatly appreciated, thanks in advance!
You're calling std::istream::getline(char *, streamsize) - you can see it requires a char * instead of the std::string you're passing.
Use std::getline(std::istream&, std::string&, char) instead, like so:
getline(cin, add_string, '\n');
istream::getline doesn't take a std::string as parameter, but a char*. You can fix it by calling the function correctly.
So, provided you know the max size of the line:
char buff[256]; //or whatever length
cin.getline (buff,string_size,'\n');
string add_string(buff);
Don't use member .getline()s, but global std::getline().
Member .getline()s can only use char * as buffer, while std::getline() can use std::string.
cin.getline is a member function. As such, it is not overloaded to account for every possible type in existence. So, developers overload the global version (i.e., std::getline).

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.