Search code examples
rerror-handlinguser-inputgrepl

How do I validate a user input for conditions using grepl


I am trying to stick to base R as a personal challenge. I'm not committed to using grepl though, it was just my first thought. And I've hit a roadblock.

Here is what I have so far:

armstrong <- function(x) {
if (grepl("^[-]{0,1}[0-9]{0,}.{0,1}[0-9]{1,}$", x) == FALSE) {
    stop("Please try submitting a valid number")
  } 
  else {
  temp <- strsplit(as.character(x), split = "")  
  y <- sapply(temp, function(y)sum(as.numeric(y)^length(y)))
  if (y == x) {
    print(paste("The number you entered,", x ,", is an Armstrong number"))
    }
  else {
    print(paste("The number you entered,", x ,", is not an Armstrong number"))
    }
  }
}

armstrong(readline(prompt = "Please enter a three digit positive number"))

The program checks to see if the user inputted an Armstrong number. That part works. What I'm stuck on is the error handling for the user input. I can't get grepl to output FALSE if the user inputs a negative number, or if they input characters in between numbers, such as 1a4. It would be nice if grepl would output FALSE is the user inputs a number that isn't 3 digits, but that's not such a big deal because the function will still work.

How do I update the regular expressions to help with error handling?


Solution

  • Why not just

    if (! is.numeric(x) || x < 0) stop(…)
    

    In other words: use proper types. Don’t accept a string if the input is supposed to be a number.

    If you are required to accept a string, convert that string to a number and test whether the conversion succeeded. You can test for NA to check if it was successful.

    I’d also suggest a few other changes to the function:

    armstrong <- function (x) {
      num <- as.numeric(x)
      if (is.na(num) || num < 0) stop("Please try submitting a valid number")
    
      digits <- strsplit(x, "")[[1L]]
      sum <- sum(as.numeric(digits) ^ length(digits))
      msg <- paste0(
        "The number you entered, ", x, ", is ",
        if (num != sum) "not " else "",
        "an Armstrong number"
      )
      message(msg)
    }