windows Haskell:立即从控制台读取输入字符,而不是在换行符之后
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/2983974/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Haskell: read input character from console immediately, not after newline
提问by Steves
I've tried this:
我试过这个:
main = do
hSetBuffering stdin NoBuffering
c <- getChar
but it waits until the enter is pressed, which is not what I want. I want to read the character immediately after user presses it.
但它一直等到按下回车键,这不是我想要的。我想在用户按下后立即读取字符。
I am using ghc v6.12.1 on Windows 7.
我在 Windows 7 上使用 ghc v6.12.1。
EDIT: workaround for me was moving from GHC to WinHugs, which supports this correctly.
编辑:我的解决方法是从 GHC 转移到 WinHugs,它正确支持这一点。
采纳答案by Artelius
Might be a bug:
可能是一个错误:
http://hackage.haskell.org/trac/ghc/ticket/2189
http://hackage.haskell.org/trac/ghc/ticket/2189
The following program repeats inputted characters until the escape key is pressed.
import IO import Monad import Char main :: IO () main = do hSetBuffering stdin NoBuffering inputLoop inputLoop :: IO () inputLoop = do i <- getContents mapM_ putChar $ takeWhile ((/= 27) . ord) i
Because of the hSetBuffering stdin NoBuffering line it should not be necessary to press the enter key between keystrokes. This program works correctly in WinHugs (sep 2006 version). However, GHC 6.8.2 does not repeat the characters until the enter key is pressed. The problem was reproduced with all GHC executables (ghci, ghc, runghc, runhaskell), using both cmd.exe and command.com on Windows XP Professional...
以下程序重复输入的字符,直到按下转义键。
import IO import Monad import Char main :: IO () main = do hSetBuffering stdin NoBuffering inputLoop inputLoop :: IO () inputLoop = do i <- getContents mapM_ putChar $ takeWhile ((/= 27) . ord) i
由于 hSetBuffering stdin NoBuffering 行,因此不必在两次击键之间按 Enter 键。该程序在 WinHugs(2006 年 9 月版本)中正常运行。但是,GHC 6.8.2 在按下回车键之前不会重复字符。在 Windows XP Professional 上使用 cmd.exe 和 command.com 的所有 GHC 可执行文件(ghci、ghc、runghc、runhaskell)都重现了该问题...
回答by AndrewC
Yes, it's a bug. Here's a workaround to save folks clicking and scrolling:
是的,这是一个错误。这是一种避免人们点击和滚动的解决方法:
{-# LANGUAGE ForeignFunctionInterface #-}
import Data.Char
import Foreign.C.Types
getHiddenChar = fmap (chr.fromEnum) c_getch
foreign import ccall unsafe "conio.h getch"
c_getch :: IO CInt
So you can replace calls to getChar
with calls to getHiddenChar
.
因此,您可以将调用替换为getChar
调用getHiddenChar
。
Note this is a workaround just for ghc/ghci on Windows. For example, winhugs doesn't have the bug and this code doesn't work in winhugs.
请注意,这是仅适用于 Windows 上的 ghc/ghci 的解决方法。例如,winhugs 没有错误,并且此代码在 winhugs 中不起作用。
回答by ony
Hmm.. Actually I can't see this feature to be a bug. When you read stdin
that means that you want to work with a "file" and when you turn of buffering you are saying that there is no need for read buffer. But that doesn't mean that application which is emulating that "file" should not use write buffer. For linux if your terminal is in "icanon" mode it doesn't send any input until some special event will occur (like Enter pressed or Ctrl+D). Probably console in Windows have some similar modes.
嗯.. 其实我看不出这个功能是一个错误。当您阅读时stdin
,这意味着您想要使用“文件”,而当您关闭缓冲时,您是在说不需要读取缓冲区。但这并不意味着模拟“文件”的应用程序不应该使用写缓冲区。对于 linux,如果您的终端处于“icanon”模式,它不会发送任何输入,直到发生某些特殊事件(例如按下 Enter 或 Ctrl+D)。Windows 中的控制台可能有一些类似的模式。
回答by romc
The Haskelinepackage worked for me.
该Haskeline包对我来说有效。
If you need it for individual characters, then just change the sample slightly.
如果您需要单个字符,则只需稍微更改示例即可。
getInputLine
becomesgetInputChar
"quit"
becomes'q'
++ input
becomes++ [input]
getInputLine
变成getInputChar
"quit"
变成'q'
++ input
变成++ [input]
main = runInputT defaultSettings loop
where
loop :: InputT IO ()
loop = do
minput <- getInputChar "% "
case minput of
Nothing -> return ()
Just 'q' -> return ()
Just input -> do outputStrLn $ "Input was: " ++ [input]
loop