Keyboard input/Flush the keyboard buffer: Difference between revisions
m (moved Keyboard Input/Flush the keyboard buffer to Keyboard input/Flush the keyboard buffer: Capitalization policy) |
(C is incorrect. Add Ruby. The long Ruby solution uses fork, pipe, exec and several more lines of code, only to turn off canonical input mode.) |
||
Line 1: | Line 1: | ||
{{task}} |
{{task|Keyboard input}} |
||
Flush the [[input device::keyboard]] buffer. This reads characters from the keyboard input and discards them until there are no more currently buffered, and then allows the program to continue. ''The program must not wait for users to type anything.'' |
Flush the [[input device::keyboard]] buffer. This reads characters from the keyboard input and discards them until there are no more currently buffered, and then allows the program to continue. ''The program must not wait for users to type anything.'' |
||
Line 28: | Line 28: | ||
<lang basic>10 IF INKEY$ <> "" THEN GO TO 10</lang> |
<lang basic>10 IF INKEY$ <> "" THEN GO TO 10</lang> |
||
[[Category:Keyboard Input]] |
|||
=={{header|C}}== |
=={{header|C}}== |
||
{{incorrect|C|<code>fflush(stdin)</code> only flushes an ''output'' buffer. A correct program might use POSIX tcflush().}} |
|||
<lang C>#include <stdlib.h> |
<lang C>#include <stdlib.h> |
||
#include <stdio.h> |
#include <stdio.h> |
||
Line 56: | Line 56: | ||
=={{header|PureBasic}}== |
=={{header|PureBasic}}== |
||
<lang PureBasic>While Inkey(): Wend</lang> |
<lang PureBasic>While Inkey(): Wend</lang> |
||
=={{header|Ruby}}== |
|||
Each terminal device has an ''input queue'' for keyboard input. We can either flush this input queue, or read it empty. |
|||
Ruby 1.9.3 adds a new library 'io/console', providing IO#iflush to flush and discard the input queue. If its IO object is not a terminal, it raises an error, perhaps Errno::ENODEV. |
|||
{{works with|Ruby|1.9.3}} |
|||
<lang ruby>require 'io/console' |
|||
$stdin.iflush</lang> |
|||
The other option uses IO#read_nonblock to read the input, without any blocking or waiting. This has a caveat: if the terminal uses the ''canonical input mode'', IO reads only entire lines; and if the input queue contains part of a line, IO#read_nonblock cannot discard this last partial line! |
|||
<lang ruby>loop { $stdin.read_nonblock(256) } rescue nil</lang> |
|||
The complete solution calls IO#iflush, or turns off canonical input mode and calls IO#read_nonblock. |
|||
<lang ruby>class IO |
|||
def discard_input |
|||
icanon = false |
|||
if tty? |
|||
begin |
|||
# With Ruby 1.9.3, simply call IO#iflush. |
|||
require 'io/console' |
|||
return iflush |
|||
rescue LoadError |
|||
# Try to run stty(1) to check if this terminal uses |
|||
# canonical input mode. Acts like `stty -a`, but redirects |
|||
# stdin from tty. Works with Ruby 1.8, no Process#spawn. |
|||
r, w, pid = nil |
|||
begin |
|||
r, w = IO.pipe |
|||
pid = fork do |
|||
IO.for_fd(0).reopen(self) # stdin from tty |
|||
IO.for_fd(1).reopen(w) # stdout to pipe |
|||
exec 'stty', '-a' |
|||
end |
|||
w.close; w = nil |
|||
icanon = (not r.read.include? "-icanon") |
|||
rescue |
|||
# stty(1) only works with Unix clones. |
|||
ensure |
|||
pid and Process.wait pid |
|||
w and w.close |
|||
r and r.close |
|||
end |
|||
end |
|||
end |
|||
if icanon |
|||
# Turn off canonical input mode. |
|||
pid = nil |
|||
begin |
|||
pid = fork do |
|||
IO.for_fd(0).reopen(self) # stdin from tty |
|||
exec 'stty', '-icanon' |
|||
end |
|||
ensure |
|||
pid and Process.wait pid |
|||
end |
|||
end |
|||
# Discard input. |
|||
loop { $stdin.read_nonblock(256) } rescue nil |
|||
if icanon |
|||
# Turn on canonical input mode. |
|||
pid = nil |
|||
begin |
|||
pid = fork do |
|||
IO.for_fd(0).reopen(self) # stdin from tty |
|||
exec 'stty', 'icanon' |
|||
end |
|||
ensure |
|||
pid and Process.wait pid |
|||
end |
|||
end |
|||
nil |
|||
end |
|||
end</lang> |
|||
<lang ruby># Demonstration: discard input, then input a line from user. |
|||
puts 'Type anything for 2 seconds.' |
|||
sleep 2 |
|||
$stdin.discard_input |
|||
print 'Enter a line? ' |
|||
if line = $stdin.gets |
|||
then print 'Got line. ', line |
|||
else puts 'No line!' |
|||
end</lang> |
|||
=={{header|Tcl}}== |
=={{header|Tcl}}== |
Revision as of 23:19, 31 August 2011
You are encouraged to solve this task according to the task description, using any language you may know.
Flush the keyboard buffer. This reads characters from the keyboard input and discards them until there are no more currently buffered, and then allows the program to continue. The program must not wait for users to type anything.
Ada
<lang Ada>with Ada.Text_IO; procedure Flushtest is begin
Ada.Text_IO.Put_Line ("Type anything for 2 s"); Delay 2.0; Flush_Input : declare Ch : Character; More : Boolean; begin loop Ada.Text_IO.Get_Immediate (Ch, More); exit when not More; end loop; end Flush_Input; Ada.Text_IO.Put_Line ("Okay, thanks. Here some input from you:"); Ada.Text_IO.Put_Line (Ada.Text_IO.Get_Line);
end Flushtest;</lang>
BASIC
ZX Spectrum Basic
<lang basic>10 IF INKEY$ <> "" THEN GO TO 10</lang>
C
<lang C>#include <stdlib.h>
- include <stdio.h>
int main(void) {
(void) fflush(stdin); return EXIT_SUCCESS;
}</lang>
Euphoria
<lang Euphoria>while get_key()!=-1 do end while</lang>
PicoLisp
<lang PicoLisp>(while (key 10))</lang>
PowerShell
The following uses the special $Host
variable which points to an instance of the PowerShell host application. Since the host's capabilities may vary this may not work in all PowerShell hosts. In particular, this works in the console host, but not in the PowerShell ISE.
<lang powershell>while ($Host.UI.RawUI.KeyAvailable) {
$Host.UI.RawUI.ReadKey() | Out-Null
}</lang>
PureBasic
<lang PureBasic>While Inkey(): Wend</lang>
Ruby
Each terminal device has an input queue for keyboard input. We can either flush this input queue, or read it empty.
Ruby 1.9.3 adds a new library 'io/console', providing IO#iflush to flush and discard the input queue. If its IO object is not a terminal, it raises an error, perhaps Errno::ENODEV.
<lang ruby>require 'io/console' $stdin.iflush</lang>
The other option uses IO#read_nonblock to read the input, without any blocking or waiting. This has a caveat: if the terminal uses the canonical input mode, IO reads only entire lines; and if the input queue contains part of a line, IO#read_nonblock cannot discard this last partial line!
<lang ruby>loop { $stdin.read_nonblock(256) } rescue nil</lang>
The complete solution calls IO#iflush, or turns off canonical input mode and calls IO#read_nonblock.
<lang ruby>class IO
def discard_input icanon = false if tty? begin # With Ruby 1.9.3, simply call IO#iflush. require 'io/console' return iflush rescue LoadError # Try to run stty(1) to check if this terminal uses # canonical input mode. Acts like `stty -a`, but redirects # stdin from tty. Works with Ruby 1.8, no Process#spawn. r, w, pid = nil begin r, w = IO.pipe pid = fork do IO.for_fd(0).reopen(self) # stdin from tty IO.for_fd(1).reopen(w) # stdout to pipe exec 'stty', '-a' end w.close; w = nil icanon = (not r.read.include? "-icanon") rescue # stty(1) only works with Unix clones. ensure pid and Process.wait pid w and w.close r and r.close end end end
if icanon # Turn off canonical input mode. pid = nil begin pid = fork do IO.for_fd(0).reopen(self) # stdin from tty exec 'stty', '-icanon' end ensure pid and Process.wait pid end end
# Discard input. loop { $stdin.read_nonblock(256) } rescue nil
if icanon # Turn on canonical input mode. pid = nil begin pid = fork do IO.for_fd(0).reopen(self) # stdin from tty exec 'stty', 'icanon' end ensure pid and Process.wait pid end end
nil end
end</lang>
<lang ruby># Demonstration: discard input, then input a line from user. puts 'Type anything for 2 seconds.' sleep 2 $stdin.discard_input print 'Enter a line? ' if line = $stdin.gets then print 'Got line. ', line else puts 'No line!' end</lang>
Tcl
<lang tcl># No waiting for input fconfigure stdin -blocking 0
- Drain the data by not saving it anywhere
read stdin
- Flip back into blocking mode (if necessary)
fconfigure stdin -blocking 1</lang>