regarding streams in c++ - c++

I want to use file streams and consol output stream. In constructor, I want to initialize with either file or consol output stream depending on parameter passed to constructor. Then I will have another function in class which will redirect output to that stream. what will be the code for it? I am trying with the below code which is not working.
Any other design suggestions are welcome.
class Test
{
private:
std::ios *obj;
std::ofstream file;
std::ostream cout1;
public:
// Test(){}
Test(char choice[])
{
if(choice=="file")
{
obj=new ofstream();
obj->open("temp.txt");
}
else
obj=new ostream();
}
void printarray()
{
for(int i=0;i<5;i++)
(*obj)<<"\n \n"<<"HI"
}
};

Something like this should work:
#include <iostream>
#include <fstream>
#include <string>
class Test
{
private:
std::ofstream file;
std::ostream& obj;
public:
// Use overloaded constructors. When the default constructor is used,
// use std::cout. When the constructor with string is used, use the argument
// as the file to write to.
Test() : obj(std::cout) {}
Test(std::string const& f) : file(f.c_str()), obj(file) {}
void printarray()
{
for(int i=0;i<5;i++)
obj<<"\n " << "HI" << " \n";
}
};
int main()
{
Test a;
a.printarray();
Test b("out.txt");
b.printarray();
}
PS Look at the changes to printarray. What you were trying, with %s, is good for the printf family of functions but not for std::ostream.

