Menu
Coddy logo textTech

Walidacja danych wejściowych

Część sekcji Logika i przepływ sterowania ścieżki R w Coddy. Lekcja 55 z 64.

Dane wejściowe od użytkowników lub z plików to tekst i mogą zawierać cokolwiek. Sprawdź je przed użyciem: suppressWarnings(as.numeric(s)) zwraca NA dla tekstu, który nie jest liczbą, a is.na() sprawdza, czy tak jest:

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"))

Wynik:

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

Walidator może zebrać wszystkie problemy, zamiast zatrzymywać się na pierwszym, dzięki czemu przekazuje bardziej przydatne informacje zwrotne. W tym przypadku zwraca wektor komunikatów, pusty, gdy dane wejściowe są prawidłowe:

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")))

Wynik:

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

Wybierz sposób postępowania w zależności od tego, kto wywołuje funkcję: zwróć komunikat, gdy wywołujący spodziewa się nieprawidłowych danych wejściowych i wyświetla go użytkownikowi; zgłoś błąd za pomocą stop(), gdy nieprawidłowe dane wejściowe oznaczają błąd, który nie powinien pozostać niezauważony.

# kod wywołujący spodziewa się nieprawidłowych danych wejściowych i wyświetla komunikat
read_age("abc")                     # "not a number"
# nieprawidłowe dane wejściowe oznaczają błąd w programie
if (!is.numeric(x)) stop("x must be numeric")

Walidacja za pomocą tryCatch() wokół etapu parsowania pozwala uniknąć kontroli w głównym kodzie: każdy rekord jest albo konwertowany, albo zgłaszany:

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")
}

Wynik:

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

Wyzwanie

Łatwy

Uzupełnij check_signup(name, age, email). Zbierz wszystkie problemy w tej kolejności: name is empty (po usunięciu spacji na początku i końcu), age must be a number, age must be 13 or older (tylko gdy wiek jest liczbą) i email needs @. Zwróć ok, gdy nie ma żadnego problemu, w przeciwnym razie zwróć problemy połączone za pomocą ; .

Dostarczony kod odczytuje imię, wiek i adres e-mail (po jednym w wierszu) i wypisuje zwróconą wartość.

Spróbuj swoich sił

check_signup <- function(name, age, email) {
  # Wpisz tutaj swój kod
  "ok"
}

# Dostarczony kod wejścia/wyjścia: pozostaw go bez zmian
input <- suppressWarnings(readLines(file("stdin")))
cat(check_signup(input[1], input[2], input[3]), sep = "\n")
quiz iconSprawdź się

Ta lekcja zawiera krótki quiz. Zacznij lekcję, żeby na niego odpowiedzieć i śledzić swoje postępy.

Wszystkie lekcje w sekcji Logika i przepływ sterowania

Poćwicz samodzielnie: Kompilator R online