Topic: istream::sync()
Author: dietmar_kuehl@yahoo.com (Dietmar Kuehl)
Date: Sat, 14 Aug 2004 19:13:51 GMT Raw View
Francis Glassborow wrote:
> I am not asking for kbhit() or any version of that. I think I am asking
> for something very simple and apparently something that Bjarne
> Stroustrup thinks already exists (see page 643 et seq. of TC++PL 3ed).
I apparently got confused by your references to blocking. For the
description of the problem you have given in this article, at least
how I have understood it, there is indeed a solution. Well, at least
if it is acceptable to skip whitespace characters.
> Furthermore I cannot see any reason for it not being available other
> than the possibility that some people just think that programmers should
> be made to suffer.
Are you referring to 'kbhit()' or to a solution to your problem which
should be available?
> Consider:
>
> int main(){
> try {
> do{
> foo();
> std::cout << "Another?";
> // what goes here
> while(std::cin.get() != 'n');
> }
> catch(...){std::cerr << "something went wrong.\n"; }
> }
> I know this is overly simple but it does illustrate the problem.
Does the code below solve the problem?
#include <iostream>
#include <string>
#include <limits>
void foo()
{
static int i = 0;
std::string str;
std::cout << "string: ";
if (++i % 2)
std::cin >> str;
else
std::getline(std::cin, str);
}
std::istream& ignore(std::istream& in)
{
return in.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
}
int main(){
try {
do{
foo();
std::cout << "Another?";
std::cin >> std::ws;
}
while(std::cin.get() != 'n' && std::cin >> ignore);
}
catch(...){std::cerr << "something went wrong.\n"; }
}
What is going on is actually quite simple: when applying 'std::ws' to
an 'std::istream', it removes all whitespaces and stops on the first
non-whitespace. That is, if there is still a newline sticking in the
stream, it is extracted. However, any leading whitespace like additional
newlines, leading spaces, etc. are also extracted. The net effect is
that prior to the call to 'get()', the stream is on the non-space
character on the new line.
Ignoring the newline character after entering something different than
'n' is necessary because 'std::getline()' does not skip leading
whitespace. Since there is a newline guaranteed to be sticking there,
'std::getline()' would only read up to this newline. Thus, it is
necessary to extract this newline. The formatted input function
automatically skips leading spaces but ignoring the newline right away
is not harmful.
Now back to the state after falling the function 'foo()': If you also
want to handle space characters, the consistent state is achieved
differently, namely using the ugly 'putback()' hack I mentioned before.
That is, you would the replace the use of 'std::ws' by:
if (!std::cin.putback('\n'))
std::cin.clear();
std::cin >> ignore;
The idea is that there is at least a one character buffer if
'underflow()' does not fail. Thus, 'putback()' can check whether
the last character extracted was '\n'. If it was, the '\n' is back
in the stream and if it wasn't, nothing happened except that the
error flags are set and need clearing. Afterwards, the '\n'
character is consistently extracted again.
This still does not handle the case if someone hits return immediately
when being asked for "Another?" This case can be handled by comparing
the result of the 'get()' function against both 'n' and '\n':
int c = 0
do {
// ...
}
while((c = std::cin.get()) != 'n'
&& (c == '\n' || std::cin >> ignore));
As far as I have understood your problem, this should solve it. I
have tested it with gcc-3.3.1 on a linux machine using both libstc++
and my own implementation. I haven't tested it on other machines
although I don't see a reason why it should not work there.
> Just because you never write programs that have this kind of problem is
> no reason to dismiss it as a non-problem.
I do not dismiss it as a non-problem. I described what problem I understood
and discussed why I either don't think it is a problem or why I doubt that
we will ever get a solution in C++ (the letter referring to some form of
'kbhit()'). Actually, I think I also posted a solution to the problem.
> Note that even as an expert
> library programmer you cannot see any good reason for in_avail() to
> return 0 even when there is data waiting for processing and yet it does.
I tried the g++ implementation and found that 'in_avail()' yields '0'
if entering a non-number for this program:
#include <iostream>
int main() {
int i = 0;
std::cin >> i;
std::cout << std::cin.rdbuf()->in_avail() << "\n";
}
I would have expected the library to buffer at least one character.
On a POSIX-system there are good reasons why 'in_avail()' yield '0'
while there is some data waiting on the line which is not yet terminated
by a newline.
> Note that in this case I am just a deeply frustrated user. Library
> design and implementation are not my thing. But why is it so hard to
> understand the problem and why so hard to fix it.
Concerning the understanding of the problem, I was definitely distracted
by your description. I hope I understood it this time. Without a clear
understanding of the problem it is hard to come up with a matching
solution. On the other hand, I think the filtering stream buffer I
posted before also solved the problem. Actually, it is probably a safer
approach than the 'putback()' hack.
--
<mailto:dietmar_kuehl@yahoo.com> <http://www.dietmar-kuehl.de/>
<http://www.contendix.com> - Software Development & Consulting
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html ]
Author: francis@robinton.demon.co.uk (Francis Glassborow)
Date: Sat, 14 Aug 2004 21:16:50 GMT Raw View
In article <2o5iinF77m9tU1@uni-berlin.de>, Dietmar Kuehl
<dietmar_kuehl@yahoo.com> writes
>Concerning the understanding of the problem, I was definitely distracted
>by your description. I hope I understood it this time. Without a clear
>understanding of the problem it is hard to come up with a matching
>solution. On the other hand, I think the filtering stream buffer I
>posted before also solved the problem. Actually, it is probably a safer
>approach than the 'putback()' hack.
Thanks for your time and patience. I will experiment a bit with your
solution to check that it can be adapted a little.
--
Francis Glassborow ACCU
Author of 'You Can Do It!' see http://www.spellen.org/youcandoit
For project ideas and contributions: http://www.spellen.org/youcandoit/projects
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html ]
Author: johnchx2@yahoo.com (johnchx)
Date: Wed, 11 Aug 2004 04:44:04 GMT Raw View
francis@robinton.demon.co.uk (Francis Glassborow) wrote
> <johnchx2@yahoo.com> writes
> >I don't see anything remotely like this behavior specified in the
> >standard. The istream's sync() calls the streambuf's pubsync() which
> >calls the streambuf's sync() which has the following Effects:
>
> Note that streambuf's sync is a virtual function.
>
Sure, which gives implementors of derived classes the flexibility to
do what's needed to achieve the specified effects, depending on the
peculiarities of the controlled sequence. I don't see the
virtual-ness as authorizing derived classes to do any random thing
they feel like. The function has a clearly documented contract.
> >
> >As far as I can see, the only sensible use for sync() is to flush
> >buffered output to a file, which is what I suspect it's really for.
> >
> >Which does raise one interesting question: why in the world does an
> >istream even have this member?
>
> An excellent question. However on the other side, what does sync do for
> an ostream that flush doesn't?
The plot thickens: basic_ostream::sync() doesn't seem to exist.
(basic_ostream::flush() is specified exactly the same way as
basic_istream::sync(), except for its return type.) So I'm evidently
wrong about the purpose of sync(). I've got no idea what it is
supposed to be for.
> >>
> >> It certainly works with MinGW but should it be portable?
> >>
> >
> >I may be missing something, but this sure sounds like a gnu extension
> >(assuming you're using libstdc++). It seems handy, and, as I said, I
> >don't see any real use for basic_istream::sync() as specified, so why
> >not replace it with something that does something sensible? But it
> >doesn't look portable.
>
> Well I would love to replace it with something sensible but
> unfortunately is_avail() is not required to return anything greater than
> zero and in several implementations of std.cin std.cin.is_avail() always
> returns zero. OTOH ignore() requires that there be at least one
> character to ignore.
I meant that it might be a good idea to replace the specified
semantics of sync() with the semantics you've observed in practice
since the specified semantics seem entirely useless.
> So when it comes down to the wire, all the mechanisms suggested by
> experts such as Dietmar fail whilst this one that externally offers no
> reasonable promise of success, does so. Theory and practice seem to be
> an ocean apart in a situation that makes the life of novices and casual
> programmers impossible.
Well, I think the real problem is that interactive console i/o really
isn't quite compatible with the stream abstraction. We can sort of
"simulate" interactive i/o, and, as you've seen, the simulation
doesn't pass close inspection.
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html ]
Author: sean@f4.ca (Sean Kelly)
Date: Wed, 11 Aug 2004 04:44:18 GMT Raw View
Francis Glassborow wrote:
> In article <4fb4137d.0408092144.16fcbe8c@posting.google.com>, johnchx
> <johnchx2@yahoo.com> writes
>>
>> Synchronizes the controlled sequences with the arrays. That is, if
>> pbase() is non-null the characters between pbase() and pptr() are
>> written to the controlled sequence. The pointers may then be
>> reset as appropriate.
>>
>> --27.5.2.4.2 p7
>>
>> As far as I can see, the only sensible use for sync() is to flush
>> buffered output to a file, which is what I suspect it's really for.
>>
>> Which does raise one interesting question: why in the world does an
>> istream even have this member?
>
> An excellent question. However on the other side, what does sync do for
> an ostream that flush doesn't?
Nothing, so far as I can tell. However sync() is only defined in
basic_istream while flush() is only defined in basic_ostream. I'm still
not sure why sync() wasn't used for both--perhaps to allow
basic_iostream to just inherit behavior from basic_istream and
basic_ostream without having to deal with multiply defined versions of
sync()?
> It surprised me to find that istream::sync() did, in effect, cancel all
> current input to std::cin (on all the compilers I have so far tried).
>
> So when it comes down to the wire, all the mechanisms suggested by
> experts such as Dietmar fail whilst this one that externally offers no
> reasonable promise of success, does so. Theory and practice seem to be
> an ocean apart in a situation that makes the life of novices and casual
> programmers impossible.
Indeed. The language describing basic_streambuf::sync() is sufficiently
vague that I don't think it provides any behavior gurantees for the
input buffer. "The pointers may then be reset as appropriate" seems to
imply that it's both legal to leave the input buffer alone and to toss
it out.
Sean
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html ]
Author: francis@robinton.demon.co.uk (Francis Glassborow)
Date: Wed, 11 Aug 2004 17:06:41 GMT Raw View
In article <4fb4137d.0408101701.52adad4c@posting.google.com>, johnchx
<johnchx2@yahoo.com> writes
>francis@robinton.demon.co.uk (Francis Glassborow) wrote
>> <johnchx2@yahoo.com> writes
>> >I don't see anything remotely like this behavior specified in the
>> >standard. The istream's sync() calls the streambuf's pubsync() which
>> >calls the streambuf's sync() which has the following Effects:
>>
>> Note that streambuf's sync is a virtual function.
>>
>
>Sure, which gives implementors of derived classes the flexibility to
>do what's needed to achieve the specified effects, depending on the
>peculiarities of the controlled sequence. I don't see the
>virtual-ness as authorizing derived classes to do any random thing
>they feel like. The function has a clearly documented contract.
It must be my advancing years because I have re-read the relevant parts
of the Standard as well as commentaries from such experts as Nico
Josuttis and Angelika Langer and I still do not understand what is
required rather than what is permitted.
>
>> >
>> >As far as I can see, the only sensible use for sync() is to flush
>> >buffered output to a file, which is what I suspect it's really for.
>> >
>> >Which does raise one interesting question: why in the world does an
>> >istream even have this member?
>>
>> An excellent question. However on the other side, what does sync do for
>> an ostream that flush doesn't?
>
>The plot thickens: basic_ostream::sync() doesn't seem to exist.
>(basic_ostream::flush() is specified exactly the same way as
>basic_istream::sync(), except for its return type.) So I'm evidently
>wrong about the purpose of sync(). I've got no idea what it is
>supposed to be for.
Good, we are coming to a degree of agreement. We have a function
istream::sync() that seems to be about as portable as volatile. I.e. the
syntax is well defined but the semantics are up in the air.
>
>> >>
>> >> It certainly works with MinGW but should it be portable?
>> >>
>> >
>> >I may be missing something, but this sure sounds like a gnu extension
>> >(assuming you're using libstdc++). It seems handy, and, as I said, I
>> >don't see any real use for basic_istream::sync() as specified, so why
>> >not replace it with something that does something sensible? But it
>> >doesn't look portable.
>>
>> Well I would love to replace it with something sensible but
>> unfortunately is_avail() is not required to return anything greater than
>> zero and in several implementations of std.cin std.cin.is_avail() always
>> returns zero. OTOH ignore() requires that there be at least one
>> character to ignore.
>
>I meant that it might be a good idea to replace the specified
>semantics of sync() with the semantics you've observed in practice
>since the specified semantics seem entirely useless.
Well at least let us tie down some guaranteed semantics.
>
>
>> So when it comes down to the wire, all the mechanisms suggested by
>> experts such as Dietmar fail whilst this one that externally offers no
>> reasonable promise of success, does so. Theory and practice seem to be
>> an ocean apart in a situation that makes the life of novices and casual
>> programmers impossible.
>
>Well, I think the real problem is that interactive console i/o really
>isn't quite compatible with the stream abstraction. We can sort of
>"simulate" interactive i/o, and, as you've seen, the simulation
>doesn't pass close inspection.
I think that is probably it. Perhaps we do really need a
'console_buffer' type that provides the specialised behaviour needed for
reliable and portable use of std::cin. Placing this at the buffer level
would allow us to handle redirection by changing to an appropriate
buffer type with correct semantics.
--
Francis Glassborow ACCU
Author of 'You Can Do It!' see http://www.spellen.org/youcandoit
For project ideas and contributions: http://www.spellen.org/youcandoit/projects
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html ]
Author: andy@servocomm.freeserve.co.uk (kwikius)
Date: Wed, 11 Aug 2004 21:35:49 GMT Raw View
francis@robinton.demon.co.uk (Francis Glassborow) wrote in message news:<7BXBu+BooHGBFw5H@robinton.demon.co.uk>...
> It surprised me to find that istream::sync() did, in effect, cancel all
> current input to std::cin (on all the compilers I have so far tried).
>
> So when it comes down to the wire, all the mechanisms suggested by
> experts such as Dietmar fail whilst this one that externally offers no
> reasonable promise of success, does so. Theory and practice seem to be
> an ocean apart in a situation that makes the life of novices and casual
> programmers impossible.
It is mentioned in C++ 3rd Ed. in 21.6.2. and what it says is pretty
unambiguous:
"Flushing an istream is done using sync(). This cannot always be done
right. For some kinds of streams, we would have to reread characters
from the real source - and that is not always possible or desirable.
Consequently, sync() returns 0 if it succeeded. If it failed it sets
ios_base::badbit and returns -1.
Setting badbit may trigger an exception."
and very useful it is too :-)
regards
Andy Little
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html ]
Author: dietmar_kuehl@yahoo.com (Dietmar Kuehl)
Date: Wed, 11 Aug 2004 21:36:35 GMT Raw View
Francis Glassborow wrote:
> It must be my advancing years because I have re-read the relevant parts
> of the Standard as well as commentaries from such experts as Nico
> Josuttis and Angelika Langer and I still do not understand what is
> required rather than what is permitted.
The requirement is pretty obvious: the put area has to be synchronized
with the external representation (this is what is typically referred to
as "flushing"). There may be effects to the get area but these remain
unspecified.
I don't think there are any restrictions what you can do in the member
function, nor are there any substantial restrictions what other
functions can do. Well, some functions are limited by their performance
characteristics although this is only related to the input size of the
respective function, i.e. it can still consume loads of time.
> We have a function
> istream::sync() that seems to be about as portable as volatile. I.e. the
> syntax is well defined but the semantics are up in the air.
The semantics of 'std::basic_isteram::sync()' are fairly tight and, IMO,
not ambiguous at all: if present, it calls 'pubsync()' on the stream
buffer and otherwise fails (27.6.1.4; there is no paragraph number in
the document I have). What might cause some confusion is the statement
concerning the number of extracted characters: this might indicate that
'sync()' might extract any characters. Actually, this is, IMO, not the
case: it extracts 0 characters and thus 'gcount()' is not updated.
The semantics of 'pubsync()' are also clearly specified (27.5.3.2.2
paragraph 4): it returns 'sync()', the one on the stream buffer in this
case. The semantics of 'std::basic_streambuf::sync()' are also clearly
described. The first sentence of 27.5.3.4.2 paragraph 8 (the effects
clause for 'sync()') reads: "Synchronizes the controlled sequences with
the arrays." This is kept fairly vague which in turn is a reasonable
approach as 'sync()' is a virtual function which is to be overridden.
The effects clause goes on describing what is supposed to happen with
the output buffer; it does not explicitly mention the input buffer
although use of the plural in the above quoted sentences seems to
indicate that the input sequence is also synchronized.
Now the big question becomes what "synchronization" of the sequences
actually refers to. For the output sequence it is described: essentially
the output sequence is flushed. Assuming that there is just one actor
operating on the underlying input sequence, namely the stream buffer,
there is obviously nothing to be done as the input sequence is clearly
in sync with itself. If there are more actors, it may e.g. become
necessary to update the internal buffer of the input sequence because
some external entity may have modified the content of the input
sequence. Another example is reflecting the current state of the
pointers in the get area of a filtering stream buffer (i.e. a stream
buffer which uses another stream buffer underneath):
struct filter: std::streambuf {
filter(std::streambuf* sbuf): m_sbuf(sbuf) {}
int underflow() {
typedef std::streambuf::traits_type traits;
int c = gptr() != eback()? m_sbuf->snextc(): m_sbuf->sgetc();
if (c != traits::eof())
{
m_buffer = traits::to_char_type(c);
setg(&m_buffer, &m_buffer, 1 + &m_buffer);
}
return gptr() != egptr()? c: traits::eof();
}
int sync() {
if (gptr() != eback())
m_sbuf->sbumpc();
setg(0, 0, 0);
return 0;
}
private:
std::streambuf* m_sbuf;
char m_buffer;
};
In the above example, 'underflow()' sets up a one character buffer. If
this character was consumed, e.g. by call of 'sbumpc()' on the 'filter'
object, this is not reflected in the underlying stream buffer 'm_sbuf'.
A call to 'sync()' corrects this problem, i.e. it brings the the stream
buffers array into synchronization with the controlled sequence.
"Synchronization" of the input sequence does, however, not mean that
'sync()' should go forth and extract the characters it considers unfit
from the sequence. If the controlled sequence has changed, e.g. because
another process has modified a file which is currently read by the
process calling 'sync()' on the corresponding stream buffer, it might
cause a change in the buffer to reflect such a change.
>>> Well I would love to replace it with something sensible but
>>> unfortunately is_avail() is not required to return anything greater than
>>> zero and in several implementations of std.cin std.cin.is_avail() always
>>> returns zero. OTOH ignore() requires that there be at least one
>>> character to ignore.
If there is no character, how did you determine that it is a "bad" one
which should be ignored? Put differently, in the setting you are
concerned with (fault tolerance of programs written by programmers new
to C++ or IOStreams) there always is at least one character, i.e. it
is safe to do something like this:
int i = 0;
while (!(std::cin >> i) && !std::cin.eof())
{
std::cin.clear();
std::cin.ignore();
}
if (std::cin)
std::cout << "number read: " << 10 << "\n";
else
std::cout << "hit EOF\n";
Actually, without further contracts on the file format, i.e. explicitly
known recovery points, this is as far as I would go with respect to
fault tolerance! If I'm dealing with some protocol where I know e.g. a
message size, it may be reasonable to read the whole message. ... or if
the protocol is line based it may be reasonable to abandon the current
line. However, 'std::basic_istream' or 'std::basic_streambuf' does not
know anything about such protocols!
BTW, using gcc-3.3.1 on my Linux machine and changing 'ignore' to 'sync'
causes the program to loop forever if I enter something which cannot be
parsed as an integer (as I would have expected).
> Perhaps we do really need a
> 'console_buffer' type that provides the specialised behaviour needed for
> reliable and portable use of std::cin. Placing this at the buffer level
> would allow us to handle redirection by changing to an appropriate
> buffer type with correct semantics.
I still don't see where anything new is necessary! Just process things
linewise as is recommended since ages anyway if you don't like the
characterwise recovery I have shown above. Since computer don't go
into deep meditation when parsing things, it is very unlikely that the
user had any chance to type even another single character after hitting
newline and being prompted for an error! The code could look like this:
int i = 0;
for (std::string line; std::getline(std::cin); )
{
std::istringstream in;
if (in >> i)
break;
}
..and if you insist that 'std::basic_istream::sync()' is the way to go,
wrap this up into a stream buffer and implement 'sync()' correspondingly:
struct console_buffer: std::streambuf {
int underflow() {
typedef std::streambuf::traits_type traits;
if (!std::getline(std::cin, m_line))
return traits::eof();
m_line.append("\n");
char* c_str = const_cast<char*>(m_line.c_str()); // (*)
setg(c_str, c_str, c_str + m_line.size());
return gptr() != egptr()? traits::to_int_type(*gptr()): traits::eof();
}
int sync() {
setg(0, 0, 0);
return 0;
}
private:
std::string m_line;
};
(*) This cast is, of course, quite ugly. However, I think it is
actually OK in this case although a "real" stream buffer might want
to copy the buffer just in case...
--
<mailto:dietmar_kuehl@yahoo.com> <http://www.dietmar-kuehl.de/>
<http://www.contendix.com> - Software Development & Consulting
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html ]
Author: francis@robinton.demon.co.uk (Francis Glassborow)
Date: Thu, 12 Aug 2004 05:30:43 GMT Raw View
In article <iUgSc.3344$rN7.301@newssvr27.news.prodigy.com>, Sean Kelly
<sean@f4.ca> writes
>> An excellent question. However on the other side, what does sync do
>>for an ostream that flush doesn't?
>
>Nothing, so far as I can tell. However sync() is only defined in
>basic_istream while flush() is only defined in basic_ostream. I'm
>still not sure why sync() wasn't used for both--perhaps to allow
>basic_iostream to just inherit behavior from basic_istream and
>basic_ostream without having to deal with multiply defined versions of
>sync()?
Possibly, but then we need to address what sync() is required to do.
Without required semantics it is useless in portable code. And while we
are about it I think we need to address is_avail() at least in the
context of console input from a source such as a keyboard or serial
port.
>
>> It surprised me to find that istream::sync() did, in effect, cancel
>>all current input to std::cin (on all the compilers I have so far
>>tried).
>> So when it comes down to the wire, all the mechanisms suggested by
>>experts such as Dietmar fail whilst this one that externally offers no
>>reasonable promise of success, does so. Theory and practice seem to be
>>an ocean apart in a situation that makes the life of novices and
>>casual programmers impossible.
>
>Indeed. The language describing basic_streambuf::sync() is
>sufficiently vague that I don't think it provides any behavior
>gurantees for the input buffer. "The pointers may then be reset as
>appropriate" seems to imply that it's both legal to leave the input
>buffer alone and to toss it out.
Good, so I am not alone in finding this part of the Standard unhelpful.
--
Francis Glassborow ACCU
Author of 'You Can Do It!' see http://www.spellen.org/youcandoit
For project ideas and contributions: http://www.spellen.org/youcandoit/projects
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html ]
Author: Francis Glassborow <francis@robinton.demon.co.uk>
Date: Thu, 12 Aug 2004 12:24:29 CST Raw View
In article <2873fa46.0408101802.12f98238@posting.google.com>, kwikius
<andy@servocomm.freeserve.co.uk> writes
>francis@robinton.demon.co.uk (Francis Glassborow) wrote in message news:<7BXBu+BooHGBFw5H@robinton.demon.co.uk>...
>
>> It surprised me to find that istream::sync() did, in effect, cancel all
>> current input to std::cin (on all the compilers I have so far tried).
>>
>> So when it comes down to the wire, all the mechanisms suggested by
>> experts such as Dietmar fail whilst this one that externally offers no
>> reasonable promise of success, does so. Theory and practice seem to be
>> an ocean apart in a situation that makes the life of novices and casual
>> programmers impossible.
>
>It is mentioned in C++ 3rd Ed. in 21.6.2. and what it says is pretty
>unambiguous:
>
>"Flushing an istream is done using sync(). This cannot always be done
>right. For some kinds of streams, we would have to reread characters
>from the real source - and that is not always possible or desirable.
>Consequently, sync() returns 0 if it succeeded. If it failed it sets
>ios_base::badbit and returns -1.
>Setting badbit may trigger an exception."
>
>and very useful it is too :-)
Thanks. And I note that on page 647 in 21.6.4 he comments on in_avail()
returning 0 even in cases where an input would succeed. So at least
Bjarne believes that sync() should generally work but that is not what
the library experts around here are saying (though I note that VC++ is
one of the implementations where it works and they use the Dinkumware
Library)
So perhaps the following might be portable:
void clear_cin(){
if(cin.rdbuf()->in_avail())
cin.ignore(numeric_limits<int>::max(), '\n');
else cin.sync();
}
Or are there implementations that both always return 0 for in_avail()
and do not flush input when sync() is called? That would be immensely
better than the following extremely ugly hack I currently have to use:
void clear_cin(){
cout<< "If this program halts here press ENTER\n";
cin.ignore(numeric_limits<int>::max(), '\n');
}
--
Francis Glassborow ACCU
Author of 'You Can Do It!' see http://www.spellen.org/youcandoit
For project ideas and contributions: http://www.spellen.org/youcandoit/projects
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html ]
Author: francis@robinton.demon.co.uk (Francis Glassborow)
Date: Thu, 12 Aug 2004 18:52:04 GMT Raw View
In article <2nvah0F553aqU1@uni-berlin.de>, Dietmar Kuehl
<dietmar_kuehl@yahoo.com> writes
>>>> Well I would love to replace it with something sensible but
>>>> unfortunately is_avail() is not required to return anything greater than
>>>> zero and in several implementations of std.cin std.cin.is_avail() always
>>>> returns zero. OTOH ignore() requires that there be at least one
>>>> character to ignore.
>
>If there is no character, how did you determine that it is a "bad" one
>which should be ignored? Put differently, in the setting you are
>concerned with (fault tolerance of programs written by programmers new
>to C++ or IOStreams) there always is at least one character, i.e. it
>is safe to do something like this:
>
> int i = 0;
> while (!(std::cin >> i) && !std::cin.eof())
> {
> std::cin.clear();
> std::cin.ignore();
> }
> if (std::cin)
> std::cout << "number read: " << 10 << "\n";
> else
> std::cout << "hit EOF\n";
No, you still miss the point. The case of bad input is only one example
and is easily handled with ignore. However what is not easily handled is
input from std::cin where the programmer does not know if the last
extraction was 'up to white space' (as for operator >>) or 'up to \n as
delimiter' (as for the default use of getline)
There is no portable way that I can find that manages that case. Do you
really think that books for novices should abandon all use of
operator >> applied to std::cin and replace it with a special input
handling mechanism that reads a line and then applies operator >> to it
until it is empty at which point it will refresh itself by applying
getline to std::cin?
>
>Actually, without further contracts on the file format, i.e. explicitly
>known recovery points, this is as far as I would go with respect to
>fault tolerance! If I'm dealing with some protocol where I know e.g. a
>message size, it may be reasonable to read the whole message. ... or if
>the protocol is line based it may be reasonable to abandon the current
>line. However, 'std::basic_istream' or 'std::basic_streambuf' does not
>know anything about such protocols!
>
>BTW, using gcc-3.3.1 on my Linux machine and changing 'ignore' to 'sync'
>causes the program to loop forever if I enter something which cannot be
>parsed as an integer (as I would have expected).
OK, but I bet that same setup does not return 0 for is_avail() which the
MinGW version of gcc-3.3.1 does on Windows platforms.
>
>> Perhaps we do really need a
>> 'console_buffer' type that provides the specialised behaviour needed for
>> reliable and portable use of std::cin. Placing this at the buffer level
>> would allow us to handle redirection by changing to an appropriate
>> buffer type with correct semantics.
>
>I still don't see where anything new is necessary! Just process things
>linewise as is recommended since ages anyway if you don't like the
>characterwise recovery I have shown above. Since computer don't go
>into deep meditation when parsing things, it is very unlikely that the
>user had any chance to type even another single character after hitting
>newline and being prompted for an error! The code could look like this:
>
> int i = 0;
> for (std::string line; std::getline(std::cin); )
> {
> std::istringstream in;
> if (in >> i)
> break;
> }
>
>..and if you insist that 'std::basic_istream::sync()' is the way to go,
>wrap this up into a stream buffer and implement 'sync()' correspondingly:
I don't. I don't insist that any specific route is the way to go but I
do think that a fully portable way should be provided by the Standard.
And people like you have carefully explained to me why is_avail() is
allowed to return 0 even when std::cin.get() will return without any
further user action.
>
> struct console_buffer: std::streambuf {
> int underflow() {
> typedef std::streambuf::traits_type traits;
> if (!std::getline(std::cin, m_line))
But there is the problem again, the program will 'lock' waiting for
input if there is none currently available.
> return traits::eof();
> m_line.append("\n");
> char* c_str = const_cast<char*>(m_line.c_str()); // (*)
> setg(c_str, c_str, c_str + m_line.size());
> return gptr() != egptr()? traits::to_int_type(*gptr()): traits::eof();
> }
> int sync() {
> setg(0, 0, 0);
> return 0;
> }
> private:
> std::string m_line;
> };
I really do not care how it is achieved but I do require that there be a
way to check whether there is currently at least one item waiting for
processing in std::cin's input. Currently no one has managed to provide
a portable solution to that problem.
--
Francis Glassborow ACCU
Author of 'You Can Do It!' see http://www.spellen.org/youcandoit
For project ideas and contributions: http://www.spellen.org/youcandoit/projects
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html ]
Author: andy@servocomm.freeserve.co.uk (kwikius)
Date: Fri, 13 Aug 2004 05:11:42 GMT Raw View
Francis Glassborow <francis@robinton.demon.co.uk> wrote in message news:<ryf1isHIc1GBFwYV@robinton.demon.co.uk>...
> In article <2873fa46.0408101802.12f98238@posting.google.com>, kwikius
> <andy@servocomm.freeserve.co.uk> writes
> >francis@robinton.demon.co.uk (Francis Glassborow) wrote in message news:<7BXBu+BooHGBFw5H@robinton.demon.co.uk>...
> >
> >> It surprised me to find that istream::sync() did, in effect, cancel all
> >> current input to std::cin (on all the compilers I have so far tried).
> >>
> >> So when it comes down to the wire, all the mechanisms suggested by
> >> experts such as Dietmar fail whilst this one that externally offers no
> >> reasonable promise of success, does so. Theory and practice seem to be
> >> an ocean apart in a situation that makes the life of novices and casual
> >> programmers impossible.
> >
> >It is mentioned in C++ 3rd Ed. in 21.6.2. and what it says is pretty
> >unambiguous:
> >
> >"Flushing an istream is done using sync(). This cannot always be done
> >right. For some kinds of streams, we would have to reread characters
> >from the real source - and that is not always possible or desirable.
> >Consequently, sync() returns 0 if it succeeded. If it failed it sets
> >ios_base::badbit and returns -1.
> >Setting badbit may trigger an exception."
> >
> >and very useful it is too :-)
>
> Thanks. And I note that on page 647 in 21.6.4 he comments on in_avail()
> returning 0 even in cases where an input would succeed. So at least
> Bjarne believes that sync() should generally work but that is not what
> the library experts around here are saying (though I note that VC++ is
> one of the implementations where it works and they use the Dinkumware
> Library)
>> Or are there implementations that both always return 0 for
in_avail()
> and do not flush input when sync() is called? That would be immensely
> better than the following extremely ugly hack I currently have to use:
I guess if you are talking Generic Programming then for all the
reasons above
neither in_avail() nor ignore() nor sync() describe the situation,
but...
IMO sync() is designed for the particular case of keyboard input, in
which there is no such thing as an EOF, because the user can always
type something else. For keyboard input if you use ignore(n, '\n')
then either, the user must input a '\n' for the programme to proceed,
or the user has already typed an '\n' maybe followed by other data. ie
the result of the call is unknown from the point of view of what I
guess is your intent, as described below. OTOH in_avail() may return
an 'estimate' , which IMO means never rely on it at all in the
keyboard input situation.
Therefore... a facility such as sync() is extremely useful when
Learning a new programming language(which is why it may not be
appreciated by gurus). The situation here is that I am writing very
short programs and using keyboard input to provide data to quickly
test code I have written. I want a simple means of saying "clear all
the previous rubbish, including returns and get me to a state where
the next character I enter is potentially the first meaningful
character". That is my understanding of what std::cin.sync() does.
> void clear_cin(){
> cout<< "If this program halts here press ENTER\n";
> cin.ignore(numeric_limits<int>::max(), '\n');
> }
A quick alternative blast at this assuming cin Is keyboard input and
following the rules in C++ 3rd Ed as above:
void clear_cin(); // defined below
// nominally any istream but probably unwise on anything but keyboard
input
template<typename Istream>
bool try_sync(Istream& in )
{
try {
typename Istream::int_type ret = in.sync();
switch (ret){
case 0:
return true;
case -1:
return false;
default:
in.clear(std::ios_base::badbit); // ie set "bad
stream"
std::cout << "odd behaviour in
std::cin.sync()..quitting";
throw std::unexpected;
}
}
catch(std::ios_base::failure e){
std::cerr << "sorry "<< typeid(Istream).name() << ".sync()\n"
"failed with \"" << e.what() << "\"\nplease report\n";
return false;
}
}
void clear_cin()
{
if (!try_sync(std::cin)){
std::cout <<
"Sorry... std::cin.sync() fails on your system\n"
"please report\n";
// belt and braces?
throw std::exception("std::cin.sync(),fails on your system "
"please report.");
}
}
pragmatically
regards
Andy Little
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html ]
Author: dietmar_kuehl@yahoo.com (Dietmar Kuehl)
Date: Fri, 13 Aug 2004 16:57:14 GMT Raw View
Francis Glassborow wrote:
> No, you still miss the point. The case of bad input is only one example
> and is easily handled with ignore.
Put differently: it is not a point.
> However what is not easily handled is
> input from std::cin where the programmer does not know if the last
> extraction was 'up to white space' (as for operator >>) or 'up to \n as
> delimiter' (as for the default use of getline)
I somewhat fail to see an example where this is necessary due to at
least two reasons:
- Often the user will know what was the last operation anyway.
- Why would the programmer care at all? If the next operation is
unformatted, is fine and trailing whitespace for formatted
operations is ignored.
Maybe you can give an example where this case actually occurs?
> There is no portable way that I can find that manages that case.
A custom filtering stream buffer can definitely tell whether the
last extracted character was a newline. Actually, using 'putback()'
you can also tell: there is a effectively a requirement that a
stream buffer sets up a buffer, even if the buffer is just one
character, when returning a character from 'underflow()' (rendering
'uflow()' to be quite useless). This in turn means that the last
character which was extracted still sits there. Ugly? Yes. Portable
according to the standard? Yes. Portable to real implementations
of 'std::cin'? Dunno. Portable to custom stream buffer? Probably not.
However, the custom filtering stream buffer is a portable approach
to this. It is not a single line built-in approach.
> Do you
> really think that books for novices should abandon all use of
> operator >> applied to std::cin and replace it with a special input
> handling mechanism that reads a line and then applies operator >> to it
> until it is empty at which point it will refresh itself by applying
> getline to std::cin?
No, not at all. I think books for novices should use typical input
idioms with 'std::cin' and stay clear of handling interactive input
(i.e. detection of whether a key was pressed or not) and error
recovery (but not error detection) at least until later chapters.
Error recovery, e.g. in the form you just described, the stream
buffer I have posted before, etc. can be introduced if the novices
have become more comfortable with C++ and streams. Since standard
C++ does not have any concept of interactive input (a la 'kbhit()'
or curses) I would stay clear of these issues in books for novices
completely. This stuff may be sexy but it is definitely non-portable
- and will probably stay non-portable in C++. It is addressed by
other standards like e.g. POSIX, however.
>>BTW, using gcc-3.3.1 on my Linux machine and changing 'ignore' to 'sync'
>>causes the program to loop forever if I enter something which cannot be
>>parsed as an integer (as I would have expected).
>
> OK, but I bet that same setup does not return 0 for is_avail() which the
> MinGW version of gcc-3.3.1 does on Windows platforms.
You'd loose your bet: 'in_avail()' return '0' although I have to
admit that I don't know how they manage to do so...
>>..and if you insist that 'std::basic_istream::sync()' is the way to go,
>>wrap this up into a stream buffer and implement 'sync()' correspondingly:
>
> I don't. I don't insist that any specific route is the way to go but I
> do think that a fully portable way should be provided by the Standard.
To do what exactly? I'm still unclear about the problem you
want to solve...
[code excerpt using 'std::getline()' remove]
> But there is the problem again, the program will 'lock' waiting for
> input if there is none currently available.
Yes, of course it will wait for input! What is wrong with this?
Especially, what is wrong with this in a context involving
novices?
The "problem" that there is no portable approach to interactive
input is actually pretty old: I have seen it discussed in both
C and C++ newsgroups since I participate in Usenet. Still, there
either have been no proposals to add a cure for it or there were
good reasons to reject them. I actually guess both apply. For
example, if you turn a UNIX console into a mode sending individual
characters, you obviously loose the support for "automatic"
backspaces etc. Also, the terminal generally knows how to move to
the previous line when deleting a character, something to which
there is also no portable solution. Essentially, starting this
road would soon lead to something quite similar to curses. ...and
would yield a tool which is rarely used in new developments,
either because the applications are not interactive or because
they use a "real" GUI (yes, this is also not part of the standard
and is actually also something I consider unlikely to become part
of standard C++).
> I really do not care how it is achieved but I do require that there be a
> way to check whether there is currently at least one item waiting for
> processing in std::cin's input. Currently no one has managed to provide
> a portable solution to that problem.
Right. There is no portable solution to interactive input, i.e.
there is no portable approach to detect when a key is pressed
(well, you can effectively detect when the return key is pressed
but I guess this is not really the request). I don't see why this
is a requirement and I doubt that a solution to this requirement
will become part of the C++ standard. Apart from the ubiquitous
"it is not implementable on all systems" (which I cannot confirm
myself: it is implementable on the systems I'm working on), I doubt
that there is a sufficiently large potential user base of such a
feature. Also, I don't think that the IOStreams library was intended
to support such a feature.
--
<mailto:dietmar_kuehl@yahoo.com> <http://www.dietmar-kuehl.de/>
<http://www.contendix.com> - Software Development & Consulting
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html ]
Author: francis@robinton.demon.co.uk (Francis Glassborow)
Date: Fri, 13 Aug 2004 19:11:13 GMT Raw View
In article <2o47fiF6tdvaU1@uni-berlin.de>, Dietmar Kuehl
<dietmar_kuehl@yahoo.com> writes
>> I really do not care how it is achieved but I do require that there be a
>> way to check whether there is currently at least one item waiting for
>> processing in std::cin's input. Currently no one has managed to provide
>> a portable solution to that problem.
>
>Right. There is no portable solution to interactive input, i.e.
>there is no portable approach to detect when a key is pressed
>(well, you can effectively detect when the return key is pressed
>but I guess this is not really the request). I don't see why this
>is a requirement and I doubt that a solution to this requirement
>will become part of the C++ standard. Apart from the ubiquitous
>"it is not implementable on all systems" (which I cannot confirm
>myself: it is implementable on the systems I'm working on), I doubt
>that there is a sufficiently large potential user base of such a
>feature. Also, I don't think that the IOStreams library was intended
>to support such a feature.
I will just quote this much because it is enough to hang my response on.
I am not asking for kbhit() or any version of that. I think I am asking
for something very simple and apparently something that Bjarne
Stroustrup thinks already exists (see page 643 et seq. of TC++PL 3ed).
Furthermore I cannot see any reason for it not being available other
than the possibility that some people just think that programmers should
be made to suffer.
Consider:
int main(){
try {
do{
foo();
std::cout << "Another?";
// what goes here
while(std::cin.get() != 'n');
}
catch(...){std::cerr << "something went wrong.\n"; }
}
I know this is overly simple but it does illustrate the problem. I want
to check that the next key pressed is either n or not n. I am perfectly
happy to explain to my user that they must press ENTER after they make
their response so I am not talking about kbhit(), getkey() or whatever.
Now explain to the user why that code sometimes never waits for a
response. Perhaps std::cin is in a fail state. No, inserting a check
shows that it is fine but we still have this odd behaviour. So we now
try using some version of ignore. It now sometimes blocks and the poor
bewildered user finds that sometimes they must press ENTER n ENTER but
sometimes that results in another iteration.
What we need is a mechanism that discards all input prior to the prompt.
And it is easy to write such code given one tiny feature but without
that feature even the best of users (of programs) who never types ahead,
never gives a bad response etc. is still left with a program that seems
to behave in an arbitrary fashion.
Why the erratic behaviour? Because some of the execution paths from the
call to foo() use a function like getline() and some use something like
operator >>. We may not even know this because the programmer may be
using third party libraries. The authors of those libraries do not
realise that their code could cause a problem -- it never does for them
and they do not even document the state that an istream is left in
because it never strikes them that the istream might be std::cin.
Peek() does not work, in_avail() is not required to tell even
approximately the truth (just a bool true/false would be enough), sync()
doesn't do it even though the original designer of the language thinks
it should.
Just because you never write programs that have this kind of problem is
no reason to dismiss it as a non-problem. Note that even as an expert
library programmer you cannot see any good reason for in_avail() to
return 0 even when there is data waiting for processing and yet it does.
Note that in this case I am just a deeply frustrated user. Library
design and implementation are not my thing. But why is it so hard to
understand the problem and why so hard to fix it.
--
Francis Glassborow ACCU
Author of 'You Can Do It!' see http://www.spellen.org/youcandoit
For project ideas and contributions: http://www.spellen.org/youcandoit/projects
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html ]
Author: francis@robinton.demon.co.uk (Francis Glassborow)
Date: Sat, 7 Aug 2004 21:47:56 GMT Raw View
Some of you may remember that I had a major problem with trying to
ensure that std::cin was in a predictable state (i.e. no data waiting
for processing). The problem was that using std::cin.rdbuf()->in_avail()
on some implementations (the case in point being MinGW) always returns 0
which makes it useless for detecting if reading may block when reading
from the keyboard.
Now in:
#include <iostream>
#include <istream>
#include <string>
int main(){
std::string s;
std::cin >> s;
std::cout << std::cin.rdbuf()->in_avail();
std::cout << "?: ";
std::cin.sync(); // line A
std::cin.get();
}
consider line A. Is that line required to compile? Is it also required
to consume all the previous input from the keyboard (assuming that is
the source for std::cin)?
It certainly works with MinGW but should it be portable?
--
Francis Glassborow ACCU
Author of 'You Can Do It!' see http://www.spellen.org/youcandoit
For project ideas and contributions: http://www.spellen.org/youcandoit/projects
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html ]
Author: dietmar_kuehl@yahoo.com ("dietmar_kuehl@yahoo.com")
Date: Tue, 10 Aug 2004 06:10:50 GMT Raw View
Francis Glassborow wrote:
> Some of you may remember that I had a major problem with trying to
> ensure that std::cin was in a predictable state (i.e. no data waiting
> for processing).
'std::cin' is viewed as a contiguous stream of characters by the
standard.
There is no such thing as discarding the currently waiting data and
somehow
continuing afterwards with new data according to the standard. If you
want
to discard some of the data from 'std::cin' portably, you need to
specify
which data this is. For example, you can discard everything on the
current
line using something like
std::cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
> #include <iostream>
> #include <istream>
> #include <string>
>
> int main(){
> std::string s;
> std::cin >> s;
> std::cout << std::cin.rdbuf()->in_avail();
> std::cout << "?: ";
> std::cin.sync(); // line A
> std::cin.get();
> }
>
> consider line A. Is that line required to compile?
Yes. Why 'sync()' is a member of 'std::basic_istream' is, however,
beyond me.
> Is it also required
> to consume all the previous input from the keyboard (assuming that is
> the source for std::cin)?
No. 'std::basic_istream::sync()' effectively calls
'std::basic_streambuf::sync()'
which in turn only has defined semantics with respect to the put buffer
but not
with respect to the get buffer. I would claim that it is an error if
'std::basic_streambuf::sync()' discards any characters since this
actually
brings the internal and external representation out of sync. However,
the
contracts established for virtual functions in the standard C++ library
are
notoriously ambiguous: there is no statement with respect to input and
it may
be OK to actually discard some input.
> It certainly works with MinGW but should it be portable?
I don't think it should be portable: introducing a time dependency
(depending
on when the call is made more data may be discarded) is, IMO,
explicitly asking
for trouble.
--
<mailto:dietmar_kuehl@yahoo.com> <http://www.dietmar-kuehl.de/>
<http://www.contendix.com> - Software Development & Consulting
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html ]
Author: johnchx2@yahoo.com (johnchx)
Date: Tue, 10 Aug 2004 06:15:11 GMT Raw View
francis@robinton.demon.co.uk (Francis Glassborow) wrote
> std::cin.sync(); // line A
> consider line A. Is that line required to compile?
Yes, I should think so.
> Is it also required
> to consume all the previous input from the keyboard (assuming that is
> the source for std::cin)?
I don't see anything remotely like this behavior specified in the
standard. The istream's sync() calls the streambuf's pubsync() which
calls the streambuf's sync() which has the following Effects:
Synchronizes the controlled sequences with the arrays. That is, if
pbase() is non-null the characters between pbase() and pptr() are
written to the controlled sequence. The pointers may then be
reset as appropriate.
--27.5.2.4.2 p7
As far as I can see, the only sensible use for sync() is to flush
buffered output to a file, which is what I suspect it's really for.
Which does raise one interesting question: why in the world does an
istream even have this member?
>
> It certainly works with MinGW but should it be portable?
>
I may be missing something, but this sure sounds like a gnu extension
(assuming you're using libstdc++). It seems handy, and, as I said, I
don't see any real use for basic_istream::sync() as specified, so why
not replace it with something that does something sensible? But it
doesn't look portable.
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html ]
Author: francis@robinton.demon.co.uk (Francis Glassborow)
Date: Tue, 10 Aug 2004 17:18:42 GMT Raw View
In article <4fb4137d.0408092144.16fcbe8c@posting.google.com>, johnchx
<johnchx2@yahoo.com> writes
>I don't see anything remotely like this behavior specified in the
>standard. The istream's sync() calls the streambuf's pubsync() which
>calls the streambuf's sync() which has the following Effects:
Note that streambuf's sync is a virtual function.
>
> Synchronizes the controlled sequences with the arrays. That is, if
> pbase() is non-null the characters between pbase() and pptr() are
> written to the controlled sequence. The pointers may then be
> reset as appropriate.
>
> --27.5.2.4.2 p7
>
>As far as I can see, the only sensible use for sync() is to flush
>buffered output to a file, which is what I suspect it's really for.
>
>Which does raise one interesting question: why in the world does an
>istream even have this member?
An excellent question. However on the other side, what does sync do for
an ostream that flush doesn't?
>
>>
>> It certainly works with MinGW but should it be portable?
>>
>
>I may be missing something, but this sure sounds like a gnu extension
>(assuming you're using libstdc++). It seems handy, and, as I said, I
>don't see any real use for basic_istream::sync() as specified, so why
>not replace it with something that does something sensible? But it
>doesn't look portable.
Well I would love to replace it with something sensible but
unfortunately is_avail() is not required to return anything greater than
zero and in several implementations of std.cin std.cin.is_avail() always
returns zero. OTOH ignore() requires that there be at least one
character to ignore.
It surprised me to find that istream::sync() did, in effect, cancel all
current input to std::cin (on all the compilers I have so far tried).
So when it comes down to the wire, all the mechanisms suggested by
experts such as Dietmar fail whilst this one that externally offers no
reasonable promise of success, does so. Theory and practice seem to be
an ocean apart in a situation that makes the life of novices and casual
programmers impossible.
--
Francis Glassborow ACCU
Author of 'You Can Do It!' see http://www.spellen.org/youcandoit
For project ideas and contributions: http://www.spellen.org/youcandoit/projects
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html ]