Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Getting user input from R console: Rcpp and std::cin

Tags:

c++

r

rcpp

I have been doing some exercises to learn c++ and decided to integrate them into R since ultimately I want to write c++ backends for R functions. I am having trouble finding a solution to retrieve user input from the R console. While there is Rcpp::Rcout for printing and returning output, there doesn't seem to be a similar funciton for std::cin....

#include <Rcpp.h>
// [[Rcpp::export]]
Rcpp::String cola() {
  Rcpp::Rcout << "Pick a drink:" << std::endl << "1 - Espresso" << std::endl << "2 - Americano" << std::endl << "3 - Latte" << std::endl << "4 - Cafe dopio" << 
std::endl << "5 - Tea" << std::endl;
  int drink;
  std::cin >> drink;
  std::string out;
  switch(drink) {
  case 1: out = "Here is your Espresso";
  case 2: out = "Here is your Americano";
  case 3: out = "Here is your Latte";
  case 4: out = "Here is your Cafe dopio";
  case 5: out = "Here is your Tea";
  case 0: out = "Error. Choice was not valid, here is your money back.";
    break;
  default:
    if(drink > 5) {out = "Error. Choice was not valid, here is your money back.";}
  }
  return out;
}
like image 275
JulianS Avatar asked Jul 25 '17 10:07

JulianS


1 Answers

Even without Rcpp in the mix, std::cin is unsuitable for interactive input.

To use the R console with Rcpp, you need to use R functions (in particular, readline) instead of C++ functionality. Luckily you can pull R objects into your C++ code:

Environment base = Environment("package:base");
Function readline = base["readline"];
Function as_numeric = base["as.numeric"];

And then you can use them:

int drink = as<int>(as_numeric(readline("> ")));

Beware that there's another error in your code: your cases are all fall-through since you are missing the break; furthermore, there’s no reason to have a case 0, and there’s no reason at all for the if in the default case.

Oh, and finally, don’t use std::endl unless you actually need to flush the output (and you only need to do this once here, at the end); use '\n' instead.

like image 117
Konrad Rudolph Avatar answered Oct 13 '22 13:10

Konrad Rudolph