Problems with cin (already tried getline)

M

Michele 'xjp'

Hi there.

I have some problems with cin. Here's the code:

http://rafb.net/p/GhK3AU65.html

If you press '6', and 'enter', it will have to ask for another insert of
a string. However, in this case, it goes straight without waiting for
input... any ideas?
 
Z

Zeppe

Michele said:
Hi there.

I have some problems with cin. Here's the code:

http://rafb.net/p/GhK3AU65.html

If you press '6', and 'enter', it will have to ask for another insert of
a string. However, in this case, it goes straight without waiting for
input... any ideas?

yes, there is a \n in the buffer. Put cin.sync() after cin >> scelta,
and everything will work ;)

Regards,

Zeppe
 
?

=?ISO-8859-15?Q?Erik_Wikstr=F6m?=

Hi there.

I have some problems with cin. Here's the code:

http://rafb.net/p/GhK3AU65.html

Please post the code inline.
If you press '6', and 'enter', it will have to ask for another insert of
a string. However, in this case, it goes straight without waiting for
input... any ideas?

Because the enter you pressed after the 6 is still in the input buffer,
so the getline() will read that, and since it's the terminator chosen
(it's default by the way, you don't have to specify it) it will read in
an empty string.

By the way, why oh why:

#define clrscr() printf("\e[2J")

What's wrong with an inline function or something like that, don't you
know that macros are evil?
 
J

Jim Langston

Michele 'xjp' said:
Hi there.

[Code from link inserted]
#include <iostream>
#include <string>
#include <cstdlib>

using namespace std;

#define clrscr() printf("\e[2J")

int main(void) {
bool end = false;
char scelta;
do
{
clrscr();
cout << "*******************************************" << endl
<< "************ foo **********" << endl
<< "*******************************************" << endl <<
endl
<< "6 - bar" << endl
<< "0 - exit" << endl;
cin >> scelta;

switch (scelta)
{
case '6': {
cout << "type here:";
string titolo;
getline(std::cin, titolo, '\n');

Add this line to help you determine what's going on a little bit:

std::cout << titolo;
break;
}
case '0':
end = true;
exit(0);
}
}
while (!end);
return 0;
}
If you press '6', and 'enter', it will have to ask for another insert of
a string. However, in this case, it goes straight without waiting for
input... any ideas?

What is happening, is the std::cin >> scelta; will look for a character, but
the input doesn't get processed until you press enter. So you press 6 and
press enter. What is waiting then in std::cin is "6\n". The cin >> scelta;
grabs the character 6, but leaves the carriage return. getline( std::cin ,
titolo, '\n'); is processed and, hey, the '\n' is already there, so that's
what it loads into titolo, nothing. That si what the std::cout << titolo;
will show. Instead of pressing 6 then enter, try "6 This is some input" and
press enter, and you'll see that " This is some input" is displayed.

So what you want to do is ignore eveyrthing in cin after you read your
character.

std::cin.ignore( 999, '\n' );
after the cin >> scelta;
would do the trick. I'm sure there's a better number to use than 999 (maybe
a constant?) but I'm not sure what it is. Maybe someone else can say.
 
R

Robert Bauck Hamar

Jim said:
Michele 'xjp' said:
Hi there.

[Code from link inserted]
#include <iostream>
#include <string>
#include <cstdlib>

using namespace std;

#define clrscr() printf("\e[2J")

int main(void) {
bool end = false;
char scelta;
do
{
clrscr();
cout << "*******************************************" << endl
<< "************ foo **********" << endl
<< "*******************************************" << endl <<
endl
<< "6 - bar" << endl
<< "0 - exit" << endl;
cin >> scelta;

switch (scelta)
{
case '6': {
cout << "type here:";
string titolo;
getline(std::cin, titolo, '\n');

Add this line to help you determine what's going on a little bit:

std::cout << titolo;
break;
}
case '0':
end = true;
exit(0);
}
}
while (!end);
return 0;
}
If you press '6', and 'enter', it will have to ask for another insert of
a string. However, in this case, it goes straight without waiting for
input... any ideas?

What is happening, is the std::cin >> scelta; will look for a character,
but
the input doesn't get processed until you press enter. So you press 6 and
press enter. What is waiting then in std::cin is "6\n". The cin >>
scelta;
grabs the character 6, but leaves the carriage return. getline( std::cin
, titolo, '\n'); is processed and, hey, the '\n' is already there, so
that's
what it loads into titolo, nothing. That si what the std::cout << titolo;
will show. Instead of pressing 6 then enter, try "6 This is some input"
and press enter, and you'll see that " This is some input" is displayed.

