Referencing cout to a variable location (file or cmd) - c++

I would like to write output either to the cmd window or a log file using one function only. The best I found to do this was this treed here.
So this code (minor changes from the referenced source) works for me to 90%:
void outputTest(){
cout << "Testing a new version of output." << endl;
std::ofstream realOutFile;
bool outFileRequested = true;
if(outFileRequested)
realOutFile.open("foo.txt", std::ios::out);
std::ostream & outFile = (outFileRequested ? realOutFile : std::cout);
outFile << "test" << endl;
keep_window_open();
}
Now instead of "foo.txt" I would like to write the file to another location. So I added the following:
string LogFile = config_.outputFiles+config_.projectName; //+"/RoomData.log"
ofstream realOutFile;
if (logFileRequested && config_.saveLogs){
realOutFile.open(LogFile+"/foo.txt", ios::out);
}
std::ostream & outFile = (logFileRequested ? realOutFile : cout);
I also tried passing only a string but in both cases I get that the function call does not match.
Is there a way to fix that?
Why is passing a string different than passing "string content"?
Thanks for your help.
P.S. Sorry I did not het the C++ code formatted properly.

Please see next link for function prototype: http://www.cplusplus.com/reference/fstream/ofstream/open/
open function receives const char* as 1st parameter.
This way it should work ->
string LogFile = config_.outputFiles+config_.projectName; //+"/RoomData.log"
ofstream realOutFile;
if (logFileRequested && config_.saveLogs){
LogFile += "/foo.txt";
realOutFile.open(LogFile.c_str(), ios::out);
}
std::ostream & outFile = (logFileRequested ? realOutFile : cout);

Related

C++ ofstream can't open file from variable name (not even after using c_str())

In my code I am trying to create a file and write to it:
std::ofstream saveFile("file.txt");
ofstream << "test" << endl;
Works perfectly!
But,
std::string fileName = "file.txt"
std::ofstream saveFile(filename.c_str());
ofstream << "test" << endl;
I've tried with and without c_str(), with no luck. There are no errors. But ofstream.good() returns false.
It should work. But do you really post the right code?
At least your code has several obvious syntax errors:
std::string fileName = "file.txt"; // no semicolon
std::ofstream saveFile(fileName.c_str()); // 'fileName' rather than 'filename'
saveFile << "test" << endl; // don't redirect "test" to std::ofstream
// std::ofstream is a class rather than an instance
Please refer to fstream for more detailed information.

ifstream not working with variable parameter using C++11 and c_str() appended

Note: I am using the C++11 standard, so I don't see why this isn't working with or without c_str() appended.
I have the following code:
// open streams
ifstream in(input);
ofstream out(output);
// get which file to open
in.ignore(INT_MAX, ':'); // we don't need the beginning part
in.ignore(); // remove trailing whitespace
string fileLocation;
getline(in, fileLocation);
out << "Loading: " << fileLocation << endl;
cout << "Loading: " << fileLocation << endl;
// now that we know where the file is, load it:
ifstream file(fileLocation);
which reads from a file that looks vaguely like this
File: file.txt
(Subcommands below)
I know that I am pulling the correct filename because of the terminal output.
Anyway, I noticed that the stream wasn't opening properly, so I added this conditional to check:
if ( !file )
{
cout << "File wasn't loaded properly." << endl;
}
And sure enough, I see that message when running the program.
My question is this: how come, when I hard-code the file location, e.g. ifstream file("file.txt") it opens up no problem? How do I get this working properly?

c++ Fstream string combination error

