g++ question, bug?

K

Kevin Stern

Hi All,

Here is a program I wrote and compiled using g++

#include <iostream>
int main() {
char a;
std::cin.get(a);
std::cout << a;
std::cin.ignore(100, '\n');
}

The problem is ... I expect that if I type one or more characters when
the program pauses for input on the cin.get, the cin.ignore will find
a '\n' on the input stream and not pause. Unfortunately, it pauses!
Any ideas?
 
R

Ron Natalie

Kevin Stern said:
The problem is ... I expect that if I type one or more characters when
the program pauses for input on the cin.get, the cin.ignore will find
a '\n' on the input stream and not pause. Unfortunately, it pauses!
Any ideas?

THis has nothing to do with either C++ or your particular implementation.
It has to do with the way the terminal interface works on your system
(presumably UNIX). The default mode on UNIX buffers up your typing
until you press enter (or newline or return depending on the configuration).
This allows you to use things like the backspace and line kill keys without
having to bulid that behavior into every program.

Look up "RAW" or "CBREAK" modes in the manual (may be under stty or ioctl).
 
K

Kevin Stern

Thanks for the info ... I am left with a couple of questions, though.

I have created the following program:

#include <iostream>

int main() {
char a;
char nl = (char) 10;
std::cout << "Enter: ";
while (a != 'g') {
std::cin.get(a);
std::cout << "a=" << (int)a;
//std::cin.ignore(500, nl);
}
std::cout << "Gimme Input: ";
std::cin >> a;
}

If I hit a key, say j, and then [enter] it outputs:

a=106a=10

If I uncomment the cin.ignore ... the ignore statement waits for me to
hit enter!

The reason this looks like a bug is that if my cin.get can find a
character on the input stream with ascii code 10 (i.e. the enter key),
then how can it be explained that the cin.ignore cannot find one and
waits for the enter key to be hit?

I don't see what this has to do with buffering input, if someone could
explain a bit more about this buffer ... I assume it buffers the input
until the enter key is hit and then dumps the buffer to the input
stream ... this should not screw up my program.

Thanks.
 
K

Kevin Stern

Ok, tell me THIS makes any sense!


Program:

#include <iostream>

int main() {
char a;
char nl = (char) 10;
while (a != 'g') {
std::cout << "Enter: ";
std::cin.get(a);
std::cout << "a=" << (int)a << std::endl;
std::cin.ignore();
std::cout << "end ignore" << std::endl;
}
std::cout << "Gimme Input: ";
std::cin >> a;
}

Output:
____________________________________________________
Enter: a[Enter Key]
a=97
b[Enter Key]
end ignore
Enter: a=98
c[Enter Key]
end ignore
Enter: a=99
[Enter Key]
end ignore
Enter: a=10
[Enter Key]
[Enter Key]
end ignore
Enter: a=10
f[Enter Key]
end ignore
Enter: a=10
_________________________________________________
 
K

Kevin Goodsell

Kevin Stern wrote:

(Please don't top-post. Read section 5 of the FAQ for posting
guidelines: http://www.parashift.com/c++-faq-lite/)
Thanks for the info ... I am left with a couple of questions, though.

I have created the following program:

#include <iostream>

int main() {
char a;

'a' is not initialized
char nl = (char) 10;

Very bad idea.

1) Don't assume a particular value for any given character. A newline is
'\n'. The value representing it could be just about anything.

2) Don't use C-style casts. Use C++ cast operators (static_cast,
dynamic_cast, const_cast, reinterpret_cast) instead. C-style casts are
far too dangerous.

3) Don't cast at all unless you absolutely have to. There's no reason
for this cast, especially if you replace the 10 with '\n'.
std::cout << "Enter: ";
while (a != 'g') {

Attempting to use the uninitialized variable 'a' invokes undefined behavior.

Sorry, I'm not addressing your actual question, it looks like that's
been handled. I just wanted to point out these problems.

-Kevin
 
K

Kevin Stern

(Please don't top-post. Read section 5 of the FAQ for posting

Will do.
'a' is not initialized
True.


Very bad idea.

Let me clarify. I used \n ... ignore did not work, I read the std.
input and I kept getting the character that I pressed plus a character
with ascii value 10 (the enter key). Just in case the \n was giving
problems I figured I'd use the actual ascii value that I wanted to
ignore.
2) Don't use C-style casts. Use C++ cast operators (static_cast,
dynamic_cast, const_cast, reinterpret_cast) instead. C-style casts are
far too dangerous.

