我试过这个:
main = do
hSetBuffering stdin NoBuffering
c <- getChar
但它会等到按下输入,这不是我想要的。我希望在用户按下后立即阅读该字符。
我在Windows 7上使用ghc v6.12.1。
编辑:我的解决方法是从GHC转移到WinHugs,它正确地支持了这一点。
答案 0 :(得分:19)
可能是个错误:
http://hackage.haskell.org/trac/ghc/ticket/2189
以下程序重复输入的字符,直到按下退出键。
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中正常工作(sep 2006版)。但是,GHC 6.8.2在按下回车键之前不会重复这些字符。使用所有GHC可执行文件(ghci,ghc,runghc,runhaskell),在Windows XP Professional上同时使用cmd.exe和command.com重现该问题...
答案 1 :(得分:19)
是的,这是一个错误。这是一个解决方法来保存人们点击和滚动:
{-# 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
因此,您可以通过调用getChar
替换对getHiddenChar
的来电。
请注意,这是针对Windows上的ghc / ghci的解决方法。例如,winhugs没有错误,这段代码在winhugs中不起作用。
答案 2 :(得分:3)
嗯..实际上我看不出这个功能是个bug。当您阅读stdin
表示您想要使用“文件”时,当您开始缓冲时,您说不需要读取缓冲区。但这并不意味着模拟“文件”的应用程序不应该使用写缓冲区。对于Linux,如果您的终端处于“icanon”模式,它将不会发送任何输入,直到发生某些特殊事件(如按下Enter或Ctrl + D)。可能Windows中的控制台有一些类似的模式。
答案 3 :(得分:2)
Haskeline包对我有用。
如果您需要单个字符,那么只需稍微更改一下样本。
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