Haskell IO:读取整个文本文件
Haskell IO: Reading the whole text file
import System.IO
import Text.Printf
kodable :: IO()
kodable = do
printf "Please load a map : "
file <- getLine
mapFile <- openFile file ReadMode
let map = loadMap [] mapFile
hClose mapFile
printf "Read map successfully! \n"
printf "Initial:\n"
outputMap map
loadMap :: [String] -> FilePath -> [String]
loadMap map fp = do
finished <- hIsEOF fp
new_map <- if not finished
then map ++ [hGetLine fp]
else return ()
loadMap new_map fp
outputMap :: [String] -> IO()
outputMap (x) = printf "%s\n" x
outputMap (x:xs) = do
printf "%s\n" x
outputMap xs
我正在开发一个项目,需要先从 txt 文件中将地图加载到游戏中,例如“map.txt”。 kodable 是主要功能。
首先,游戏会要求玩家加载地图。所以,在那种情况下,玩家将输入map.txt。然后,我尝试使用函数 loadMap 递归地将地图放入字符串数组并存储在 map 中。最后,我将使用函数 outputMap 输出我加载的地图。
由于我还是Haskell的初学者,所以我在调试这部分时遇到了麻烦。
import System.IO
import Text.Printf
kodable :: IO()
kodable = do
printf "Please load a map : "
file <- getLine
map <- readFile file
printf "Read map successfully! \n"
printf "Initial:\n"
outputMap map
outputMap :: String -> IO()
outputMap (x) = printf "%s\n" x
outputMap (x:xs) = do
printf "%s\n" x
outputMap xs
我试过readFile方法。不完全是我打算做的方式。但我想我还是会先坚持那个。谢谢!
我看到你已经决定坚持你的第一个答案。但我只是想把这个解决方案放在这里,让你对未来有一个想法。我将使用一些“复杂”的功能,这些功能目前您可能还无法使用。
首先,kodable
可以简化为:
kodable :: IO ()
kodable = getMapFile >>= readFile >>= outputMap
时髦的 >>=
函数只是一种处理 IO Monad 的方法,因此我们不必对值进行解包和包装。我不会详细介绍,因为它超出了这个问题的范围。
getMapFile :: IO String
getMapFile = putStr "Please load a map: " >> getLine
这个函数所做的就是打印出提示,然后获取输入的任何内容。>>
只是忽略左侧的返回值。
readFile
如您所愿,它从 getMapFile 获取文件名并读取文件内容。
outputMap :: String -> IO ()
outputMap = mapM_ putStrLn . lines
-- OR
outputMap :: String -> IO ()
outputMap fileContents = mapM_ putStrLn $ lines fileContents
此处的最终函数与 loadMap
和 outputMap
在您的代码中所做的完全相同。 lines
等同于 loadMap
,它根据换行符将输入文件拆分为单独的字符串。我知道您正在尝试递归思考并只是在学习,但是有许多有用的功能可以让您的生活更轻松。
将文件内容拆分成行后,我们可以使用 Monadic Map 函数 mapM_
,它实际上将 putStrLn
应用于列表中的每一行。
import System.IO
import Text.Printf
kodable :: IO()
kodable = do
printf "Please load a map : "
file <- getLine
mapFile <- openFile file ReadMode
let map = loadMap [] mapFile
hClose mapFile
printf "Read map successfully! \n"
printf "Initial:\n"
outputMap map
loadMap :: [String] -> FilePath -> [String]
loadMap map fp = do
finished <- hIsEOF fp
new_map <- if not finished
then map ++ [hGetLine fp]
else return ()
loadMap new_map fp
outputMap :: [String] -> IO()
outputMap (x) = printf "%s\n" x
outputMap (x:xs) = do
printf "%s\n" x
outputMap xs
我正在开发一个项目,需要先从 txt 文件中将地图加载到游戏中,例如“map.txt”。 kodable 是主要功能。 首先,游戏会要求玩家加载地图。所以,在那种情况下,玩家将输入map.txt。然后,我尝试使用函数 loadMap 递归地将地图放入字符串数组并存储在 map 中。最后,我将使用函数 outputMap 输出我加载的地图。 由于我还是Haskell的初学者,所以我在调试这部分时遇到了麻烦。
import System.IO
import Text.Printf
kodable :: IO()
kodable = do
printf "Please load a map : "
file <- getLine
map <- readFile file
printf "Read map successfully! \n"
printf "Initial:\n"
outputMap map
outputMap :: String -> IO()
outputMap (x) = printf "%s\n" x
outputMap (x:xs) = do
printf "%s\n" x
outputMap xs
我试过readFile方法。不完全是我打算做的方式。但我想我还是会先坚持那个。谢谢!
我看到你已经决定坚持你的第一个答案。但我只是想把这个解决方案放在这里,让你对未来有一个想法。我将使用一些“复杂”的功能,这些功能目前您可能还无法使用。
首先,kodable
可以简化为:
kodable :: IO ()
kodable = getMapFile >>= readFile >>= outputMap
时髦的 >>=
函数只是一种处理 IO Monad 的方法,因此我们不必对值进行解包和包装。我不会详细介绍,因为它超出了这个问题的范围。
getMapFile :: IO String
getMapFile = putStr "Please load a map: " >> getLine
这个函数所做的就是打印出提示,然后获取输入的任何内容。>>
只是忽略左侧的返回值。
readFile
如您所愿,它从 getMapFile 获取文件名并读取文件内容。
outputMap :: String -> IO ()
outputMap = mapM_ putStrLn . lines
-- OR
outputMap :: String -> IO ()
outputMap fileContents = mapM_ putStrLn $ lines fileContents
此处的最终函数与 loadMap
和 outputMap
在您的代码中所做的完全相同。 lines
等同于 loadMap
,它根据换行符将输入文件拆分为单独的字符串。我知道您正在尝试递归思考并只是在学习,但是有许多有用的功能可以让您的生活更轻松。
将文件内容拆分成行后,我们可以使用 Monadic Map 函数 mapM_
,它实际上将 putStrLn
应用于列表中的每一行。