Проверка того, что значение цены в строке имеет правильный формат - PullRequest
0 голосов
/ 21 мая 2011

Я использую n <- getLine, чтобы получить от пользователя цену. Как я могу проверить правильность значения? (Цена может иметь «.» И цифры и должна быть больше 0)? </p>


Не работает:

isFloat = do
    n <- getLine
    let val = case reads n of
                ((v,_):_) -> True
                _ -> False

Ответы [ 2 ]

4 голосов
/ 21 мая 2011

Если ввод всегда действителен или исключения в порядке

Если у вас есть пользователи, вводящие десятичные числа в форме «123,456», то это можно просто преобразовать в число с плавающей запятой или двойное числоиспользуя read:

n <- getLine
let val = read n

или в одну строку (импортировав Control.Monad):

n <- liftM read getLine

для отлова ошибочного ввода

Приведенный выше код дает сбой, за исключением случаев, когда пользователи вводят неверные записи.Если это проблема, тогда используйте reads и listToMaybe (из Data.Maybe):

n <- liftM (fmap fst . listToMaybe . reads) getLine

Если этот код выглядит сложным, не беспокойтесь - ниже приведена та же операция, но выполняющая всю работус явными инструкциями case:

n <- getLine
let val = case reads n of
            ((v,_):_) -> Just v
            _ -> Nothing

Обратите внимание, что мы сопоставляем шаблон, чтобы получить первый элемент кортежа в начале списка, заголовок списка равен (v,_), а первый элемент - v,Подчеркивание (_) означает просто «игнорировать значение в этом месте».

Если точка с плавающей запятой неприемлема

Общеизвестно, что значения с плавающей запятойПриблизительно и не подходит для финансовых расчетов в реальном мире (но, возможно, домашняя работа, в зависимости от вашего профессора)В этом случае вы хотите прочитать значения в Rational (из Data.Ratio).

n <- liftM maybeRational getLine
...
  where
  maybeRational :: String -> Maybe Rational
  maybeRational str =
      let (a,b) = break (=='.') str
      in liftM2 (%) (readMaybe a) (readMaybe $ drop 1 b)
  readMaybe = fmap fst . listToMaybe . reads
1 голос
/ 21 мая 2011

В дополнение к рекомендациям по синтаксическому анализу, предоставленным TomMD, рассмотрите возможность использования соответствующей монады для отчетов об ошибках.Это позволяет вам удобно объединять вычисления, которые могут быть неудачными, избегая явной проверки ошибок на каждом шаге.

{-# LANGUAGE FlexibleContexts #-}
import Control.Monad.Error

parsePrice :: MonadError String m => String -> m Double
parsePrice s = do
    x <- case reads s of
        [(x, "")] -> return x
        _         -> throwError "Not a valid real number."
    when (x <= 0) $ throwError "Price must be positive."
    return x

main = do
    n <- getLine
    case parsePrice n of
        Left err -> putStrLn err
        Right x  -> putStrLn $ "Price is " ++ show x
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...