I'm trying to make a function that writes a .ps1 script. I'm learning fstream functions and methods and I ran in to some troubles. I can't figure a way to make Fstream create the file at the given path (path1) and add in the same time a given name for the file and the extension.
void write(string s, string name) {
ostringstream fille;
fille << "$client = new-object System.Net.WebClient\n" << s;
string fil = fille.str();
ostringstream pat;
pat << path1 << "/" << ".ps1";
string path = pat.str();
fstream file(path);
if (file.open()) {
file << fil;
file.close();
}
}
I get the following error message (on the if line) during compilation:
no instance of overloaded function "std::basic_fstream<_Elem, _Traits>::open [with _Elem=char, _Traits=std::char_traits<char>]" matches the argument list
C2661 'std::basic_fstream<char,std::char_traits<char>>‌​::open': no overloaded function takes 0 arguments
First of all you don't use name parameter.
Second you don't define path1 variable.
And you do not need to call fstream::open method if you use fstream's initialization constructor.
void write( const std::string & s, const std::string & name )
{
std::string fil("$client = new-object System.Net.WebClient\n");
fil += s;
std::ostringstream path;
path << "C:/Folder/" << name << ".ps1";
std::ofstream file( path.str() );
if ( file.is_open() ) {
file << fil;
file.close();
}
}
if (file.open()) {
Look at a reference: as the error message states, there isn't a member function of fstream called open that takes no arguments.
This is probably a typo for:
if (file.is_open()) {

How to write console output to a text file in cpp?

I'm trying to write console data into a separate text file in cpp. Anybody help me with sample code.
There are various ways to do this. You could redirect it from the command line with programname > out.txt. Or you could use freopen("out.txt","w",stdout); at the start of your program.
If you want to write from your own process, I'd suggest a simple print method
void print(const string str, ostream & output)
{
output << str;
}
Then you can call
print("Print this", cout);
for console output, or
ofstream filestream("filename.out");
print("Print this", filestream);
to write into a file "filename.out". Of course you gain most, if print is a class method that outputs all the object's specific information you need and this way you can direct the output easily to different streams.
If you want to create a child process and redirect its output you could do something like this:
FILE* filePtr = popen("mycmd");
FILE* outputPtr = fopen("myfile.txt");
if(filePtr && outputPtr) {
char tmp;
while((tmp = getc(filePtr)) != EOF)
putc(tmp, outputPtr);
pclose(filePtr);
fclose(outputPtr);
}
bbtrb wrote:
void print(const string str, ostream &
output) {
output << str; }
Better than this is of course
ostream& output(ostream& out, string str) {out << str; return out;}
so that you can even have the manipulated output stream returned by the function.
smerrimans answer should help you out.
There is also the option to implement your own streambuf and use it with std::cout and std::cerr to store printouts to file instead of printing to console. I did that a while ago to redirect printouts to some sort of rotating logs with timestamps.
You will need to read up a little bit on how it works and this book helped me get it right.
If that's not what you're after it is a bit of overkill though.
Create file -> redirect input into file
#include <iostream>
#include <fstream>
#include <string>
int main()
{
std::string file_name;
std::string str;
std::cout << "Add file name:";
std::cin >> file_name;
std::cout << "Open file:" << file_name << std::endl;
std::ofstream oFile(file_name);
if (!oFile) {
std::cout << "ERROR: we can't open file:" << file_name << std::endl;
return 1;
}
else {
std::cout << "File is open: " << oFile.is_open() << std::endl;
}
std::cout << "Enter you sentence into file:\n";
getline(std::cin >> std::ws, str);
oFile << str;
oFile.close();
return 0;
}

Returning ifstream in a function

Here's probably a very noobish question for you: How (if at all possible) can I return an ifstream from a function?
Basically, I need to obtain the filename of a database from the user, and if the database with that filename does not exist, then I need to create that file for the user. I know how to do that, but only by asking the user to restart the program after creating the file. I wanted to avoid that inconvenience for the user if possible, but the function below does not compile in gcc:
ifstream getFile() {
string fileName;
cout << "Please enter in the name of the file you'd like to open: ";
cin >> fileName;
ifstream first(fileName.c_str());
if(first.fail()) {
cout << "File " << fileName << " not found.\n";
first.close();
ofstream second(fileName.c_str());
cout << "File created.\n";
second.close();
ifstream third(fileName.c_str());
return third; //compiler error here
}
else
return first;
}
EDIT: sorry, forgot to tell you where and what the compiler error was:
main.cpp:45: note: synthesized method ‘std::basic_ifstream<char, std::char_traits<char> >::basic_ifstream(const std::basic_ifstream<char, std::char_traits<char> >&)’ first required here
EDIT: I changed the function to return a pointer instead as Remus suggested, and changed the line in main() to "ifstream database = *getFile()"; now I get this error again, but this time in the line in main():
main.cpp:27: note: synthesized method ‘std::basic_ifstream<char, std::char_traits<char> >::basic_ifstream(const std::basic_ifstream<char, std::char_traits<char> >&)’ first required here
No, not really. ifstream doesn't have a copy constructor, and if you try to return one, that means copying the instance in your function out to wherever the return needs to go.
The usual workaround is to pass in a reference to one, and modify that reference in your function.
Edit: while that will allow your code to work, it won't fix the basic problem. Right now, you're mixing two rather different responsibilities into a single function: 1) obtain a file name, 2) open or create that file. I think if you separate those, the code will be simpler, and make it much easier to eliminate the source of the problem you're seeing.
Edit 2: Using a reference like this works perfectly well without an operator=. The general idea is something like:
int open_file(char const *name, fstream &stream) {
stream.open(name);
}
The assignment operator is neither necessary nor useful in this case -- we simply use the existing fstream via the reference. An operator= would be necessary if and only if we had to pass the argument to the ctor. With a stream, we can default construct a stream that doesn't connect to a file, and then use open to connect to the file after the fact.
bool checkFileExistence(const string& filename)
{
ifstream f(filename.c_str());
return f.is_open();
}
string getFileName()
{
string filename;
cout << "Please enter in the name of the file you'd like to open: ";
cin >> filename;
return filename;
}
void getFile(string filename, /*out*/ ifstream& file)
{
const bool file_exists = checkFileExistence(filename);
if (!file_exists) {
cout << "File " << filename << " not found." << endl;
filename = getFileName(); // poor style to reset input parameter though
ofstream dummy(filename.c_str();
if (!dummy.is_open()) {
cerr << "Could not create file." << endl;
return;
}
cout << "File created." << endl;
}
file.open(filename.c_str());
}
int main()
{
// ...
ifstream file;
getFile("filename.ext", file);
if (file.is_open()) {
// do any stuff with file
}
// ...
}
ifstream does not support copy construct semantics (that what the error message basically sais), so you cannot return an ifstream. Return an ifstream* instead, and pass to the caller the responsability to delete the allocate pointer.
As an option, ifstream may be extended and custom constructor added to new class.
I've extended it to create test resource stream, encapsulating test resource lookup inside of it.
// test_utils.h
class TestResourceStream : public std::ifstream {
public:
TestResourceStream(const char* file_path);
};
// test_utils.cpp
namespace fs = std::filesystem;
fs::path test_resource_path(const char* file_path) {
fs::path path{std::string{"tests/resources/"} + file_path};
if (!fs::exists(path))
throw std::runtime_error{std::string{"path "} +
fs::absolute(path).c_str() + " does not exist"};
return path;
}
TestResourceStream::TestResourceStream(const char* file_path)
:std::ifstream{test_resource_path(file_path).c_str()} {}
// usage in test
TEST_CASE("parse") {
std::list<GosDump::Expertise> expertises;
TestResourceStream stream("requests/page_response.json");
GosDump::Json::parse(expertises, stream);
REQUIRE(10 == expertises.size());
}