Menu
CoddyTech

Kiểm tra đầu vào

Thuộc phần Logic và luồng điều khiển trong hành trình R của Coddy. Bài học 55 trên 64.

Đầu vào từ người dùng hoặc tệp là văn bản và có thể chứa bất cứ thứ gì. Hãy kiểm tra trước khi sử dụng: suppressWarnings(as.numeric(s)) trả về NA với văn bản không phải là số, còn is.na() kiểm tra điều đó:

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

Đầu ra:

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

Một hàm kiểm tra có thể thu thập mọi vấn đề thay vì dừng lại ở vấn đề đầu tiên, nhờ đó đưa ra phản hồi hữu ích hơn. Ở đây, hàm trả về một vector chứa các thông báo, vector này rỗng khi dữ liệu đầu vào hợp lệ:

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

Đầu ra:

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

Chọn cách xử lý dựa trên nơi gọi hàm: trả về một thông báo khi nơi gọi dự kiến có đầu vào không hợp lệ và hiển thị thông báo đó cho người dùng; phát sinh lỗi bằng stop() khi đầu vào không hợp lệ cho thấy có lỗi trong chương trình và không nên bị bỏ qua.

# Bên gọi dự kiến đầu vào không hợp lệ và hiển thị thông báo
read_age("abc")                     # "not a number"
# Đầu vào không hợp lệ là lỗi trong chương trình
if (!is.numeric(x)) stop("x must be numeric")

Việc xác thực bằng tryCatch() quanh bước phân tích giúp phần code chính không cần các bước kiểm tra: mỗi bản ghi hoặc được chuyển đổi, hoặc được báo lỗi:

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

Đầu ra:

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

Thử thách

Dễ

Hoàn thiện check_signup(name, age, email). Thu thập mọi vấn đề theo thứ tự này: name is empty (sau khi xóa khoảng trắng ở hai đầu), age must be a number, age must be 13 or older (chỉ khi tuổi là một số) và email needs @. Trả về ok khi không có vấn đề nào, nếu không thì nối các vấn đề bằng ; .

Code được cung cấp đọc tên, tuổi và email (mỗi giá trị trên một dòng) rồi in ra giá trị trả về.

Tự làm thử

check_signup <- function(name, age, email) {
  # Viết code của bạn ở đây
  "ok"
}

# Đoạn code đầu vào/đầu ra đã được cung cấp: giữ nguyên
input <- suppressWarnings(readLines(file("stdin")))
cat(check_signup(input[1], input[2], input[3]), sep = "\n")
quiz iconTự kiểm tra

Bài học này có một bài trắc nghiệm ngắn. Bắt đầu bài học để trả lời và theo dõi tiến độ.

Tất cả bài học trong Logic và luồng điều khiển

Tự luyện tập: Trình biên dịch R online