F#异常处理:如何在ReadLine()中解析数字?

缺口

我正在尝试从命令行输入中获取输入数字:

let mutable guess = Console.ReadLine() |> System.Int32.Parse

只要输入是数字,此方法就可以正常工作;除非输入是字母字符串(例如),kdf否则程序将以退出System.TypeInitilizationException

如何在控制台输入中处理字符串?

更新

我正在尝试用F#编写猜谜游戏这是整个程序:

open System

printfn "Guess the number"

let secretNum = System.Random().Next(1,101)

let mutable continueLooping = true 

while continueLooping do

    printfn "Please input your guess."

    let mutable input = Console.ReadLine() 

    let result =
        match Int32.TryParse input with
        | (true, result) -> Some(result) 
        | (false, _) -> printfn "Please input a number!"; None

    let guess = Option.get result

    printfn "You guessed: %A" guess

    if guess < secretNum then printfn "Too small!"
    else if guess > secretNum then printfn "Too big!"
    else do 
        printfn "You win!" 
        continueLooping <- false



[<EntryPoint>]
let main argv = 
    printfn "%A" argv
    0 // return an integer exit code

该程序可以完成正确的工作,只是它不能处理无效的输入问题。我是编程的新手,也许这对.NET程序员来说是一个非常明显的问题。恐怕初学者经常会有愚蠢的问题。

卡斯滕

我通常会

match System.Int32.TryParse input with
| (true, number) -> ...
| (false, _)     -> ....

对于TryXY.net中的所有模式而言,它的工作方式也很吸引人;)

例子

F# Interactive for F# 3.1 (Open Source Edition)
Freely distributed under the Apache 2.0 Open Source License

For help type #help;;

> let tryInt input = match System.Int32.TryParse input with | (true, number) -> Some number | _ -> None;;

val tryInt : input:string -> int option

> tryInt "55";;
val it : int option = Some 55
> tryInt "no";;
val it : int option = None
>    

评论

我的猜测是您要查询用户,直到他输入有效的整数。因此,您可以使用我刚刚给您的函数通过一个类似递归循环的函数来完成此任务

let rec queryAnInt () =
    printf "please input an integer " 
    let input = System.Console.ReadLine()
    match System.Int32.TryParse input with
    | (true, number) -> number
    | _              -> printfn "sorry - you did not enter an integer"
                        queryAnInt ()

现在queryAnInt ()将要求用户提供一个整数,直到他给出一个整数并返回为止(没有这个整数,Option您似乎有问题)

你的程序

这是我在您的程序中看到的一些内容:

  • 首先是显而易见的事情:您将所有代码直接编码到模块中,而当您真的想要将其包含在main方法和函数中时-这将使您迅速陷入困境

  • 您将猜测resultOption唯一匹配,将您获得的所有内容丢给下一行Option.get result,这将在resultwas None(用户未输入数字)时抛出错误-这是您真正的问题

  • 您使用全局可变变量和命令式循环-两者都是功能代码的味道

一个简单的重写(没有难看的可变)可能看起来像这样:

open System

let rec queryGuess () =
    printf "please input your guess " 
    let input = Console.ReadLine()
    match System.Int32.TryParse input with
    | (true, number) when number >= 1 && number <= 100
                     -> number
    | _              -> printfn "sorry - please enter a number between 1 and 100"
                        queryGuess ()

let rec guess secret nrTriesLeft =
    if nrTriesLeft = 0 then printfn "Sorry you lost" else
    match queryGuess () with
    | g when g < secret ->
        printfn "Too small!"
        guess secret (nrTriesLeft - 1)
    | g when g > secret ->
        printfn "Too big!"
        guess secret (nrTriesLeft - 1)
    | g when g = secret ->
        printfn "You win!"
    | _ -> failwith "impossible case" 

let game () = 
    printfn "Guess my secret number - it's between 1 and 100"

    let secretNum = System.Random().Next(1,101)

    guess secretNum 7 // 7 tries should always be enough - bonus question: why?

[<EntryPoint>]
let main _ = 
    game ()
    0

这样一来,您也可以轻松地扩展到只说一定数量的重试次数(只需guess稍微更改一下功能-您应该尝试一下!

我希望这最终可以帮助您处理语法问题

本文收集自互联网,转载请注明来源。

如有侵权,请联系 [email protected] 删除。

编辑于
0

我来说两句

0 条评论
登录 后参与评论

相关文章