Keyboard input/Obtain a Y or N response: Difference between revisions

From Rosetta Code
Content added Content deleted
(added ruby code)
(→‎{{header|C}}: replaced non-portable code -- fflush(stdin) and conio.h)
Line 45: Line 45:


=={{header|C}}==
=={{header|C}}==
For POSIX compliant systems (in theory that includes WinNT family).
<lang C>
#include<stdio.h>
<lang C>#include <stdio.h>
#include <stdio.h>
#include <termios.h>
#include <unistd.h>
#include <fcntl.h>
void set_mode(int want_key)
{
static struct termios old, new;
if (!want_key) {
tcsetattr(STDIN_FILENO, TCSANOW, &old);
return;
}
tcgetattr(STDIN_FILENO, &old);
new = old;
new.c_lflag &= ~(ICANON);
tcsetattr(STDIN_FILENO, TCSANOW, &new);
}
int get_key(int no_timeout)
{
int c = 0;
struct timeval tv;
fd_set fs;
tv.tv_usec = tv.tv_sec = 0;
FD_ZERO(&fs);
FD_SET(STDIN_FILENO, &fs);


select(STDIN_FILENO + 1, &fs, 0, 0, no_timeout ? 0 : &tv);
if (FD_ISSET(STDIN_FILENO, &fs)) {
c = getchar();
set_mode(0);
}
return c;
}
int main()
int main()
{
{
char ch;
int c;
while(1) {
set_mode(1);
do{
while (get_key(0)); /* clear buffer */
printf("\nDo you want to see this prompt again (Y/N) :");
printf("Prompt again [Y/N]? ");
fflush(stdin);
scanf("%c",&ch);
fflush(stdout);

}while(ch=='y'||ch=='Y');
c = get_key(1);
if(ch=='n'||ch=='N')
if (c == 'Y' || c == 'y') {
printf("\n");
{
continue;
printf("\nYou opted not, so toodleedoo......");
}
}

if (c == 'N' || c == 'n') {
printf("\nWhat the heck !");
printf("\nDone\n");
return 0;
break;
}
}

</lang>
printf("\nYes or no?\n");
}

return 0;
}</lang>

=={{header|Common Lisp}}==
=={{header|Common Lisp}}==



Revision as of 17:46, 28 June 2011

Task
Keyboard input/Obtain a Y or N response
You are encouraged to solve this task according to the task description, using any language you may know.

Obtain a valid Y or N response from the keyboard. The keyboard should be flushed, so that any outstanding keypresses are removed, preventing any existing Y or N keypress from being evaluated. The response should be obtained as soon as Y or N are pressed, and there should be no need to press an enter key.

Ada

<lang Ada> function Yes_Or_No (Prompt : String := "Your answer (Y/N): ") return Boolean is

     Answer : Character;
  begin
     Ada.Text_IO.Put (Prompt);
     loop
        Ada.Text_IO.Get_Immediate (Answer);
        case Answer is
           when 'Y'|'y' => return True;
           when 'N'|'n' => return False;
           when others  => null;
        end case;
     end loop;
  end Yes_Or_No;</lang>

AutoHotkey

<lang AutoHotkey>#NoEnv ; Recommended for increased performance Input, Response,,,y,n

Waits until they press y or n, storing all characters.

StringRight, Out, Response, 1

retrieves the ending character (which will be y or n)

Msgbox %out% If (Out = "y")

   Msgbox You pressed Y

If (Out = "n")

   Msgbox You pressed n

ExitApp </lang>

BASIC

ZX Spectrum Basic

Note that this will also work in GW-BASIC and most QBasic-compatible BASICs if all instances of "GO TO" are changed to "GOTO".

<lang qbasic>10 IF INKEY$<>"" THEN GO TO 10 20 PRINT "Press Y or N to continue" 30 LET k$ = INKEY$ 40 IF k$ = "y" OR k$ = "Y" OR k$ = "n" OR k$ = "N" THEN GO TO 60 50 GO TO 30 60 PRINT "The response was "; k$</lang>

C

For POSIX compliant systems (in theory that includes WinNT family). <lang C>#include <stdio.h>

  1. include <stdio.h>
  2. include <termios.h>
  3. include <unistd.h>
  4. include <fcntl.h>

void set_mode(int want_key) { static struct termios old, new; if (!want_key) { tcsetattr(STDIN_FILENO, TCSANOW, &old); return; }

tcgetattr(STDIN_FILENO, &old); new = old; new.c_lflag &= ~(ICANON); tcsetattr(STDIN_FILENO, TCSANOW, &new); }

int get_key(int no_timeout) { int c = 0; struct timeval tv; fd_set fs; tv.tv_usec = tv.tv_sec = 0;

FD_ZERO(&fs); FD_SET(STDIN_FILENO, &fs);

select(STDIN_FILENO + 1, &fs, 0, 0, no_timeout ? 0 : &tv); if (FD_ISSET(STDIN_FILENO, &fs)) { c = getchar(); set_mode(0); } return c; }

