通过从 C/C++ 替换 R 控制台中的输出来创建进度更新

Creating a progress update by replacing output in the R console from C/C++

是否可以使用 R 的 C/C++ 打印函数覆盖 R 控制台输出?

Rcpp::sourceCpp( code = '
  #include <Rcpp.h>

  // [[Rcpp::export]]
  void print_test() {
    for(int i = 0; i < 10; i++) {
      std::stringstream strs;
      strs << "number: " << i;
      std::string temp_str = strs.str();
      char const* char_type = temp_str.c_str();      

      REprintf(char_type);
    }
  }'
)

print_test()

这个函数的输出是

number: 0number: 1number: 2number: 3number: 4number: 5number: 6number: 7number: 8number: 9

但我希望它是一个动态序列。例如:

number: 0

稍等几秒:

number: 1

其中 number: 0 已从控制台中完全删除。重复此过程,直到达到 number: 9

我已经看到 this 问题,但我无法获得与 REprintf() 一起使用的回车 return 解决方案。

要正确更新 R 控制台,您需要使用 Rinterfaces.h header。此 header 仅适用于 unix-alike 系统。因此,您的进度更新将在 Windows.

中断

特别是,您应该结合使用 REprintf(标准错误)或 Rprintf(标准输出)和 R_FlushConsole 来更新控制台。这里的关键是用 "\r" 或回车符 return 包围输出,这会强制 return 到行的开头。这将导致打印您的值,然后上一行为 "erased."

在此过程中,检查用户中断可能是有利的(例如,如果用户按退出键,退出进程)。因此,我包含了对 R_CheckUserInterrupt() 的调用。

最后,为了强调正在进行更新,我选择了 减慢 循环,迫使它每隔一秒左右进入休眠状态。

#include <Rcpp.h>

// for unix-alike machines only
#if !defined(WIN32) && !defined(__WIN32) && !defined(__WIN32__)
#include <unistd.h>
#include <Rinterface.h>
#endif

// [[Rcpp::export]]
void print_test() {
  int n = 10;

  for(int i = 0; i < n; i++) {

    #if !defined(WIN32) && !defined(__WIN32) && !defined(__WIN32__)
    // Sleep for a second
    usleep(1000000);
    #endif

    std::stringstream strs;
    strs << "number: " << i;
    std::string temp_str = strs.str();
    char const* char_type = temp_str.c_str();      

    REprintf("\r");
    REprintf("%s", char_type);
    REprintf("\r");
    #if !defined(WIN32) && !defined(__WIN32) && !defined(__WIN32__)
    R_FlushConsole();
    #endif
    R_CheckUserInterrupt();
  }

}

示例: