How to flush STDIN with getc()?

L

Lars Eighner

I'm using perl 5.8.8 on FreeBSD.

I understand that getc() defaults to STDIN when an argument is not
specified, and getc() does not work until ENTER is hit at the keyboard
(i.e. STDIN). However, on the second call to get(), it appears I
get the next character from the same line (which might be the
newline from the ENTER, or might be 'e' if 'yes\n' was typed instead
of 'y\n'.

What's the right way to throw away the junk from the previous line?
 
L

Lars Eighner

the said:
I'm using perl 5.8.8 on FreeBSD.
I understand that getc() defaults to STDIN when an argument is not
specified, and getc() does not work until ENTER is hit at the keyboard
(i.e. STDIN). However, on the second call to get(), it appears I
get the next character from the same line (which might be the
newline from the ENTER, or might be 'e' if 'yes\n' was typed instead
of 'y\n'.
What's the right way to throw away the junk from the previous line?

Nevermind.

It appears getc() is not what I want (athough I am still curious about
the question posed. $answer = <STDIN> seems to be the right solution,
and works in this sub:

sub ask {
$question = shift(@_);
print "$question\n$enter ($aff/$neg): ";
$answer = <STDIN>;
chomp $answer;
$answer =~ s/^(.).*\n/$1/;
if ( $answer eq $aff || $answer eq uc($aff)){
print "Answer is yes.\n";
return 1;
}
if ( $answer eq $neg || $answer eq uc($neg)){
print "Answer is no.\n";
return 0;
}
my $count=1;
while ($count <= 3){
print "$question\n$bad_answer";
$answer = <STDIN>;
chomp $answer;
$answer =~ s/^(.).*\n/$1/;
if ( $answer eq $aff || $answer eq uc($aff)){
print "Answer is yes.\n";
return 1;
}
if ( $answer eq $neg || $answer eq uc($neg)){
print "Answer is no.\n";
return 0;
}
if ( $answer eq $quit || $answer eq uc($quit)){
die ("$quit_req\n");
}
$count = $count + 1;
}
die ("$too_many");
}

where the English values are:

$aff = 'y';
$neg = 'n';
$quit ='q';
$enter = 'enter';
$bad_answer = "No default. Please enter y for yes or n for no or " .
"q to quit\n" .
"Enter (y/n or to quit enter q): ";
$quit_req = "Quit requested. Goodbye!";
$too_many = "Too many tries. Goodbye!";
 
J

John W. Krahn

Lars said:
Nevermind.

It appears getc() is not what I want (athough I am still curious about
the question posed. $answer = <STDIN> seems to be the right solution,
and works in this sub:

sub ask {
$question = shift(@_);
print "$question\n$enter ($aff/$neg): ";
$answer = <STDIN>;
chomp $answer;
$answer =~ s/^(.).*\n/$1/;

chomp() removes the newline so your pattern won't match.
if ( $answer eq $aff || $answer eq uc($aff)){

You can simplify that a bit:

my $answer = <STDIN>;
if ( uc $aff eq uc substr $answer, 0, 1 ) {




John
 
L

Lars Eighner

chomp() removes the newline so your pattern won't match.

You are right. I copied and pasted from one working version, changed
my mind and then tried to make the post agree with new working version,
and obvious did not get the post right.
You can simplify that a bit:
my $answer = <STDIN>;
if ( uc $aff eq uc substr $answer, 0, 1 ) {

neat.
 
B

Ben Morrow

Quoth "John W. Krahn said:
You can simplify that a bit:

my $answer = <STDIN>;
if ( uc $aff eq uc substr $answer, 0, 1 ) {

lc is better than uc when performing case-smashed comparisons, as not
all Unicode characters have a defined 'uc' (Unicode has the concept of
'titlecase', which is distinct from 'uppercase').

This particular comparison could also be written

if ($aff =~ /^\Q$answer/i) {

of course.

Ben
 
J

John W. Krahn

Ben said:
lc is better than uc when performing case-smashed comparisons, as not
all Unicode characters have a defined 'uc' (Unicode has the concept of
'titlecase', which is distinct from 'uppercase').

This particular comparison could also be written

if ($aff =~ /^\Q$answer/i) {

of course.

ITYM:

if ( $answer =~ /^\Q$aff/i ) {

From the OP's code:
where the English values are:

$aff = 'y';
$neg = 'n';
$quit ='q';

So if $answer contains 'yes' then $aff =~ /^\Q$answer/i will not match.



John
 
L

Lars Eighner

the lovely and said:
if ( $answer =~ /^\Q$aff/i ) {
From the OP's code:
So if $answer contains 'yes' then $aff =~ /^\Q$answer/i will not match.

Yes. Perhaps it is advancing geezerhood, but applications which which
burp if I inadvertantly type yes at a y/n prompt rattle me.

I'm still vaguely curious about the best way to flush STDIN so
getc() might work in similar way. I can off course eat the line
in a while loop until I get the \n, but I think there might be something
more elegant I gather the example in the getc documentation is off
to the races when it gets one character, which isn't what I want and
doesn't enlighten me about what to do to flush the keyboard buffer.

It seems to me that opening STDIN should close it before opening if
it already is open, but either this doesn't work as I think it should,
or I haven't got the incantation right.
 
J

John W. Krahn

Lars said:
I'm still vaguely curious about the best way to flush STDIN so
getc() might work in similar way. I can off course eat the line
in a while loop until I get the \n, but I think there might be something
more elegant I gather the example in the getc documentation is off
to the races when it gets one character, which isn't what I want and
doesn't enlighten me about what to do to flush the keyboard buffer.

It seems to me that opening STDIN should close it before opening if
it already is open, but either this doesn't work as I think it should,
or I haven't got the incantation right.

AFAIK you can't flush STDIN, perhaps you want
http://search.cpan.org/~jstowe/TermReadKey-2.30/ReadKey.pm or
http://search.cpan.org/~nuffin/Prompt-ReadKey-0.03/lib/Prompt/ReadKey.pm



John
 
P

Peter J. Holzer

I understand that getc() defaults to STDIN when an argument is not
specified, and getc() does not work until ENTER is hit at the keyboard
(i.e. STDIN).

Your understanding is incomplete. getc just gets the next byte from the
input stream. It doesn't care about newlines. The reason why getc
"doesn't work" until you hit enter is that the terminal driver is in a
"line editor" mode: Before you hit enter, you can always erase and
change what you typed. Only when you hit enter (or ctrl-D) the line is
appended to the input stream. Perldoc -f getc telly you how to switch
the terminal into "one character at a time" mode.

hp
 

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,768
Messages
2,569,574
Members
45,048
Latest member
verona

Latest Threads

Top