So what you want to do is ignore eveyrthing in cin after you read your
character.

std::cin.ignore( 999, '\n' );
after the cin >> scelta;
would do the trick. I'm sure there's a better number to use than 999
(maybe a constant?) but I'm not sure what it is. Maybe someone else can
say.

std::numeric_limits<std::streamsize>::max() is the magic number. Ignore()
will take that as infinity, and only stop at end of file or the given
sentinel (here '\n').
 
M

Michele 'xjp'

Zeppe ha scritto:
yes, there is a \n in the buffer. Put cin.sync() after cin >> scelta,
and everything will work ;)

Regards,

Zeppe

I get the same problem with cin.sync()...

Solved with:
cin.ignore(INT_MAX, '\n' );

after the initially cin >> scelta

Thank you!
 
M

Michele 'xjp'

Jim Langston ha scritto:
What is happening, is the std::cin >> scelta; will look for a character, but
the input doesn't get processed until you press enter. So you press 6 and
press enter. What is waiting then in std::cin is "6\n". The cin >> scelta;
grabs the character 6, but leaves the carriage return. getline( std::cin ,
titolo, '\n'); is processed and, hey, the '\n' is already there, so that's
what it loads into titolo, nothing. That si what the std::cout << titolo;
will show. Instead of pressing 6 then enter, try "6 This is some input" and
press enter, and you'll see that " This is some input" is displayed.

So what you want to do is ignore eveyrthing in cin after you read your
character.

std::cin.ignore( 999, '\n' );
after the cin >> scelta;
would do the trick. I'm sure there's a better number to use than 999 (maybe
a constant?) but I'm not sure what it is. Maybe someone else can say.


Solved with:
cin.ignore(INT_MAX, '\n' );

after the initially cin >> scelta

Thank you!
 
O

Obnoxious User

Hi there.

I have some problems with cin. Here's the code:

http://rafb.net/p/GhK3AU65.html

If you press '6', and 'enter', it will have to ask for another insert of
a string. However, in this case, it goes straight without waiting for
input... any ideas?

Always verify input data, and always verify the state of the input stream,
after each input.
 
R

Robert Bauck Hamar

Michele said:
Jim Langston ha scritto:


Solved with:
cin.ignore(INT_MAX, '\n' );

after the initially cin >> scelta

You should really prefer std::numeric_limits<std::streamsize>::max() over
INT_MAX here. Std::numeric_limits is defined in <limits>.
 
J

James Kanze

You should really prefer
std::numeric_limits<std::streamsize>::max() over INT_MAX here.
Std::numeric_limits is defined in <limits>.

The problem is that the original standard says that the argument
type is int, and the magic value for infinity
std::numeric_limits<int>::max() (i.e. INT_MAX). IMHO, this was
an error, and the latest draft for the next version of the
standard uses std::streamsize, as expected, but it's likely that
some implementations actually implemented what was written in
the standard. Using the smaller of the two values is probably
safe (unless you have users who regularly enter very, very long
lines), but if you use a value larger than the target type, and
the target type is signed (e.g. int), the results will be
negative, and probably not what you want. The probability that
std::streamsize is smaller than int seems pretty small, at least
on the machines I work on, so I use INT_MAX, just to be sure.
 
J

James Kanze

Always verify input data, and always verify the state of the
input stream, after each input.

I'll second that. And if you want line oriented input, always
use getline, then (if necessary) istringstream to parse it.
Something like:

std::string line ;
getline( std::cin, line ) ;
std::istringstream l( line ) ;
int number ;
l >> number >> std::ws ;
if ( ! l || l.get() != EOF ) {
// We got a problem, somewhere between the keyboard
// and the chair.
}
 
Z

Zeppe

James said:
cin is an input buffer; cin.sync() has no defined meaning.

Strousrup doesn't quite agree with you, in 21.6.2 (third ed.): "Flushing
an istream is done using sync()."

Regards,

Zeppe
 
J

James Kanze

Strousrup doesn't quite agree with you, in 21.6.2 (third ed.): "Flushing
an istream is done using sync()."

The standard says (for the effects of std::filebuf::sync):

