Menu
CoddyTech

Bắt lỗi với tryCatch()

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 53 trên 64.

tryCatch(expr, error = function(e) ...) chạy expr. Nếu phát sinh lỗi, trình xử lý sẽ chạy thay thế và giá trị của nó trở thành kết quả, còn tập lệnh tiếp tục chạy:

safe_sqrt <- function(x) {
  tryCatch(sqrt(x), error = function(e) NA)
}
print(safe_sqrt(16))
print(safe_sqrt("a"))
print("still running")

Đầu ra:

[1] 4
[1] NA
[1] "still running"

Hàm xử lý nhận lỗi dưới dạng e, còn conditionMessage(e) trả về nội dung thông báo của lỗi:

result <- tryCatch(
  stop("file not found"),
  error = function(e) paste("Problem:", conditionMessage(e))
)
print(result)

Đầu ra:

[1] "Problem: file not found"

Chỉ bọc lời gọi có thể gặp lỗi, rồi xử lý lỗi ở nơi bạn có thể làm điều gì đó hữu ích, chẳng hạn như dùng giá trị mặc định hoặc hiển thị thông báo cho người dùng:

to_number <- function(s) {
  tryCatch({
    if (s == "") stop("empty input")
    as.integer(s)
  }, error = function(e) -1L)
}
print(to_number("42"))
print(to_number(""))

Đầu ra:

[1] 42
[1] -1

Trong vòng lặp, tryCatch() giúp một phần tử không hợp lệ gây lỗi mà vẫn xử lý các phần tử còn lại:

inputs <- list(4, "x", 9)
for (v in inputs) {
  r <- tryCatch(sqrt(v), error = function(e) "not a number")
  cat(format(v), "->", r, "\n")
}

Đầu ra:

4 -> 2 
x -> not a number 
9 -> 3 
challenge icon

Thử thách

Dễ

Hoàn thiện safe_divide(a, b). Dùng tryCatch(): bên trong, phát sinh lỗi division by zero khi b bằng 0, nếu không thì tính a / b. Trình xử lý trả về Error: theo sau là thông báo. Trả về kết quả đã làm tròn đến hai chữ số thập phân dưới dạng văn bản, 3.33, hoặc văn bản lỗi.

Code được cung cấp đọc các cặp số như 10/3, được phân tách bằng dấu phẩy, rồi in kết quả của từng cặp trên một dòng riêng.

Tự làm thử

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

# Đoạn code đầu vào/đầu ra đã cho: giữ nguyên
input <- suppressWarnings(readLines(file("stdin")))
for (pair in strsplit(input[1], ",")[[1]]) {
  p <- as.numeric(strsplit(pair, "/")[[1]])
  cat(safe_divide(p[1], p[2]), "\n", sep = "")
}
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