Menu
CoddyTech

验证输入

本课属于 Coddy R 学习旅程的“逻辑与流程”单元。第 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

根据谁来调用函数来选择风格:如果调用方预期会收到错误输入,并会向用户显示消息,就返回一条消息;如果错误输入意味着程序中有不应被忽略的 bug,就用 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 在线编译器