Basic question on streams

J

John Simeon

I understand that to creat a file output stream for example, I have to
include <fstream> and then:

ofstream fout;

which will create an object of type ofstream that I can use to interact with
a file.

My question concerns cout and cin. Clearly by intuition, these are also
objects? Is it possible to define an object of the same type of cin and cout
and use them similarly? What are those types and what would the definitions
to create those objects look like?

Thanks.
 
G

Gianni Mariani

John said:
I understand that to creat a file output stream for example, I have to
include <fstream> and then:

ofstream fout;

which will create an object of type ofstream that I can use to interact with
a file.

My question concerns cout and cin. Clearly by intuition, these are also
objects? Is it possible to define an object of the same type of cin and cout
and use them similarly? What are those types and what would the definitions
to create those objects look like?


Look up the class hierarchy for std::eek:stream. You'll see that ofstream
derives from ostream hence cout is interchangeable with your fout.
 
J

Jim Langston

John Simeon said:
I understand that to creat a file output stream for example, I have to
include <fstream> and then:

ofstream fout;

which will create an object of type ofstream that I can use to interact
with a file.

My question concerns cout and cin. Clearly by intuition, these are also
objects? Is it possible to define an object of the same type of cin and
cout and use them similarly? What are those types and what would the
definitions to create those objects look like?

The definition to create a cin or cout duplicate would be fairly complicated
because you have to talk to the console, however that is done on the OS
level. Like for windows I'd have to attach the console window, send the
output, etc...

However.

cin derives from istream, cout derives from ostream and can be used as such.

Here is a little sample toy program to illistrate how you can use std::cout
as a std::eek:stream:

#include <iostream>
#include <ostream>
#include <fstream>
#include <string>

void OutputRhyme( std::eek:stream& Output )
{
Output << "Mary had a little lamb\n"
"Its fleece was white as snow.\n"
"Every where that Mary went\n"
"The lamb was sure to go\n";
}

int main()
{
std::string Choice = "";
while ( Choice != "Q" )
{
while ( Choice != "F" && Choice != "S" && Choice != "Q" )
{
std::cout << "Output to <F>ile or <S>creen. <Q> to Quit: ";
std::getline( std::cin, Choice );
}

if ( Choice != "Q" )
{
if ( Choice == "F" )
{
std::eek:fstream File("Rhyme.txt");
OutputRhyme( File );
}
else
OutputRhyme( std::cout );
Choice = "";

}
}

}
 
R

Robert Bauck Hamar

Yes, they are. They are global objects.

The types: cin is an istream, and cout is an ostream. That's the easy part.
The definition to create a cin or cout duplicate would be fairly
complicated because you have to talk to the console, however that is done
on the OS level. Like for windows I'd have to attach the console window,
send the output, etc...

This is, however, not correct. cin should communicate with the standard
input, and cout with standard output. They are not necessarily connected
with the console. If we should constrain ourselves to not use cin and cout,
the only means of using standard input and standard output with only
standard methods, are the C stdio functions, and the stdin and stdout
objects, on which the standard specifies cin and cout operate. So if you
want to create similar objects, you could make them call the old functions
from <cstdio>.

So how do you do that? Well, it's not for beginners. First you'll have to
make a class derived from std::streambuf. How you do this are best
explained by a good book. At last, you have to create objects of this
class, and create istream and ostream objects with them.

Chances are, however, that your compiler already has such buffer classes. If
you are using the GNU compiler, you could check out this:

http://gcc.gnu.org/onlinedocs/libstdc++/documentation.html

Specifically, g++ has an extension: __gnu_cxx::stdio_filebuf is a class for
sending output to/reading input from FILE* files.
 
J

John Simeon

I take it your statement on the task "not being for beginners" is in
reference to creating a cout or cin look-alike from scratch.

I however would merely like to declare a type of the same opject and use it
that way.

Would this be appropriate then:

ostream Output;

Output << "Hello World!"
 
J

John Simeon

Wait, are you basically saying that ofstream inherits from ostream and that,
therefore, it should be possible to output to the screen with fout?

How would I do that if so?
 
B

BobR

John Simeon said:
I take it your statement on the task "not being for beginners" is in
reference to creating a cout or cin look-alike from scratch.

I however would merely like to declare a type of the same opject and use it
that way.

Would this be appropriate then:

ostream Output;

Output << "Hello World!"

That depends on how you declared/defined 'ostream'. Did you define
'operator<<()'?

Please do not top-post.

Why not just use the standard libraries:

