2

代码:

main = do
         putStrLn "4917 Microprocessor\nEnter the Machine Code to be run: "
         inp <- getContents
         putStrLn "The output of the Program is:"
         fState <- ((runStateT _4917) . construct . parse) inp
         args <- getArgs
         if elem "-v" args then putStrLn ("\nFinal state was: " ++ (show . snd) fState) else return ()
         putStrLn "\n================================ RESTART ================================"
         main
        where parse xs = array (0,15) $
                         zip [0..15] $
                         take 16 $
                         map ((makeArbInt 4) . read) (words (filter ((/=)'.') xs)) ++ repeat (makeArbInt 4 0)
              construct xs = Program xs z z z z 0 False
              z = (makeArbInt 4 0)

还有更多,但这是相关部分。基本上第 3 行需要多次评估,但 getContents 正在关闭标准输入句柄:

4917: <stdin>: hGetContents: illegal operation (handle is closed)

有没有办法重新打开手柄?还是某种阻止 getContents 这样做的方法?(也许我发送了错误的信号。我在 Linux 上通过 Ctrl-D EOF 发送。也许我应该使用 EOT 或其他东西?)

编辑:我已经设法获得所需的行为,但它不会移植到 Windows。

mystdin <- openFile "/dev/tty" ReadMode
inp <- hGetContents mystdin

新问题:是否有一种通用的方法可以可移植地打开标准输入的句柄?

4

3 回答 3

3

您无法阻止getContents关闭文件,并且关闭的文件保持关闭状态。

在我看来,您需要一些其他功能。通常,当您读取文件的某些部分时,您知道何时停止(行尾,流中的某些字节)。所以是的:如果您无法解析正在读取的数据并检测到它何时完成,您应该使用某种分隔符(可能是 EOT,或空行,或数据中不太可能出现的特殊文本,如__END__)。

于 2013-06-15T13:14:37.133 回答
3

让他们输入一个空行来结束输入:

getContents2 = helper "" where 
  helper str = do
    a <- getLine
    if "" == a then return str
    else helper (str++"\n"++a)

您也可以让他们通过输入一个空行来表示会话结束。

于 2013-06-15T13:55:49.787 回答
1

要可移植地打开 stdin 的句柄,请在现有的 stdio 句柄上使用 hDuplicate 函数来获取新的句柄:

mystdin <- hDuplicate stdin
inp <- hGetContents mystdin

确保永远不要关闭原始标准输入,以便您可以根据需要进行更多重复。(我不确定这是否是好的 Haskell 风格)

于 2013-06-15T14:14:20.047 回答