int main() { int c; while(1) { set_mode(1); while (get_key(0)); /* clear buffer */ printf("Prompt again [Y/N]? "); fflush(stdout);

c = get_key(1); if (c == 'Y' || c == 'y') { printf("\n"); continue; }

if (c == 'N' || c == 'n') { printf("\nDone\n"); break; }

printf("\nYes or no?\n"); }

return 0; }</lang>

Common Lisp

<lang lisp>(defun rosetta-y-or-n ()

 (clear-input *query-io*)
 (y-or-n-p))</lang>

Euphoria

<lang Euphoria>integer key

puts(1,"Your answer? (Y/N)\n") while get_key()!=-1 do end while

while 1 do

   key = get_key()
   if key!=-1 and (key = 'Y' or key = 'y' or key = 'N' or key = 'n') then
       exit
   end if

end while

printf(1,"Your response was %s\n",key)</lang>

Inform 7

Keyboard input goes through a virtual machine that's only required to provide blocking input operations, so flushing the buffer isn't possible.

Inform 7 has a built-in function to ask the user for yes-or-no input, but it requires them to press enter afterward: <lang inform7>Qwantz is a room.

When play begins: say "A wizard has turned you into a whale. Is this awesome (Y/N)? "; if the player consents, say "Awesome!"; end the story.</lang>

To read a single key without waiting for enter, we can redefine the function by including a snippet of Inform 6 code: <lang inform7>To decide whether player consents: (- (YesOrNoKey()) -).

Include (- [ YesOrNoKey ch;

   do { ch = VM_KeyChar(); } until (ch == 'y' or 'Y' or 'n' or 'N');
   return ch == 'y' or 'Y';

]; -).</lang>

PicoLisp

<lang PicoLisp>(de yesno ()

  (loop
     (NIL (uppc (key)))
     (T (= "Y" @) T)
     (T (= "N" @)) ) )</lang>

PureBasic

Inkey() returns the character string of the key which is being pressed at the time. <lang PureBasic>PrintN("Press Y or N to continue")

Repeat

 ; Get the key being pressed, or a empty string.
 Key$=UCase(Inkey())
 ;
 ; To Reduce the problems with an active loop
 ; a Delay(1) will release the CPU for the rest
 ; of this quanta if no key where pressed.
 Delay(1)

Until Key$="Y" Or Key$="N" PrintN("The response was "+Key$)</lang>

Python

<lang python>#!/usr/bin/env python

try:

   from msvcrt import getch

except ImportError:

   def getch():
       import sys, tty, termios
       fd = sys.stdin.fileno()
       old_settings = termios.tcgetattr(fd)
       try:
           tty.setraw(sys.stdin.fileno())
           ch = sys.stdin.read(1)
       finally:
           termios.tcsetattr(fd, termios.TCSADRAIN, old_settings)
       return ch

print "Press Y or N to continue" while True:

   char = getch()
   if char.lower() in ("y", "n"):
       print char
       break</lang>
   

REXX

REXX (in general) requires the user to press ENTER when entering text.

Some REXX interpretors have a keyboard read subroutine so that the program can read keyboard keys as they are pressed. <lang rexx>

 do queued()      /*flush the stack if any lines queued.   */
 pull
 end

prompt='Press Y or N for some reason.' /*prompt message*/ ok='Y N' /*acceptable answers (will be uppercase)*/

 do forever
 say              /*write a blank line for visual fidelity.*/
 say prompt       /*prompt the user for an input.          */
 pull ans         /*get the answer(s), also, uppercase it. */
 ans=strip(ans)   /*get rid of leading/trailing blanks.    */
 if ans= then iterate              /*if blank, try again.*/
 if wordpos(ans,ok)\==0 then leave   /*if ans is OK, leave.*/
 end
                  /*as this point, ANS holds a  Y  or  N.  */

</lang>

Ruby

<lang Ruby> def yesno

 begin
   system("stty raw -echo")
   str = STDIN.getc
 ensure
   system("stty -raw echo")
 end
 if str == "Y"
   return true
 elsif str == "N"
   return false
 else
   raise "Invalid character."
 end

end </lang>

Tcl

<lang tcl>proc yesno Template:Message "Press Y or N to continue" {

   fconfigure stdin -blocking 0
   exec stty raw
   read stdin ; # flush
   puts -nonewline "${message}: "
   flush stdout
   while {![eof stdin]} {
       set c [string tolower [read stdin 1]]
       if {$c eq "y" || $c eq "n"} break
   }
   puts [string toupper $c]
   exec stty -raw
   fconfigure stdin -blocking 1
   return [expr {$c eq "y"}]

}

set yn [yesno "Do you like programming (Y/N)"]</lang>