2012-04-12 7 views
4

Ziel ist es, das Spiel von Nim in Haskell als Schulaufgabe zu codieren. Ich bin neu in Haskell und bekomme seltsames Verhalten, wenn ich versuche, Eingaben zu lesen.Haskell: Grund Lesen Int

Das Ziel ist, zwei ganze Zahlen zu lesen. Statt die erste Nachricht zu drucken, dann auffordert und dann zum zweiten geht, druckt er nur die zwei Nachrichten, und ich bin nicht in der Lage den richtigen Eingang zu geben. Was ist hier falsch?

type Board = [Int]  -- The board 
type Heap = Int  -- id of heap 
type Turn = (Int, Int) -- heap and number of stars to remove 

readInt :: String -> IO Int 
readInt msg = do putStr (msg ++ "> ") 
       inp <- getChar 
       let x = ord inp 
       return x 

readTurn :: Board -> IO(Turn) 
readTurn b = do heap <- readInt "Select heap:" 
       amt <- readInt "Select stars:" 
       print heap 
       print amt 
       return(heap, amt) 
+1

Warum verwenden Sie 'getChar'? Es ist offensichtlich, dass dies nicht sehr gut zum Lesen von ganzen Zahlen ist, oder? – leftaroundabout

+0

@leftaroundabout, es ist nicht so offensichtlich. In einigen Situationen möchte man vielleicht jedes Zeichen als eine separate Ganzzahl behandeln (basierend auf ASCII oder was auch immer), wie es hier geschrieben wurde; es ist ein wenig, äh, unkonventionell und nicht das, was das Poster will, aber es ist offensichtlich nicht falsch. Immerhin ist 'getChar >> = zurück. ord 'hat den erwarteten Typ: 'IO Int'. – huon

Antwort

7

Das Problem ist, dass stdout zeilen gepuffert standardmäßig, was bedeutet, dass nichts ausgegeben wird, bis Sie eine neue Zeile zu drucken. Es gibt zwei Möglichkeiten, dies zu beheben:

  1. Verwenden Sie hFlush stdout nach dem Drucken der Aufforderung, den Puffer zu leeren.
  2. Verwenden hSetBuffering stdout NoBuffering zu Beginn des Programms Ausgabepufferung zu deaktivieren.

Auch mit getChar und ord wird ein einzelnes Zeichen lesen und Ihnen seine ASCII-Wert geben, das ist wahrscheinlich nicht das, was Sie wollten. Um eine Nummer zu lesen und zu analysieren, verwenden Sie :

+0

Danke, es funktioniert jetzt! – user1329182

+0

@ user1329182, wenn hammar Antwort Ihre Frage gelöst, geben Sie dies bitte durch die Antwort zu akzeptieren. Vielen Dank. – Gangadhar

1

readChar liest jeweils nur ein Zeichen. Ich nehme an, Sie möchten stattdessen eine ganze Zeile lesen, sie in eine Zahl umwandeln (möglicherweise mit mehr als einer Ziffer) und fortfahren. Sie müssen getLine :: IO String und read :: Read a => String -> a verwenden:

readInt :: String -> IO Int 
readInt msg = do 
    putStr (msg ++ "> ") 
    hFlush stdout 
    inp <- getLine 
    return (read inp) 
+2

Oder, einfacher, 'readLn'. – leftaroundabout

+0

@leftaroundabout: sicher, aber ich wollte, dass ihm ein Minimum an Änderungen von seiner Lösung geben, ist es seine Hausaufgaben, nachdem all :) –

+0

Da es nicht stdout diesen Druck, den Text nicht hFlush nach den Wert in einigen Fällen – sandino