If a put area exists, calls filebuf::eek:verflow to write the
characters to the file. If a get area exists, the effect is
implementation-defined.

Given that the semantics of filebuf are defined in terms of
FILE*, by reference to the C standard, I would expect
std::filebuf::sync to have the same semantics as the C function
fflush (which is likely what Stroustrup is thinking of when he
wrote that). According to the C standard, the effects of
fflush( stream ) are:

If stream points to an output stream or an update stream in
which the most recent operation was not input, the fflush
function causes any unwritten data for that stream to be
delivered to the host environment to be written to the file;
otherwise, the behavior is undefined.

All of which is very logical when one considers the technical
meaning of the English word flush, which only applies to output.
 
Z

Zeppe

James said:
The standard says (for the effects of std::filebuf::sync):

If a put area exists, calls filebuf::eek:verflow to write the
characters to the file. If a get area exists, the effect is
implementation-defined.

We are talking about the sync function in basic_istream.
For sync(), "my" standard says, at 27.6.1.3#36 (Unformatted input
functions):

Behaves as an unformatted input function (as described in 27.6.1.3,
paragraph 1), except that it does not count the number of characters
extracted and does not affect the value returned by subsequent calls to
gcount().
wrote that). According to the C standard, the effects of
fflush( stream ) are:

If stream points to an output stream or an update stream in
which the most recent operation was not input, the fflush
function causes any unwritten data for that stream to be
delivered to the host environment to be written to the file;
otherwise, the behavior is undefined.

All of which is very logical when one considers the technical
meaning of the English word flush, which only applies to output.

I know the semantics of fflush in C, and I agree that it's logical and
that it agrees to the English language, but I can't get your point:
fflush is one thing (and there is the corresponding flush method in C++
for ostreams), and sync is another thing (with a quite different English
meaning, too) :)

Regards,

Zeppe
 
J

James Kanze

We are talking about the sync function in basic_istream.
For sync(), "my" standard says, at 27.6.1.3#36 (Unformatted input
functions):
Behaves as an unformatted input function (as described in 27.6.1.3,
paragraph 1), except that it does not count the number of characters
extracted and does not affect the value returned by subsequent calls to
gcount().

Strange. Which version is that, which doesn't say that it calls
rdbuf()->pubsync()? Functions in basic_istream have no effect
on the actual stream, except in so far as they call functions on
the streambuf.

In streambuf, pubsync() is required to call the virtual function
sync(), and the above is the definition of the semantics for
this function if the streambuf is a filebuf (the case for cin,
for example).
I know the semantics of fflush in C, and I agree that it's logical and
that it agrees to the English language, but I can't get your point:
fflush is one thing (and there is the corresponding flush method in C++
for ostreams), and sync is another thing (with a quite different English
meaning, too) :)

I'm trying to get at intent. Practically everything in iostream
is defined by mapping it to something appropriate in stdio.h;
formatting is defined in terms of printf formatters,
filebuf::eek:pen in terms of fopen, etc. So "intuitively", one
would expect sync to correspond to fflush (since that's about
the closest you can come in C). You're right, of course, that
the English word chosen does have different implications; I'm
not sure what it should mean with respect to keyboard input, but
you can't automatically say that it can't have meaning for input
in general. And C++ *does* require the implementation to
document what it does---it's not undefined behavior, as fflush
is in C. So if you're not worried about portability, and your
implementation defines it to do something which is useful to
you, by all means.

