2010-06-06 71 views
24

後,我已經試過這樣:哈斯克爾:立即讀取從控制檯輸入字符,而不是換行

main = do 
    hSetBuffering stdin NoBuffering 
    c <- getChar 

但等到被按下,這不是我想要的輸入。我想在用戶按下後立即讀取角色。

我使用的Windows 7

GHC v6.12.1編輯:解決方法我是從GHC移動到WinHugs,它正確地支持此功能。

+2

這不是一個真正的好的解決方法。真正的解決方法是明確選擇字符緩衝IO;通過使用系統conio.h中的getch。 Artelius的鏈接包含示例代碼。 – jrockway 2010-06-07 01:11:50

+0

這是一個很好的解決方法,如果它適合他!使用不具有錯誤的不同工具是有道理的。如果你不需要最新的ghc編譯器的語言特性,WinHugs比我的經驗快ghci或winghci。它沒有大驚小怪,看起來更好。編輯代碼時,您也不需要':r',我喜歡它。 – AndrewC 2012-11-13 23:02:52

+0

它與'main = do hSetBuffering stdin NoBuffering;交互$ map Data.Char.toUpper'?就我而言,它會在任何輸出出現之前等待一個新行。 (Ubuntu,GHC 7.6.3。) – ominug 2015-06-28 13:18:24

回答

18

可能是一個錯誤:

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)轉載,同時使用的cmd.exe和command.com在Windows XP專業版...

4

嗯..其實我看不到這功能是一個錯誤。當你讀stdin這意味着你想用一個「文件」來工作,當你開始緩衝時,你說的是不需要讀取緩衝區。但這並不意味着模擬該「文件」的應用程序不應該使用寫入緩衝區。對於Linux,如果你的終端處於「icanon」模式,它將不會發送任何輸入,直到發生一些特殊事件(如Enter按或Ctrl + D)。 Windows中的控制檯可能有一些類似的模式。

+0

謝謝。聽起來很真實,但是如果你看到錯誤描述:我真正想問的是什麼,所以現在我要標記Artelius的答案。 – Steves 2010-06-06 12:00:52

+3

至少它在Windows和Linux下的工作方式不同。在linux下,Steves發佈的代碼無需等待。所以我認爲這是一個錯誤,應該修復。 – 2012-10-16 17:15:09

+0

這是(部分)不正確。當使用控制檯仿真軟件或MinGW控制檯時,緩衝仍然被忽略。 Windows忽略OS級別的緩衝,而不是控制檯級別的緩衝。 – YoYoYonnY 2016-03-11 22:16:34

17

是的,這是一個錯誤。這裏有一個解決辦法,以節省鄉親點擊和滾動:

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

所以,你可以通過調用getHiddenChar取代調用getChar

注意這是一個解決方法,僅適用於Windows上的ghc/ghci。例如,winhugs沒有bug,這個代碼在winhugs中不起作用。

+1

我喜歡這個解決方案。但是,請注意,'unsafe'會導致阻塞調用'getch'來阻塞程序中的所有其他線程。我是Hackage的['hidden-char'](http://hackage.haskell.org/package/hidden-char)包的作者,它使用不安全的FFI具有此函數的變體。 – 2017-07-20 20:45:44

1

Haskeline包爲我工作。

如果您需要單個字符,則只需稍微更改示例。

  1. getInputLine成爲getInputChar
  2. "quit"成爲'q'
  3. ++ 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