#include <iostream>
#include <sstream>
#include <string>
std::eek:stringstream Output;

void MyFunc(){
Output << " In MyFunc()!";
return;
}

int main(){
Output << "Hello World!";
// ......
std::cout<< Output.str() <<std::endl;
Output.clear(); Output.str("");
Output << " How are you?";
MyFunc();
std::string TheOutput( Output.str() );
std::cout<< TheOutput <<std::endl;
// ......
std::cout<< Output.str() <<std::endl;
return 0;
} // main()
 
G

Gianni Mariani

John said:
Wait, are you basically saying that ofstream inherits from ostream and that,
therefore, it should be possible to output to the screen with fout?

How would I do that if so?

Open the screen "file".

That is platform specific.

If you want to create your own ostream type that writes to a file and
the screen, you can do that too.

G
 
R

Robert Bauck Hamar

John Simeon wrote:

Please stop top posting. Learn how to quote properly.
I take it your statement on the task "not being for beginners" is in
reference to creating a cout or cin look-alike from scratch.

Sort of. You don't have to write from scratch. All you have to do is to
write your own buffer class. It should be a subclass of std::streambuf,
which declares some virtual functions for you. Basically, you will have to
make these functions actually output to some location.
I however would merely like to declare a type of the same opject and use
it that way.

Well, then cin _is_ a std::istream, and cout _is_ a std::eek:stream. They are
written, and work well. However, both classes needs a buffer object to
actiually make output.
Would this be appropriate then:

ostream Output;

If you tried it, you would have found that this doesn't compile (unless your
compiler has some extensions). The standard only specifies one constructor
for std::eek:stream: It takes a pointer to a std::streambuf object. But the
standard specifies no subclass of std::streambuf that can send stuff to
stdout or read from stdin.
 
R

Robert Bauck Hamar

John said:
Wait, are you basically saying that ofstream inherits from ostream and
that, therefore, it should be possible to output to the screen with fout?

No, he's saying that a std::eek:stream and a std::eek:fstream has the same
functions for output, and a std::eek:fstream can be used in situations where a
std::eek:stream is expected.
How would I do that if so?

Your first problem is: define screen. C++ has no concept of screens. C++
guarantees that there exists a standard out, but does not say where it ends
and how. On many computers, the screen is a buffer in memory, and writing
to special addresses will make characters appear on the screen. On other
systems, the screen can only be reached with special system calls. How it
works on your system, however is not the topic of this group. But here is
something that works on my system:

std::eek:fstream out("/dev/stdout");
out << "Hello, world\n";

This works on UNIX systems, where /dev/stdout is a special file. I don't
know if it works, but somethings tell me that the special file name CON has
similar meanings on WinDOS.
 
J

Jim Langston

Robert Bauck Hamar said:
No, he's saying that a std::eek:stream and a std::eek:fstream has the same
functions for output, and a std::eek:fstream can be used in situations where
a
std::eek:stream is expected.


Your first problem is: define screen. C++ has no concept of screens. C++
guarantees that there exists a standard out, but does not say where it
ends
and how. On many computers, the screen is a buffer in memory, and writing
to special addresses will make characters appear on the screen. On other
systems, the screen can only be reached with special system calls. How it
works on your system, however is not the topic of this group. But here is
something that works on my system:

std::eek:fstream out("/dev/stdout");
out << "Hello, world\n";

This works on UNIX systems, where /dev/stdout is a special file. I don't
know if it works, but somethings tell me that the special file name CON
has
similar meanings on WinDOS.

It's actually CON: The following program outputs:

Did it work?
Testing

#include <iostream>
#include <fstream>
#include <string>

int main()
{
std::eek:fstream Console("CON:");
Console << "Testing\n";
std::cout << "Did it work?\n";

return 0;
}

One would expect
Testing
Did it work?
but that's not what was output.
 
J

James Kanze

No, he's saying that a std::eek:stream and a std::eek:fstream has the same
functions for output, and a std::eek:fstream can be used in situations where a
std::eek:stream is expected.


Your first problem is: define screen. C++ has no concept of screens. C++
guarantees that there exists a standard out, but does not say where it ends
and how. On many computers, the screen is a buffer in memory, and writing
to special addresses will make characters appear on the screen. On other
systems, the screen can only be reached with special system calls. How it
works on your system, however is not the topic of this group. But here is
something that works on my system:

std::eek:fstream out("/dev/stdout");
out << "Hello, world\n";

