這就是我到目前為止所擁有的。目前,它掛起并且什么也不做。請注意,我需要能夠從這個程式 rot-N 接收資料,并根據它所說的在正確的時間發回資料。有必要在不安裝任何額外有趣的模塊的情況下發生這種情況。我只需要知道執行此操作的魔法詞是什么,因為我無法在其他任何地方找到它們。
import Data.Array
import System.Process
import System.IO
import Text.Printf
--definition for the decrypt function goes here (I'm not going to write it out because it's not important)
main = do
--create process with pipes
(Just hin, Just hout, _, ph) <- createProcess (shell "./rot-N"){ std_in = CreatePipe, std_out = CreatePipe }
--discard first line of std_out to the console
putStrLn =<< hGetLine hout
--bind second line of std_out to the name "ciphertext"
ciphertext <- hGetLine hout
--discard third line of std_out
putStrLn =<< hGetLine hout
putStrLn ciphertext
--generate array of decrypted strings
let decryptedStrings = listArray (0,25) $ zipWith decrypt [0..25] $ repeat ciphertext
--print these strings to the console in order
mapM_ (uncurry $ printf "d: %s\n") $ assocs decryptedStrings
putStrLn "Select the correct string"
number <- getLine >>= return . (read :: Int)
hPutStrLn hin $ decryptedStrings ! number
hClose hin
--I assume that this makes the program finish whatever it would do normally
--(of course I want all of its std_out to get sent to the console as normal)
waitForProcess ph
hClose hout
uj5u.com熱心網友回復:
問題是它rot-N有一點錯誤。列印提示后它不會重繪 輸出。當rot-N從命令列運行時,您不會注意到這一點,因為當 stdout 連接到終端時,輸出默認是行緩沖的,因此每次rot-N寫入一整行時,它都會立即在控制臺上得到輸出。但是,當rot-N通過管道運行時,輸出是“塊緩沖”的,并且多個輸出行累積而不被輸出,除非它們被顯式重繪 。當rot-N暫停等待輸入時,它仍然沒有重繪 任何緩沖輸出。因此,兩個程式都卡在等待對方的第一行輸出。
您可以使用以下 C 程式觀察問題:
#include <stdio.h>
int main()
{
char buffer[4096];
puts("I don't know how to write C!");
fgets(buffer, sizeof(buffer), stdin);
return 0;
}
如果你直接從 shell 運行這個程式,你會在它暫停等待你的輸入之前得到輸出。
$ ./c_program
I don't know how to write C!
<pauses for input>
如果通過 管道輸出cat,它會立即要求輸入而不列印任何內容:
$ ./c_program | cat
<pauses for input>
如果您輸入一行,您將在程式終止后得到輸出。(程式終止強制重繪 。)
如果通過重繪 輸出來修復 C 程式:
// fix #1
#include <stdio.h>
int main()
{
char buffer[4096];
puts("I don't know how to write C!");
fflush(stdout);
fgets(buffer, sizeof(buffer), stdin);
return 0;
}
或通過在程式開始時更改為行緩沖:
// fix #2
#include <stdio.h>
int main()
{
char buffer[4096];
setlinebuf(stdout);
puts("I don't know how to write C!");
fgets(buffer, sizeof(buffer), stdin);
return 0;
}
那么即使以./c_program | cat.
現在,由于rot-N可能只打算以互動方式運行,因此作者可能不會認為這是一個真正的錯誤。假設他們拒絕修復他們的程式,解決這個問題的最簡單方法是使用stdbuf應該在任何 Linux 安裝上都可用的實用程式。通過運行:
stdbuf -oL ./name_of_broken_program
這將嘗試修改程式標準輸出的緩沖,使其成為行緩沖。請注意,這只適用于使用 C 庫 I/O 函式的程式。 因此,它應該適用于 C 和 C 程式,但它尤其不適用于 Haskell 程式。
無論如何,假設rot-N是一個 C 程式或類似程式,你會想要:
(Just hin, Just hout, _, ph) <-
createProcess (shell "stdbuf -oL ./rot-N") { std_in = CreatePipe, std_out = CreatePipe }
請注意,您幾乎在自己的程式中引入了類似的錯誤。你寫過:
hPutStrLn hin $ str
但是hin是塊緩沖的,因此該陳述句實際上不會導致將輸出發送到rot-N行程,直到下一次重繪 。最好的做法是hin在呼叫后設定為行緩沖createProcess:
hSetBuffering hin LineBuffering
或者在通話hFlush后hPutStrLn hin呼叫:
hPutStrLn hin $ str
hFlush hin
幸運的是,在您的程式中,您hClose hin在發送strwhich 后會執行隱式重繪 。
最后一點,如果您希望尾隨輸出來自rot-N控制臺,您需要將其復制到那里。您的程式的以下修改版本可能會起作用:
import Data.Array
import System.Process
import System.IO
import Text.Printf
-- dummy decrypt function
decrypt :: Int -> String -> String
decrypt i str = "encryption " show i " of " str
main = do
-- change #1: use stdbuf utility to set line buffering
(Just hin, Just hout, _, ph) <-
createProcess (shell "stdbuf -oL ./rot-N")
{ std_in = CreatePipe, std_out = CreatePipe }
putStrLn =<< hGetLine hout
ciphertext <- hGetLine hout
putStrLn =<< hGetLine hout
putStrLn ciphertext
let decryptedStrings = listArray (0::Int,25) $ zipWith decrypt [0..25] $ repeat ciphertext
mapM_ (uncurry $ printf "d: %s\n") $ assocs decryptedStrings
putStrLn "Select the correct string"
-- change #2: it's polite to flush our own prompts in
-- case someone wants to use *our* program via pipes
hFlush stdout
-- change #3: your version caused a type error. Try this one.
number <- read <$> getLine
hPutStrLn hin $ decryptedStrings ! number
-- note: if you decide you need to delay the `hClose in` for
-- some reason, add an `hFlush hin` to make sure the string is
-- sent to the rot-N process
hClose hin
-- change #4: copy all remaining output
putStr =<< hGetContents hout
waitForProcess ph
hClose hout
轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/512517.html
下一篇:為什么這個C輸入函式會崩潰?
