Menu
Coddy logo textTech

Проверка входных данных

Часть раздела Логика и потоки выполнения путешествия по R на Coddy. Урок 55 из 64.

Ввод от пользователей или из файлов является текстом и может содержать что угодно. Проверьте его перед использованием: suppressWarnings(as.numeric(s)) возвращает NA для текста, который не является числом, а is.na() проверяет это:

read_age <- function(s) {
  n <- suppressWarnings(as.numeric(s))
  if (is.na(n)) return("not a number")
  if (n < 0 || n > 130) return("out of range")
  paste("age", n)
}
print(read_age("36"))
print(read_age("abc"))
print(read_age("200"))

Результат:

[1] "age 36"
[1] "not a number"
[1] "out of range"

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

check_password <- function(p) {
  problems <- c()
  if (nchar(p) < 8) problems <- c(problems, "too short")
  if (!grepl("[0-9]", p)) problems <- c(problems, "needs a digit")
  problems
}
print(check_password("abc"))
print(length(check_password("secret123")))

Результат:

[1] "too short"     "needs a digit"
[1] 0

Выбирайте стиль в зависимости от того, кто вызывает функцию: возвращайте сообщение, когда вызывающий код ожидает некорректный ввод и показывает его пользователю; вызывайте ошибку с помощью stop(), когда некорректный ввод означает ошибку в программе, которая не должна остаться незамеченной.

# вызывающая сторона ожидает некорректный ввод и показывает сообщение
read_age("abc")                     # "not a number"
# некорректный ввод — это ошибка в программе
if (!is.numeric(x)) stop("x must be numeric")

Проверка с помощью tryCatch() вокруг шага разбора позволяет не загромождать основной код проверками: каждая запись либо преобразуется, либо о ней сообщается:

parse_record <- function(line) {
  parts <- strsplit(line, ",")[[1]]
  if (length(parts) != 2) stop("expected 2 fields")
  qty <- suppressWarnings(as.integer(parts[2]))
  if (is.na(qty)) stop("quantity is not a whole number")
  list(item = parts[1], qty = qty)
}
for (line in c("tea,2", "jam", "oil,x")) {
  r <- tryCatch(parse_record(line), error = function(e) conditionMessage(e))
  cat(line, ":", if (is.list(r)) paste("ok", r$qty) else r, "\n")
}

Вывод:

tea,2 : ok 2 
jam : expected 2 fields 
oil,x : quantity is not a whole number 
challenge icon

Задание

Легко

Завершите check_signup(name, age, email). Соберите все проблемы в таком порядке: name is empty (после удаления пробелов в начале и конце), age must be a number, age must be 13 or older (только если возраст является числом) и email needs @. Верните ok, если проблем нет, иначе — проблемы, объединённые с помощью ; .

Предоставленный код считывает имя, возраст и адрес электронной почты (по одному значению в строке) и выводит возвращённое значение.

Попробуйте сами

check_signup <- function(name, age, email) {
  # Напишите свой код здесь
  "ok"
}

# Предоставленный код ввода/вывода: оставьте его как есть
input <- suppressWarnings(readLines(file("stdin")))
cat(check_signup(input[1], input[2], input[3]), sep = "\n")
quiz iconПроверьте себя

В этом уроке есть небольшой тест. Начните урок, чтобы ответить на вопросы и сохранить прогресс.

Все уроки раздела Логика и потоки выполнения

Потренируйтесь самостоятельно: Онлайн-компилятор R