Haskell新手技术问询:如何提取单行输入中的两个独立字符串
解决Haskell单行输入提取两个内容的问题
嘿,作为Haskell新手能自己动手写代码尝试解决问题,真的超棒!咱们来一步步把你的代码修正,实现从test "John" "Jack"这样的输入里提取出John和Jack的需求~
先说说你现有代码里的小问题
- main函数的递归陷阱:你写的
strings <- readStrings里,变量名和函数名重名了,而且这样会无限递归调用readStrings,程序根本没法正常运行。 - test函数的类型错误:你写的
test :: String -> String -> IO [String]不符合需求,咱们要的是提取两个名字后做输出(比如打印),所以类型应该是String -> String -> IO ()才对。 - 输入处理的逻辑衔接:
readStrings的逻辑是对的(用fmap (map read . words) getLine把输入行转成字符串列表),但需要正确匹配输入的结构来提取目标内容。
修正后的完整代码(支持带引号的名字输入)
如果你希望用户输入带双引号的名字(比如test "John" "Jack"),可以用下面的代码:
-- 读取输入行并解析成字符串列表 readStrings :: IO [String] readStrings = fmap (map read . words) getLine -- 处理提取到的两个名字,这里以打印为例 test :: String -> String -> IO () test name1 name2 = do putStrLn $ "第一个提取到的名字:" ++ name1 putStrLn $ "第二个提取到的名字:" ++ name2 -- 主函数:读取输入、匹配格式、调用test处理 main :: IO () main = do strings <- readStrings case strings of -- 匹配"test"开头,后面跟着两个名字的结构 "test":name1:name2:_ -> test name1 name2 -- 处理格式错误的情况 _ -> putStrLn "输入格式不对哦,请按照 `test \"名字1\" \"名字2\"` 的格式输入"
代码解释
words getLine会把输入按空格分割成字符串列表,比如输入test "John" "Jack"会变成["test", "\"John\"", "\"Jack\""];map read会把每个带双引号的元素解析成真正的String类型(比如"\"John\""会被转换成"John");- 用
case表达式匹配列表结构,只要输入是test开头加两个名字,就提取出来传给test函数处理,否则提示格式错误。
额外方案:支持不带引号的名字输入
如果不想让用户输入双引号(比如直接输入test John Jack),可以去掉map read,直接用words的结果:
main :: IO () main = do inputLine <- getLine let parts = words inputLine case parts of "test":name1:name2:_ -> do putStrLn $ "第一个名字:" ++ name1 putStrLn $ "第二个名字:" ++ name2 _ -> putStrLn "输入格式不对,请按照 `test 名字1 名字2` 的格式输入"
⚠️ 注意:这种方式下名字里不能包含空格,如果需要支持带空格的名字,就得用更复杂的解析方式(比如用Parsec库做语法解析),不过作为新手,先从简单的场景入手就好啦~
内容的提问来源于stack exchange,提问作者antelemon
相关产品推荐
相关产品推荐