This works on UNIX systems, where /dev/stdout is a special file. I don't
know if it works, but somethings tell me that the special file name CON has
similar meanings on WinDOS.
 
J

James Kanze

No, he's saying that a std::eek:stream and a std::eek:fstream has
the same functions for output, and a std::eek:fstream can be used
in situations where a std::eek:stream is expected.

More generally, except when actually opening or closing the
file, you should use std::eek:stream&, and not std::eek:fstream&.
Your first problem is: define screen. C++ has no concept of screens. C++
guarantees that there exists a standard out, but does not say where it ends
and how. On many computers, the screen is a buffer in memory, and writing
to special addresses will make characters appear on the screen. On other
systems, the screen can only be reached with special system calls. How it
works on your system, however is not the topic of this group. But here is
something that works on my system:
std::eek:fstream out("/dev/stdout");
out << "Hello, world\n";

That's not standard Unix (which only requires "/dev/tty",
"/dev/null" and "/dev/console"), just a common extension. And
even on systems where it's implemented (e.g. Solaris or Linux),
it doesn't write to the screen; it writes to where ever standard
out happens to be redirected.

In general, to write to the screen, you need to use the X
Windows interfaces. "/dev/tty" will output to the terminal
window your process is connected to, IF it is connected to a
terminal window, and "/dev/console" will output to the console
window(s), if there are any.
This works on UNIX systems, where /dev/stdout is a special file. I don't
know if it works, but somethings tell me that the special file name CON has
similar meanings on WinDOS.

I'm not sure about the name, but there is something similar to
"/dev/tty" under Windows, I think.
 
J

James Kanze

The definition to create a cin or cout duplicate would be
fairly complicated because you have to talk to the console,
however that is done on the OS level.

Not at all.

First, of course, cout doesn't necessarily go to the console.
In fact, in most application software, it doesn't go to the
console: if the software is interactive, it uses a GUI, and if
it isn't, it runs disconnected from any terminal window. (I
might also point out that the word "console" is ambiguous, since
it means different things under Windows and Unix.)

And it's very, very easy to create an ostream which goes to the
same place as cout:

std::eek:stream dest( std::cout.rdbuf() ) ;

Not really very useful, IMHO, but not difficult.
 
G

gerry2000

Not at all.

First, of course, cout doesn't necessarily go to the console.
In fact, in most application software, it doesn't go to the
console: if the software is interactive, it uses a GUI, and if
it isn't, it runs disconnected from any terminal window. (I
might also point out that the word "console" is ambiguous, since
it means different things under Windows and Unix.)

And it's very, very easy to create an ostream which goes to the
same place as cout:

std::eek:stream dest( std::cout.rdbuf() ) ;

Not really very useful, IMHO, but not difficult.

--
James Kanze (GABI Software) email:[email protected]
Conseils en informatique orientée objet/
Beratung in objektorientierter Datenverarbeitung
9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34

==================================================================
class OutPut : public streambuf, public ostream
{
private:
ofstream m_ofs;
ofstream m_ofs_error;
ofstream m_ofs_warnning;
public:
// define some other operations

}
 
J

James Kanze

On 7 23 , 4 52 , James Kanze <[email protected]> wrote:
class OutPut : public streambuf, public ostream
{
private:
ofstream m_ofs;
ofstream m_ofs_error;
ofstream m_ofs_warnning;
public:
// define some other operations
}

And that should do what?

If you want to be able to configure the class so that e.g.
m_ofs_error goes to standard out, the simplest way is to make it
a pointer to an ostream. (Typically, of course, logging/tracing
is a lot more complicated than that, and the "streams" being
written to will be using filtering streambuf's, which insert
timestamps, handle "records", etc., and are addressed through
wrapper classes which handle things like synchronization,
flushing, etc. And of course, in some cases, you might
configure one of the filtering streambuf's to forward to the
streambuf of cout or cerr.)
 
M

Marcus Kwok

Jim Langston said:
It's actually CON: The following program outputs:

Did it work?
Testing

#include <iostream>
#include <fstream>
#include <string>

int main()
{
std::eek:fstream Console("CON:");
Console << "Testing\n";

Console << "Testing" << std::endl;

or

Console << "Testing\n" << std::flush;

or

Console << "Testing\n";
Console.flush();
std::cout << "Did it work?\n";

return 0;
}

One would expect
Testing
Did it work?
but that's not what was output.

If you flush the Console stream, then it works as you expect.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,769
Messages
2,569,581
Members
45,057
Latest member
KetoBeezACVGummies

Latest Threads

Top