I think we're off topic here :)
3) Don't cast at all unless you absolutely have to. There's no reason
for this cast, especially if you replace the 10 with '\n'.

Still a bit off topic.
Attempting to use the uninitialized variable 'a' invokes undefined behavior.

a is initialized with the std::cin.get so it's something from the
input stream ... you seem to be missing the point ... this is a test
program not something I'm selling.
Sorry, I'm not addressing your actual question, it looks like that's
been handled. I just wanted to point out these problems.

Yep. Nope. Thanks.
 
K

Kevin Goodsell

Kevin said:
Let me clarify. I used \n ... ignore did not work, I read the std.
input and I kept getting the character that I pressed plus a character
with ascii value 10 (the enter key). Just in case the \n was giving
problems I figured I'd use the actual ascii value that I wanted to
ignore.

I'm not sure I understand, but it sounds like you ran into a problem
using your input stream. ignore() with a sufficiently large 1st argument
should remove whatever's left of the line, including the '\n' (assuming
that's what you use for the terminator). If that isn't the behavior you
observed then there's a problem with the code or the library. The code
you posted had the ignore() call commented out. It looks like it would
have worked (well, sort of) with that call in place.
I think we're off topic here :)

Not at all. We're talking about C++, which is the topic of this group.
If you meant that we are straying from your question, well, I never saw
the original post, and it appears from the replies that it was a
platform-specific problem, so technically that's the discussion that
would be off-topic.
Still a bit off topic.

Nope, perfectly on-topic.
a is initialized with the std::cin.get so it's something from the
input stream ... you seem to be missing the point ... this is a test
program not something I'm selling.

I'm not missing any point, because I was not addressing any particular
point. I was talking about the code itself, which does, in fact, invoke
undefined behavior due to the error I pointed out. 'a' is obviously NOT
initialized by the std::cin.get, since you are quite clearly testing 'a'
*before* that call occurs. Hence, you are examining the value of a
variable that is indeterminate, and the behavior is undefined.
Yep. Nope. Thanks.

Your problem has not been handled?

....

OK, fair enough. Let me take another look. Here's the code (with changes
to make it well-defined):

#include <iostream>

int main() {
char a = 0; // initialized
// char nl = (char) 10; // no need for this
std::cout << "Enter: ";
while (a != 'g') {
std::cin.get(a);
std::cout << "a=" << (int)a;
//std::cin.ignore(500, '\n');
}
std::cout << "Gimme Input: ";
std::cin >> a;

return 0; // added (not strictly required)
}

With this, I see output similar to what you reported, and I'm not
surprised. Now, if I uncomment the ignore() call it waits for a line of
input, then gives the character value of the first character in that
line, and waits for another line of input (until the first character is
'g'). This is the expected behavior. You said:

If I uncomment the cin.ignore ... the ignore statement waits for me to
hit enter!

The reason this looks like a bug is that if my cin.get can find a
character on the input stream with ascii code 10 (i.e. the enter key),
then how can it be explained that the cin.ignore cannot find one and
waits for the enter key to be hit?

I don't quite understand this. Neither get() nor ignore() can find the
'enter' value unless you press 'enter'. Presumably, your keyboard input
is something like this: <a><enter><p><enter>. Now, if the ignore() call
is not present, get() finds 'a', 'enter', 'p', 'enter' in that order,
and the program outputs the value for each (four total). With the ignore
call, get() finds 'a', then ignore() removes the 'enter', then get()
finds 'p', then ignore() removes the second 'enter'.

If this doesn't help you understand what is happening, or if you believe
what I'm describing is not what you are observing, then please clarify
what you expected and what you actually observed.

-Kevin
 

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
474,141
Messages
2,570,817
Members
47,367
Latest member
mahdiharooniir

Latest Threads

Top