从包含点的文件中读取

时间:2013-06-25 12:42:56

标签: haskell

我的文件txt包含两个数字,例如:

2

3

你怎么看,每一行都以点结束。

如何阅读并打印例如这些数字的总和?

如果我的文件不包含点,那么例如我有

2

3

这不是问题。我的代码是:

main3 = do
    x <- openFile "C:/Users/file.txt"  ReadMode
    m <- hGetLine x
    n <- hGetLine x
    return ((read m::Int)+(read n::Int))

它运作良好。但是当我的文件中有点时,我不知道我能做什么。也许是任何图书馆?

感谢您的帮助。

3 个答案:

答案 0 :(得分:5)

问题是read不会将"3."解析为3。如果你只想以一种黑客的方式做到这一点,你可以放弃最后一个角色。

main4 = do
    x <- openFile "C:/Users/file.txt"  ReadMode
    m <- hGetLine x
    n <- hGetLine x
    return ((read (init m)::Int)+(read (init n)::Int))

可能有效但很脆弱,因为它假定每行中唯一的非数字字符是最后一个。我们可以通过假设我们的数字中的第一个n数字字符来做得更好

import Data.Char

-- takeWhile isDigit :: String -> String

main5 path = do
  f <- readFile path
  numberStrings <- map (takeWhile isDigit) (lines f)
  sum (map read numberStrings)

最强大的解决方案是升级到像Parsec这样的“解析器组合库”,它可以让你写出文本文件的语法。

答案 1 :(得分:3)

有几种方法可以做到..最简单的是

main = do
  text <- readFile "file.txt" -- Grab the file
  let nums = map read . map init . lines $ text
  print $ sum nums

init只会丢弃.。但是我会像这样写

import Text.Parsec.String
import Text.Parsec
import Control.Applicative ((<*), (<$>))

getNums :: Parser [Int]
getNums = num `sepEndBy` newline
    where num = read <$> many1 digit <* char '.'

main = parseFromFile getNums "filename" >>= print . fmap sum

是否值得使用parsec这样的东西?答案是“它取决于”。我的经验法则是,如果我计划不止一次使用它,那么只需咬紧牙关并使用parsec。使用像parsec这样的库来修改新的和更复杂的格式会更容易,更容易。另外,您可以通过这种方式获得免费[体面]错误消息。

答案 2 :(得分:0)

您可以通过几个步骤来利用Haskell的monadic API:

  1. 每行读入文件行
  2. 检查每一行是否以点结束:使用map并返回一个Maybe monad:Nothing,当该行未以点结束时,Just(值不带点)当该行以点结尾时
  3. 使用map + flatten将每个String转换为数字,再次使用Maybe monad。没有错误,或只是x包含数字
  4. 使用fold
  5. 对值求和

    当我有时间的时候,我会尝试建立一个例子。使用Haskell的monadic API总是很有趣。