Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

How to flush STDIN with getc()?

0 views
Skip to first unread message

Lars Eighner

unread,
Aug 6, 2008, 4:10:49 AM8/6/08
to
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?


--
Lars Eighner <http://larseighner.com/> use...@larseighner.com
War on Terrorism: Bad News from the Sanity Front
"In this autumn of anger, even a liberal can find his thoughts turning to ...
torture." --Jonathan Alter,_Newsweek_

Lars Eighner

unread,
Aug 6, 2008, 9:40:32 AM8/6/08
to
In our last episode, <slrng9imqi....@debranded.larseighner.com>, the
lovely and talented Lars Eighner broadcast on comp.lang.perl.misc:

> 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!";

Consider what might be fertilizing the greener grass across the fence.

John W. Krahn

unread,
Aug 6, 2008, 2:07:46 PM8/6/08
to
Lars Eighner wrote:
> In our last episode, <slrng9imqi....@debranded.larseighner.com>, the
> lovely and talented Lars Eighner broadcast on comp.lang.perl.misc:
>
>> 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/;

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
--
Perl isn't a toolbox, but a small machine shop where you
can special-order certain sorts of tools at low cost and
in short order. -- Larry Wall

Lars Eighner

unread,
Aug 6, 2008, 2:25:01 PM8/6/08
to
In our last episode, <SLlmk.61095$nD.52932@pd7urf1no>, the lovely and
talented John W. Krahn broadcast on comp.lang.perl.misc:

> Lars Eighner wrote:
>> In our last episode, <slrng9imqi....@debranded.larseighner.com>, the
>> lovely and talented Lars Eighner broadcast on comp.lang.perl.misc:
>>
>>> 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/;

> 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.

>> 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 ) {

neat.

War hath no fury like a noncombatant.
- Charles Edward Montague

Ben Morrow

unread,
Aug 6, 2008, 3:15:35 PM8/6/08
to

Quoth "John W. Krahn" <jwk...@shaw.ca>:

> Lars Eighner wrote:
>
> > 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 ) {

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

--
You poor take courage, you rich take care:
The Earth was made a common treasury for everyone to share
All things in common, all people one.
'We come in peace'---the order came to cut them down. [b...@morrow.me.uk]

John W. Krahn

unread,
Aug 6, 2008, 3:48:07 PM8/6/08
to
Ben Morrow wrote:
> Quoth "John W. Krahn" <jwk...@shaw.ca>:
>> Lars Eighner wrote:
>>
>>> 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 ) {
>
> 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.

Lars Eighner

unread,
Aug 6, 2008, 4:29:34 PM8/6/08
to
In our last episode, <Xdnmk.61455$nD.56524@pd7urf1no>, the lovely and

talented John W. Krahn broadcast on comp.lang.perl.misc:

> Ben Morrow wrote:


>> Quoth "John W. Krahn" <jwk...@shaw.ca>:
>>> Lars Eighner wrote:
>>>
>>>> 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 ) {
>>
>> 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.

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.

War on Terrorism: Bad News from the Sanity Front

"There's one thing ... that I do like about Rumsfeld, he's just a little bit
crazy, OK"? --Thomas Friedman, _The New York Times_

John W. Krahn

unread,
Aug 6, 2008, 4:43:56 PM8/6/08
to
Lars Eighner wrote:
>
> 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

Peter J. Holzer

unread,
Aug 7, 2008, 7:56:27 AM8/7/08
to
On 2008-08-06 08:10, Lars Eighner <use...@larseighner.com> wrote:
> 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

0 new messages