Any other design suggestions are welcome.
Two of these members are useless:
std::ios *obj;
std::ofstream file;
std::ostream cout1;
You can't do anything with a std::ios, a std::ostream that isn't associated with a streambuf is useless, and you never use file or cout1 anyway!
You want:
std::ofstream file;
std::ostream& out;
as shown in R Sahu's answer, and write to out.
Test(char choice[])
{
if(choice=="file")
This doesn't work, you need to use strcmp to compare char strings. You should probably use std::string not char*.

Related

c++: Storing ostream in a List

I have a function
foo(ostream& os)
which writes to the ostream passed to it.
I now want to write a test and therefore would like to store whatever is written by foo into a list.
What is a clean way of doing this?
Populate the list with a std::ostringstream instance:
#include <sstream>
#include <cassert>
void foo(std::ostream& out) { out << "test1"; } // example implementation
void test_foo()
{
std::ostringstream buffer;
foo(buffer);
assert(buffer.str() == "test1");
}

Make a wrapper for cout?

So here's an interesting question, How would I make something kinda like a wrapper for cout?
I want to be able to add it into a dll so I can throw it into my programs. but the basic syntax of it should be
Mything::mesage << "I'm some text" << im_an_int << someclass << mything::endl;
or
Mything::mesageandlog << "I'm going to print to console, and to a file!" << mything::endl;
I can handle most of the internal logic but as to what I should put to even do this. kinda stumped.
Possibly make a static stream member in my class called message, then have an event fire when its written too that runs it through a method?
Idk, I looked around and found something sortA similar, but as for throwing it into a dll I'm at a loss. (How to write a function wrapper for cout that allows for expressive syntax?)
because this requires me to use extern and a variable, but how would I make it static so I can just straight call it without creating a variable?
Bit of clarification, something like this:
mydll.h
#include <iostream>
namespace mynamespace {
extern struct LogMessage{};
template <typename T>
LogMessage& operator<< (LogMessage &s, const T &x) {
SetStdHandle(STD_OUTPUT_HANDLE, GetStdHandle(STD_OUTPUT_HANDLE));
SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE),FOREGROUND_BLUE);
std::cout << "[IF] ";
SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE),FOREGROUND_WHITE);
//LogTimestamp(); --ill impliment this.
std::cout << x << endl;
//writeStreamToLogfile(s); --and ill handle this.
return s;
}
}
driverprogram.h
#include <mydll.h>
#include <iostream>
int _tmain(int argc, _TCHAR* argv[])
{
mynamespace::LogMessage << "Something: << std::endl;
}
expected output:
"[IF] [00:00:00] Something
You can create a struct, that has a << operator
struct OutputThing
{
template< class T >
OutputThing &operator<<( T val )
{
std::cout<<val;
return *this;
}
};
Now whenever you want to log, you will have to instance the object.
OutputThing()<<"x ="<<x;
If you want to avoid the repeated construction and destruction of the object, you can make it a singleton.
struct OutputThingSingleton
{
static OutputThingSingleton& GetThing()
{
static OutputThingSingleton OutputThing;
return OutputThing;
}
template< class T >
OutputThingSingleton &operator<<( T val )
{
std::cout<<val;
return *this;
}
private:
OutputThingSingleton()
{};
};
So the call now looks like
OutputThingSingleton::GetThing()<<"x ="<<x;
Which you could shorten using a macro.
This will work across multiple dlls, however depending on how it is used you can have multiple instances of the singleton existing. This would work fine as long as you don't want to maintain any state in your singleton. If you do need to ensure a single instance, you can compile it in its own dll. Any other binary that uses this dll will share the single instance 'owned' by the dll.
First of all, just to give fair warning, I'm pretty sure this won't work in a DLL. You want to put it into a header (as it's shown here).
Second, it's probably a little more elaborate than you were considering. In particular, it defines a multi-output stream class that works like any other stream. Essentially any normal overload of operator<< should work fine with it.
Unlike a normal stream operator, however, the output goes to multiple streams, and each line of output (on all the streams) is preceded by a prefix (currently set to the value "[FIX]", but it just uses the content of a string, so whatever you put in that string should work. A more polished/finished implementation would probably allow you to set the prefix with something like a manipulator, but this (currently) doesn't support that.
Finally, it does some variadic template trickery, so you can specify the output files as either file names or existing ostream objects, or a combination thereof (e.g., see demo main at end).
First, the header:
#ifndef LOGGER_H_INC_
#define LOGGER_H_INC_
#include <iostream>
#include <streambuf>
#include <vector>
#include <fstream>
class logger: public std::streambuf {
public:
logger(std::streambuf* s): sbuf(s) {}
~logger() { overflow('\n'); }
private:
typedef std::basic_string<char_type> string;
int_type overflow(int_type c) {
if (traits_type::eq_int_type(traits_type::eof(), c))
return traits_type::not_eof(c);
switch (c) {
case '\n':
case '\r': {
prefix = "[FIX]";
buffer += c;
if (buffer.size() > 1)
sbuf->sputn(prefix.c_str(), prefix.size());
int_type rc = sbuf->sputn(buffer.c_str(), buffer.size());
buffer.clear();
return rc;
}
default:
buffer += c;
return c;
}
}
std::string prefix;
std::streambuf* sbuf;
string buffer;
};
namespace multi {
class buf : public std::streambuf {
std::vector<std::streambuf *> buffers;
public:
typedef std::char_traits<char> traits_type;
typedef traits_type::int_type int_type;
buf() {}
void attach(std::streambuf *s) { buffers.push_back(s); }
void attach(std::ofstream &s) { buffers.push_back(s.rdbuf()); }
int_type overflow(int_type c) {
bool eof = false;
for (std::streambuf *buf : buffers)
eof |= (buf->sputc(c) == traits_type::eof());
return eof ? traits_type::eof() : c;
}
};
class logstream : public std::ostream {
std::vector<std::ofstream *> streams;
buf outputs;
logger log;
void attach(std::ostream &s) { outputs.attach(s.rdbuf()); }
void attach(char const *name) {
std::ofstream *s = new std::ofstream(name);
streams.push_back(s);
outputs.attach(s->rdbuf());
}
template <typename T, typename...pack>
void attach(T &t, pack&...p) {
attach(t);
attach(p...);
}
public:
template <typename...pack>
logstream(pack&...p) : log(&outputs), std::ostream(&log) { attach(p...); }
~logstream() {
for (auto d : streams) {
d->close();
// Bug: crashes with g++ if delete is allowed to execute.
//delete d;
}
}
};
}
#endif
Then the demo of how to use it:
#include "logger"
int main(){
multi::logstream l(std::cout, "c:/path/log.txt");
l << "This is a prefixed string\n";
}
Obviously the header is fairly large, but the code to use it seems (at least to me) about as simple as you can hope for -- create an object, specifying where you want the output to go, just a normal stream -- except that you can specify more than one. Then write to it like you would to any other stream, and the output goes to all of the specified outputs, with each line preceded by the specified prefix.

How to include a declaration in the comma operator?

I have two simple testing lines:
cout<<(cout<<"ok"<<endl, 8)<<endl;
cout<<(int i(8), 8)<<endl;
The first line worked, but the second failed compilation with
error: expected primary-expression before 'int'
For some reason, I do need a declaration in the comma operator. To be more specific, I want to declare some variables, obtain their values, and assign them to my constant class members from the initialization list of my class constructor. Following shows my intentions. If not achievable using comma operator, any another suggestions?
#include <iostream>
#include <fstream>
#include <string>
#include <sstream>
#include <cstdlib>
using namespace std;
void readFile(const string & fileName, int & a, int & b)
{
fstream fin(fileName.c_str());
if (!fin.good()) {cerr<<"file not found!"<<endl; exit(1);}
string line;
getline(fin, line);
stringstream ss(line);
try {ss>>a>>b;}
catch (...) {cerr<<"the first two entries in file "<<fileName<<" have to be numbers!"<<endl; exit(1);}
fin.close();
}
class A
{
private:
const int _a;
const int _b;
public:
A(const string & fileName)
:
_a((int a, int b, readFile(fileName,a,b), a)),
_b((int a, int b, readFile(fileName,a,b), b))
{
/*
int a, b;
readFile(fileName,a,b);
_a = a;_b = b;
*/
}
void show(){cout<<_a<<" "<<_b<<endl;}
};
int main()
{
A a("a.txt");
a.show();
}
Declarations are statements and not expressions. You cannot place statements inside of expressions, though you can place expressions inside of statements. Accordingly, you cannot declare a variable in the way that you're describing above. You'll need to separate it out into multiple different statements.
I would be surprised if if you actually needed to do this. If you do, there is probably something problematic about your design.
Hope this helps!
You should have a look at Boost Phoenix (which has phoenix::let to do roughly this). Bear in mind, Phoenix is an eDSL, really (embedded domain specific language).
You could do an ugly trick and abuse lambdas:
cout<< ([]->int{ int i(8); return 8; })() <<endl;
A lambda allows a declaration within an expression. So this is possible:
std::cout << ([]{ int i(8); m_i = i; }(), 8) << std::endl;
But it's really weird - I assume this will be in some #define macro that makes it appear closer to normal.
You cannot. This is unpossible in C++. The fact that you are trying to do this is also a code smell. Something's not right here.
I want to declare some variables, obtain their values, and assign them
to my constant class members from the initialization list of my class
constructor. Not sure how to achieve this.
You didn't say what you intended to do with these variables you declare after you've used the values, but I'm guessing that once you've finished with the values, you've finished with the variables. In other words, they are temporary.
Your edited example suggests that my assumption is correct. It also confirms the code smell. Based on your (intended) code, you are going to read the file twice.
I'd say the most straightforward way to do this is to use an intermediary, kind of like a factory class. This also has the benefit of being able to read the file only once, as opposed to twice as you are doing now.
void readFile (const std::string& fileName, int& a, int& b)
{
// some magic
a = 42;
b = 314;
}
class FileReader
{
public:
FileReader (const std::string fileName)
:
mFileName (fileName),
mA (42),
mB (314)
{
// something happens like reading the file
}
int GetA () const
{
return mA;
}
int GetB () const
{
return mB;
}
private:
int mA;
int mB;
std::string mFileName;
};
class A
{
private:
const int mA;
const int mB;
public:
A (const FileReader& reader)
:
mA (reader.GetA()),
mB (reader.GetB())
{
}
};
Using this FileReader is simple:
int main()
{
A myA (FileReader ("somefile.txt"));
}

Proper way to create ostream to file or cout

I am trying to create a Log class for my project at school. It needs to either be able to write information to the stdout or to a file depending on the parameters it is passed. I was looking into how to do this and I stumbled upon a thread with a similar question here: Obtain a std::ostream either from std::cout or std::ofstream(file)
The only difference between this thread and my own is that I want to do it inside of a class. Looking at the solution though they use std::ostream out(buf) and construct the ostream on the fly with buf. How can i declare this properly in my Log class to be able to construct the "out" object only once i enter my Log constructor?
I took a quick stab at it below but I am not sure if it is correct or if I am on the right track. Appreciate any help, thanks.
EDIT: I want to be able to do out << "Some string" << endl; after i get this Log class working properly.
EDIT2: An error I am now receiving with the new code below error : 'std::basic_ostream<_CharT, _Traits>::basic_ostream() [with _CharT = char, _Traits = std::char_traits<char>]' is protected
// log.h
#include <string>
#include <fstream>
#ifndef LOG_H_
#define LOG_H_
class Log
{
public:
enum Mode { STDOUT, FILE };
// Needed by default
Log(const char *file = NULL);
~Log();
// Writing methods
void write(char *);
void write(std::string);
private:
Mode mode;
std::streambuf *buf;
std::ofstream of;
std::ostream out;
};
#endif
// log.cpp
#include "log.h"
#include <iostream>
#include <stdlib.h>
#include <time.h>
Log::Log(const char *file)
{
if (file != NULL)
{
of.open(file);
buf = of.rdbuf();
mode = FILE;
}
else
{
buf = std::cout.rdbuf();
mode = STDOUT;
}
// Attach to out
out.rdbuf(buf);
}
Log::~Log()
{
if (mode == FILE)
of.close();
}
void Log::write(std::string s)
{
out << s << std::endl;
}
void Log::write(char *s)
{
out << s << std::endl;
}
You create tmp with std::ostream tmp(buf); and store the address of it in out with this->out = &tmp;. However, tmp will go out of scope at the end of the constructor and the pointer will no longer be pointing at a valid object.
What you should do instead is make out not a std::ostream* but simply a std::ostream:
std::ostream out;
Then in your constructor, once you've got the buf ready, you can give it to out by doing out.rdbuf(buf);.
Response to edit:
The std::ostream doesn't have a default constructor - it has to take a buffer pointer. My mistake. However, the fix is simple. Use your constructor's member initialization list to pass a null pointer (nullptr in C++11, 0 or NULL in C++03):
Log::Log(const char *file)
: out(nullptr)
{
// ...
}

How do I change a C++ output stream to refer to cout?

I have a class that I want to give an output stream as a member to, to wit:
class GameBase {
protected:
ofstream m_OutputWriter;
...
}
There is a method in this class that takes a string argument and opens m_OutputWriter to point to that file, so data may be output to that file by using the standard << operator;
However, what I would like is to make the stream point to cout by default, so that if the output path is not specified, output goes to the console output instead of to a file, and it will be completely transparent by the calling class, who would use
m_OutputWriter << data << endl;
to output the data to the predetermined destination. Yet, I have tried a couple of the other examples here, and none of them exactly seem to fit what I'm trying to do.
What am I missing here?
Why does the stream need to be a member?
struct GameBase {
void out(std::ostream& out = std::cout);
// ...
};
In addition to having an std::ofstream as a member, I would use a function that returns an std::ostream&.
For example:
class GameBase {
std::ofstream m_OutputWriter;
protected:
std::ostream& getOutputWriter() {
if (m_OutputWriter)
return m_OutputWriter;
else
return std::cout;
}
...
}
A fully-functioning example:
#include <iostream>
#include <ostream>
std::ostream& get() {
return std::cout;
}
int main() {
get() << "Hello world!\n";
}