2

几乎一无所知,我正在阅读大量教程和代码示例以了解Haskell的 IO,但我仍然不清楚。

所有的例子都是这样的:

main = do  
    putStrLn "Hello, what's your name?"  
    name <- getLine  
    putStrLn ("Hey " ++ name ++ ", welcome !") 

他们从 IO 读取字符串,还有许多其他示例对我不理解的输入进行了一些自定义。

我的问题很简单:如何在C中使用格式字符串读取Int,Float或like using DoubleCharscanf

任何人都可以帮助我清楚地解释 IO 自定义或技巧吗?

提示:如果代码带有一个很棒的 main 函数 - 它会使测试更容易。

我在CC++JavaC#和.MatlabPHP

4

3 回答 3

4

最直接的方法是使用read(您通常必须提供显式类型),如

main = do  
    putStrLn "Hello, what's your age?"  
    age <- liftM read getLine :: IO Int
    putStrLn ("Hey " ++ (show age)  ++ ", welcome !")

如果您知道字符串仅包含单个值(如果它无法将字符串解析为所需的数据类型,则会引发异常),则此方法效果很好。对于更复杂的解析,我通常直接跳到Parsec解析器组合库(它可能是您在 Haskell 中需要的所有解析器,而且还能以最小的开销处理简单的工作)。如果这不适合您,快速搜索 Hackage 会发现一些候选库提供了更简单的类似 scanf 的功能:请参阅Text.XFormat.ReadText.PrintScan等,尽管我个人不能保证两者。

于 2012-12-08T08:48:12.610 回答
3

isturdy 的答案是有效的,但如果你想要更简单的东西,最简单的方法是一步一步地做:

main = do
    i' <- getLine -- some integral input; it will be received as a String
    d' <- getLine -- some floating input; also will be received as a String
    let i = read i' :: Int -- i is an Int now
        d = read d' :: Double -- d is a Double now
    putStr "" -- so that GHC doesn't complain

的类型getLineIO String- 它将输入读取为String. read然后,您可以使用(并指示您想要的类型)更改此字符串的类型。至于类似scanf的体验,您可以尝试这样的事情:

main = do
    inp <- getLine -- the input is an Int, a String and a Double, like: 4 derp 2.7
    let list = words inp -- divide the input String into a list of Strings
        val = read (list !! 0) :: Int -- val equals 4, its type is Int
        str = list !! 1 -- str is a String ("derp"), no additional action required
        dbl = read (list !! 2) :: Double -- dbl equals 2.7 and is a Double
    putStr ""
于 2012-12-08T20:11:12.327 回答
1

您应该深入研究 Read 类型类。它是可以从字符串中读取的值的标准类型,在不需要错误报告的受控环境中非常有用。如果您想阅读自己的数据类型,您可能必须使用deriving Read语句。

但是,如果要读取任意输入,则使用parsec库是标准的。Parsec 是具有几个预定义基本解析器的解析器组合库。一个额外的包提供了许多数字解析器。还存在特殊的高速解析器组合库和解析器生成器。

于 2012-12-08T20:47:20.037 回答