C++ default output stream what causes an error? - c++

I have opened a file to write to, and according to some conditions sometimes I want to print output to the screen and sometimes to the file. So I edited my function to be like this:
Cacl(const std::string &str, const ofstream &to=std::cout)
But I'm getting an error, what may cause this?
no viable conversion from 'std::__1::ostream' (aka 'basic_ostream<char>') to 'const std::__1::ofstream' (aka 'const basic_ofstream<char>')
void Calculator::solve(const std::string &command, const ofstream &to=std::cout) {

std::cout is an object of type std::ostream which is a base class of std::ofstream (it's more general than std::ofstream), so you could just do:
void Calculator::solve(const std::string &str, std::ostream &to = std::cout) {
// instead of ofstream ^^^^^^^
and now you can pass an ofstream object to this function as well.
Also, the ostream shouldn't be const otherwise you won't be able to write to it.

Related

Passing Multiple Strings in Concatenation Attempt to an ostringstream Parameter

I am trying to create a method that will accept a stream (i.e. ostringstream) parameter that will be logged to a file.
In the header file, it is declared as:
static void Log(const std::ostringstream& message, LoggingSeverity severity = LoggingSeverity::info);
However, when I try to call the method from another class, such as:
SimpleLogger::Log("Name registered.", SimpleLogger::LoggingSeverity::trace);
I am getting the following error: E0415 no suitable constructor exists to convert from "const char []" to "std::basic_ostringstream<char, std::char_traits<char>, std::allocator<char>>"
And if I try to structure a call by concatenating strings (input is of type std::string), like this:
SimpleLogger::Log("String to int conversion of [" << input << "] failed.", SimpleLogger::LoggingSeverity::warning);
I receive the following error: E0349 no operator "<<" matches these operands
From the errors, I understand that the std::ostringstream parameter doesn't like the strings, but I was under the impression that the data type would provide me the needed functionality of being able to provide objects to the stream, including, for example, int values. Is there a better data type to achieve the desired result? Or, is the structured calls to the method incorrect?
Well the problem here is you are passing a string to a stringstram constructor, the idea is ok but the constructor is defined explicit so there is no automatic conversion to from string to stringstream, explicit stringstream (const string& str , ios_base::openmode which = ios_base::in | ios_base::out); , you can find details here
As for your question here is a sample code,
#include <string>
#include <iostream>
#include <sstream>
void Logg(const std::ostringstream& message) {
std::cout<<message.str()<<std::endl;
}
int main()
{
std::string a= "other message";
Logg(std::ostringstream("some message"));
Logg(std::ostringstream(a));
Logg(static_cast<std::ostringstream>(a));
}
Output
some message
other message
other message

Can I use a member variable of type ofstream initialized in the class constructor?

I'm having issues declaring a constructor of an inherited class.
class Report{
public:
string fileName;
std::ofstream outputFile;
Report(string fileName, ofstream outputFile) {
fileName = fileName;
outputFile = outputFile; //<-- error here
}
void returnFile(string, ofstream);
void Report::returnFile(string name, ofstream file){
file.open(name);
}
};
class financialReport: public Report{
public:
void electorateHappenings();
void electorialImpact();
double finances();
void writetoFile();
financialReport(string fileName, ofstream outputFile)
:Report(fileName, outputFile) { } //<-- error here
};
the error occurs on the 3rd last line :Report(fileName, outputFile).
This line produces the error:
function "std::basic_ofstream<_CharT, _Traits>::basic_ofstream(const
std::basic_ofstream<_CharT, _Traits> &) [with _CharT=char,
_Traits=std::char_traits<char>]" (declared at line 848 of
"C:\MinGW\lib\gcc\mingw32\9.2.0\include\c++\fstream") cannot be referenced
-- it is a deleted function
Is it not possible to create a constructor including ofstream?
The error also occurs on line 9 with outputFile = outputFile.
Thank you.
You can't pass it by copy, you can't copy one, but you can pass it by reference and initialize it in the initializer list of the class:
Demo
class Report {
public:
string fileName;
std::ofstream &outputFile; //reference here
// reference parameter, and initializer list
Report(string fileName, ofstream &outputFile) : outputFile(outputFile) {
fileName = fileName;
}
//...
};
Do the same in financialReport:
financialReport(string fileName, ofstream& outputFile) : Report(fileName, outputFile) {}
^
Note that this is a solution to the problem posed in the question, as normal, but in a more deep analysis, though you don't go in detail about what you want to achieve, I wouldn't go so far as to say it's a wrong approach, but odds are you can structure your program in a better way.
Yes, you can, but the error is telling you that you cannot copy an object of std::ofstream.
Depending on what you want to do, there are two ways to handle it.
Pass the ownership of std::ofstream to your newly created object:
Report(string fileName, ofstream outputFile) :
fileName{std::move(outputFile)},
outputFile{std::move(outputFile)}
{
}
//creation of object:
std::ofstream ofs {"filename.txt"};
Report report {"filename.txt", std::move(ofs)};
//ofs is empty here, it's whole content has been transferred to report object
Pass a reference to existing std::ofstream object:
class Report{
public:
string fileName;
std::ofstream& outputFile;
Report(string fileName, ofstream& outputFile) :
fileName{std::move(outputFile)},
outputFile{outputFile}
{
}
//creation of object:
std::ofstream ofs {"filename.txt}";
Report report {"filename.txt", ofs};
//you can use ofs from both here and from inside of report, but
//you have to ensure that ofs lives as long as report will use it or else you will enter Undefined Behaviour land
Note: If you want to have the same names for class members and for constructor arguments, you need to use member initializer list, like I did. If you decide to use references, you are required to use it as well.

QT ofstream use variable as a path name

I'm trying to make a function which takes QString as well as an int.
Convert QString variable into a filename for ofstream, then take the integer and place it into the file. So far I have managed to take a constant filename such as "Filename.dat" and write a variable into it. However when I try to use QString like this :
void write(const char what,int a){
std::ofstream writefile;
writefile.open("bin\\" + what);
writefile << a;
writefile.close();
}
I get an error
void write(const char,int)': cannot convert argument 1 from 'const char [5]' to 'const char
This is the function which calls write();
void Server::on_dial_valueChanged(int value)
{
write("dial.dat",value);
}
When I use "bin\dial.dat" instead of combining "bin\" with a string it works fine. ofstream.open(); uses "const char*".
I've tried all the filetypes so they may not match my description
The question is-
Does anybody have an idea how to combine "bin\" and a QString and make it work with ofstream?
I've spend a lot of time googling it but still can't make it work.
Thanks!
Any suggestions are more than welcome
void write(const char what,int a) is wrong as you pass only one char to function you should have void write(const char* what,int a) to pass pointer to cstring beginning.
You also want to concat two cstrings and in c++ you can't do it like in other languages but you can use std::string to do what you want.
Try this
#include <string>
void write(const char* what,int a){
std::ofstream writefile;
std::string fileName("bin\\");
fileName+=what;
writefile.open(fileName.c_str());
writefile << a;
writefile.close();
}

How to redirect printing from screen (or any FILE*) into a string/char* in C++

I am working on a C++ code and I wish to do the following:
In the code there is a new type, T, there is a method defined on T that prints some information to a type FILE* variable.
I would like to do some work on this string inside of the program, so I would like to have a variable of type string (or even char*) that will contain what is printed to the screen (if I give the printing function stdout as the File*).
How can I do this ? maybe I can create some FILE* variable and then create (somehow) a string/char* variable with the information that is stored in that File* variable we created ?
Any help is appreciated!
POSIX 1.2008 fmemopen, open_memstream functions create a FILE* pointer which writes to (and/or reads from) memory.
If it does not work for your platform (and there is no other way to hook into FILE *), then you're out of luck.
The next thing I'd try is creating an anonymous pipe, (POSIX pipe, Windows CreatePipe), wrapping its writing side into FILE * (POSIX fdopen, plus Windows _open_osfhandle to get a CRT fd from HANDLE). Here you have to ensure that the pipe's buffer size is enough, or to spawn a thread for reading the pipe. Don't forget to fflush the writing side after the method is done (or use setbuf to disable buffering).
There are several platform-independent ways to do it.
In C++ you can use stringstream(http://www.cplusplus.com/reference/sstream/stringstream/), which has many << operator overloads. So if you pass a reference to ostream& (not oFstream) to the output method, you can easily switch between files, stadard output stream and string outputs, because all this streams are inherited from ostream. Then you can get std::string object from stringstream and get C-string from it if you need.
Code example:
Output function (or method, then you don't need the second argument from the example):
void PrintMyObjectToSomeStream(std::ostream& stream, const MyClass& obj)
{
stream << obj.pubField1;
stream << obj.pubField2;
stream << obj.GetPrivField1();
stream << "string literal";
stream << obj.GetPrivField2();
}
Usage:
MyClass obj1;
std::ofsstream ofs;
std::stringstream sstr;
//...open file for ofs, check if it is opened and so on...
//...use obj1, fill it's member fields with actual information...
PrintMyObjectToSomeStream(obj1,std::cout);//print to console
PrintMyObjectToSomeStream(obj1,sstr);//print to stringstream
PrintMyObjectToSomeStream(obj1,ofs);//print to file
std::string str1=sstr.str();//get std::string from stringstream
char* sptr1=sstr.str().c_str();//get pointer to C-string from stringstream
Or you can overload operator<<:
std::ostream& operator<<(std::ostream& stream, const MyClass& obj)
{
stream << obj1.pubField;
//...and so on
return stream;
}
then you can use it in this way:
MyClass obj2;
int foo=100500;
std::stringstream sstr2;
std::ofstream ofs;//don't forget to open it
//print to stringstream
sstr2 << obj2 << foo << "string lineral followed by int\n";
//here you can get std::string or char* as like as in previous example
//print to file in the same way
ofs << obj2 << foo << "string lineral followed by int\n";
Using FILE is more C than C++ but you can think how to switch between fpirntf and sprintf or use Anton's answer.

Reading file until blank line

After reading Jerry Coffin's answer on this question I copy-pasted his code into my editor, and after some minor edits it compiled and run like it should.
Here is the code after the changes:
#include <iostream>
#include <string>
#include <istream>
#include <fstream>
class non_blank {
private:
std::string data_;
friend std::istream& operator>> (std::istream &is, non_blank &n) {
std::getline(is, n.data_);
if (n.data_.length() == 0) {
is.setstate(std::ios::failbit);
}
return is;
}
public:
operator std::string() const {
return data_;
}
};
int main(int, char *[]) {
non_blank line;
std::ifstream ifs("teste.txt");
while(ifs >> line) {
//std::cout << line; <----- error
std::string s = line;
std::cout << s << std::endl;
}
return 0;
}
I've got an error when trying to use a non_blank variable in a std::cout <<... expression. Shouldn't I be able to use a variable of the type non_blank anywhere I would use a std::string? Isn't it the purpose of the cast/conversion operator?? answer
Why can't I access the private variable string::data_ directly in the definition of the operator >>?
Here is the error I got:
..\main.cpp: In function `std::istream& operator>>(std::istream&, non_blank&)':
..\main.cpp:21: error: invalid use of non-static data member `non_blank::data_'
..\main.cpp:26: error: from this location
Shouldn't I be able to use a variable
of the type non_blank anywhere I would
use a std::string? Isn't it the
porpuse of the cast operator?
Not quite. If the compiler sees you doing something that it knows requires a std::string, it can call your conversion operator to get one. But in the case of the ostream operator <<, it doesn't have a single specific function to call, but rather quite a lot of them, all different and none matching precisely the actual type you mean to print. So it lists a whole bunch of candidates, none of which is a strong enough match. You need to define an ostream operator << for your type in order to make it print as it should.
As for your operator >>, you should make it not be a member of your class. Declare it as a friend within the class declaration if you must, but write the function itself outside.