FWIW: in practice, I think most implementations---both of
filebuf::sync and fflush---simply discard any bytes that they
currently have in the buffer. If you're reading from a file,
this doesn't really correspond to what I would expect from the
English language word sync, but then, a lot of C and C++ (and
other languages, too) use English words in very special ways.
Under Unix (and Windows, too, I think), keyboard input is line
oriented by default; the system read will always stop at a new
line character (and not return until it sees one), regardless of
how many characters you requested. So *if* the buffer is large
enough, it will contain all of the line read, and sync will have
more or less the same effect as ignore. This effect is more or
less accidental, however, is not really guaranteed (at least by
the implementations I'm familiar with), and can fail in extreme
cases. (Try doing a setbuf with a buffer length of 1, or
entering over ten thousand characters, or whatever, in a line.)
It's not reliable.
 
Z

zeppe

James said:
Strange. Which version is that, which doesn't say that it calls
rdbuf()->pubsync()? Functions in basic_istream have no effect
on the actual stream, except in so far as they call functions on
the streambuf.

It does (standard c++03), I didn't quote the entire paragraph, that is:

Behaves as an unformatted input function (as described in 27.6.1.3,
paragraph 1), except that it does not count the number of characters
extracted and does not affect the value returned by subsequent calls to
gcount(). After constructing a sentry object, if rdbuf() is a null
pointer, returns -1 . Otherwise, calls rdbuf()->pubsync() and, if that
function returns -1 calls setstate(badbit) (which may throw
ios_base::failure (27.4.4.3), and returns -1. Otherwise, returns zero.

I didn't quote it because I just wanted to make the point that sync is
defined and it has got a sense for input streams (and actually, just for
input streams, it seems).
In streambuf, pubsync() is required to call the virtual function
sync(), and the above is the definition of the semantics for
this function if the streambuf is a filebuf (the case for cin,
for example).

I see. But I can't see why filebuf should be the streambuf for cin. cin
is not a ifstream, is an istream, and it should have a basic_streambuf
as associated stream buffer.
I'm trying to get at intent. Practically everything in iostream
is defined by mapping it to something appropriate in stdio.h;
formatting is defined in terms of printf formatters,
filebuf::eek:pen in terms of fopen, etc. So "intuitively", one
would expect sync to correspond to fflush (since that's about
the closest you can come in C).

I see your point, and usually I think as you do. But in this case, being
a function named flush already present in the iostream, with the same
semantics of fflush, and being sync defined for input streams, I argue
that there is probably something different.
You're right, of course, that
the English word chosen does have different implications; I'm
not sure what it should mean with respect to keyboard input, but
you can't automatically say that it can't have meaning for input
in general. And C++ *does* require the implementation to
document what it does---it's not undefined behavior, as fflush
is in C. So if you're not worried about portability, and your
implementation defines it to do something which is useful to
you, by all means.

the semantics for basic_streambuf::sync() is (27.5.2.4.2#7):

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.
FWIW: in practice, I think most implementations---both of
filebuf::sync and fflush---simply discard any bytes that they
currently have in the buffer.

as the standard says (see above).
If you're reading from a file,
this doesn't really correspond to what I would expect from the
English language word sync, but then, a lot of C and C++ (and
other languages, too) use English words in very special ways.
Under Unix (and Windows, too, I think), keyboard input is line
oriented by default; the system read will always stop at a new
line character (and not return until it sees one), regardless of
how many characters you requested. So *if* the buffer is large
enough, it will contain all of the line read, and sync will have
more or less the same effect as ignore. This effect is more or
less accidental, however, is not really guaranteed (at least by
the implementations I'm familiar with), and can fail in extreme
cases. (Try doing a setbuf with a buffer length of 1, or
entering over ten thousand characters, or whatever, in a line.)
It's not reliable.


I agree that that isn't the best choice in general, but to clean an
input buffer from command line it should just do the job.

Regards,

Zeppe
 
J

James Kanze

It does (standard c++03), I didn't quote the entire paragraph, that is:

Behaves as an unformatted input function (as described in 27.6.1.3,
paragraph 1), except that it does not count the number of characters
extracted and does not affect the value returned by subsequent calls to
gcount(). After constructing a sentry object, if rdbuf() is a null
pointer, returns -1 . Otherwise, calls rdbuf()->pubsync() and, if that
function returns -1 calls setstate(badbit) (which may throw
ios_base::failure (27.4.4.3), and returns -1. Otherwise, returns zero.

I didn't quote it because I just wanted to make the point that sync is
defined and it has got a sense for input streams (and actually, just for
input streams, it seems).


I see. But I can't see why filebuf should be the streambuf for cin. cin
is not a ifstream, is an istream, and it should have a basic_streambuf
as associated stream buffer.


I see your point, and usually I think as you do. But in this case, being
a function named flush already present in the iostream, with the same
semantics of fflush, and being sync defined for input streams, I argue
that there is probably something different.


the semantics for basic_streambuf::sync() is (27.5.2.4.2#7):

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.


as the standard says (see above).


I agree that that isn't the best choice in general, but to clean an
input buffer from command line it should just do the job.

Regards,

Zeppe
 

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,774
Messages
2,569,599
Members
45,175
Latest member
Vinay Kumar_ Nevatia
Top