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

时间:2015-05-26 13:49:27

标签: f#

我正在尝试从命令行输入中获取输入编号:

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程序员来说是一个非常明显的问题。我担心初学者经常会有愚蠢的问题。

3 个答案:

答案 0 :(得分:5)

我经常做

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

就像.net中所有TryXY模式的魅力一样;)

例如

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方法和函数中使用它时,这将使您进入问题很快

  • 您将猜测与result匹配为Option只会将您获得的所有内容放在下一行Option.get result中,这会在{{1}时抛出错误} {是result(当用户没有输入数字时) - 这是您真正的问题

  • 你使用全局可变变量和命令循环 - 两者都是功能代码气味

简单的重写(没有丑陋的可变性)可能如下所示:

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 功能 - 你应该试一试!

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

答案 1 :(得分:2)

你看过Int32.TryParse吗?

let parsed, guess = Console.ReadLine() |> System.Int32.TryParse
if parsed then ... else ...

答案 2 :(得分:0)

与你的例子一起使用可变变量和循环:

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, _) -> None

    match result with
        |Some guess -> 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
        |None -> printfn "Your guess is not a valid number!"

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