In case of buffered stream it said in a book that it wait until the buffer is full to write back to the monitor. For example:
cout << "hi";
What do they mean by "the buffer is full".
cerr << "hi";
It is said in my book that everything sent to cerr
is written to the standard error device immediately, what does it mean?
char *ch;
cin>> ch; // I typed "hello world";
In this example ch
will be assigned to "hello" and "world" will be ignored does it mean that it still in the buffer and it will affect the results of future statements?
Your book doesn't seem very helpful.
1) The output streams send their bytes to a std::streambuf
, which may
contain a buffer; the std::filebuf
(derived from streambuf
) used by
and std::ofstream
will generally be buffered. That means that when
you output a character, it isn't necessarily output immediately; it will
be written to a buffer, and output to the OS only when the buffer is
full, or you explicitly request it in some way, generally by calling
flush()
on the stream (directly, or indirectly, by using std::endl
).
This can vary, however; output to std::cout
is synchronized with
stdout
, and most implementations will more or less follow the rules of
stdout
for std::cout
, changing the buffering strategy if the output
is going to an interactive device.
At any rate, if you're unsure, and you want to be sure that the output really does leave your program, just add a call to flush.
2) Your book is wrong here.
One of the buffering strategies is unitbuf
; this is a flag in the
std::ostream
which you can set or reset (std::ios_base::set()
and
std::ios_base::unset()
—std::ios_base
is a base class of
std::ostream
, so you can call these functions on an std::ostream
object). When unitbuf
is set, std::ostream
adds a call to flush()
to the end of every output function, so when you write:
std::cerr << "hello, world";
the stream will be flushed after all of the characters in the string
are output, provided unitbuf
is set. On start-up, unitbuf
is set
for std::cerr
; by default, it is not set on any other file. But you
are free to set or unset it as you wish. I would recommend against
unsetting it on std::cerr
, but if std::cout
is outputting to an
interactive device, it makes a lot of sense to set it there.
Note that all that is in question here is the buffer in the streambuf
.
Typically, the OS also buffers. All flushing the buffer does is
transfer the characters to the OS; this fact means that you cannot use
ofstream
directly when transactional integrity is required.
3) When you input to a string or a character buffer using >>
, the
std::istream
first skips leading white space, and then inputs up to
but not including the next white space. In the formal terms of the
standard, it "extracts" the characters from the stream, so that they
will not be seen again (unless you seek, if the stream supports it).
The next input will pickup where ever the previous left off. Whether
the following characters are in a buffer, or still on disk, is really
irrelevant.
Note that the buffering of input is somewhat complex, in that it occurs at several different levels, and at the OS level, it takes different forms depending on the device. Typically, the OS will buffer a file by sectors, often reading several sectors in advance. The OS will always return as many characters as were demanded, unless it encounters end of file. Most OSs will buffer a keyboard by line: not returning from a read request until a complete line has been entered, and never returning characters beyond the end of the current line in a read request.
In the same manner as std::ostream
uses a streambuf
for output,
std::istream
uses one to get each individual character. In the case
of std::cin
, it will normally be a filebuf
; when the istream
requests a character, the filebuf
will return one from its buffer if
it has one; if it doesn't, it will attempt to refill the buffer,
requesting e.g. 512 (or whatever its buffer size is) characters from the
OS. Which will respond according to its buffering policy for the
device, as described above.
At any rate, if std::cin
is connected to the keyboard, and you've
typed "hello world"
, all of the characters you've typed will be read
by the stream eventually. (But if you're using >>
, there'll be a lot
of whitespace that you won't see.)
streams in C++ are buffer to increase efficiency, that is file and console IO is very slow in comparison to memory operations.
To combat this C++ streams have a buffer (a bank of memory) that contains everything to write to the file or output, when it is full then it flushed to the file. The inverse is true for input, it fetches more when it the buffer is depleted.
This is very import for streams because the following
std::cout << 1 << "hello" << ' ' << "world\n";
Would be 4 writes to a file which is inefficient.
However in the case of std::cout, cin, and cerr then these type actually have buffering turned off by default to ensure that it can be used in conjunction with std::printf and std::puts etc...
To re-enable it (which I recommend doing):
std::ios_base::sync_with_stdio(false);
But don't use C style console output whilst it is set false or bad things may happen.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With