有没有办法在Haskell中从控制台读取整数?我要求的东西非常像C ++的cin或Java的Scanner.nextInt()。
我的意思是,考虑到这个输入:
1 2 3
2 3
4 25 12 7
1
我应该能够全部阅读它们,而不是同时阅读它们(可能会阅读其中的4个,进行一些计算,然后阅读其余部分)忽略它们分开的事实。
答案 0 :(得分:5)
最简单的解决方案可能是
getAll :: Read a => IO [a]
getAll = fmap (fmap read . words) getContents
getInts :: IO [Int]
getInts = getAll
将所有输入读入单个列表。
答案 1 :(得分:1)
如果有疑问,请使用Parsec!(并非总是如此,而不是真的,但是谁在乎)
import Text.ParserCombinators.Parsec
import Text.Parsec.Numbers
value = do
spaces
num <- parseFloat
return num
line = many value
然后“冲洗并重复”,getLine
直到你EOF。
注意:你可以在没有 Parsec的情况下使用read
和朋友进行,但这种方式更易扩展,更适用于更复杂的语法。
答案 2 :(得分:0)
使用Parsec:
import Text.ParserCombinators.Parsec
import Text.Parsec.Numbers
import Control.Applicative ((*>), (<*))
line = spaces *> many1 (parseFloat <* spaces)
main = putStrLn "Enter numbers:" >> fmap (parse line "") getLine >>= print
运行它:
$ ghc parsenums.hs
$ ./parsenums
Enter numbers:
345 23 654 234
[345.0,23.0,654.0,234.0]
更多&#34;手册&#34;这样做的方法就像:
import Data.Char (isDigit, isSpace)
getInts :: String -> [Int]
getInts s = case span isDigit (dropWhile isSpace s) of
("", "") -> []
("", s) -> error $ "Invalid input: " ++ s
(digits, rest) -> (read digits :: Int) : getInts rest
可以更清楚地看到它是如何工作的。事实上,这是一个完全从头开始的人:
getInts :: String -> [Int]
getInts s = case span isDigit (dropWhile isSpace s) of
("", "") -> []
("", s) -> error $ "Invalid input: " ++ s
(digits, rest) -> strToInt digits : getInts rest
isDigit :: Char -> Bool
isDigit c = '0' <= c && c <= '9'
isSpace :: Char -> Bool
isSpace c = c `elem` " \t\n\r"
charToInt :: Char -> Int
charToInt c = fromEnum c - 48
strToInt :: String -> Int
strToInt s = go 0 s where
go n [] = n
go n (c:rest) = go (n * 10 + charToInt c) rest