2 votes

Création d'une mise à jour de la progression en remplaçant la sortie dans la console R à partir de C/C++

Est-il possible d'écraser la sortie de la console R avec les fonctions d'impression C/C++ pour 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()

La sortie de cette fonction est

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

mais je veux que ce soit une séquence dynamique. Par exemple :

number: 0

Attendez quelques secondes :

number: 1

donde number: 0 est complètement effacé de la console. Cette procédure se répète jusqu'à ce que number: 9 est atteint.

J'ai vu este question, mais je n'ai pas réussi à faire fonctionner la solution du retour chariot avec REprintf().

5voto

coatless Points 10952

Pour obtenir les mises à jour appropriées de la R vous devrez utiliser l'option Rinterfaces.h en-tête. Cet en-tête n'est disponible que pour les systèmes de type unix. Ainsi, la mise à jour de votre progression rupture sur Windows.

En particulier, vous devez utiliser REprintf (erreur standard) ou Rprintf (sortie standard) en combinaison avec R_FlushConsole pour mettre à jour la console. La clé ici est d'entourer la sortie avec "\r" ou un retour chariot, qui force un retour au début de la ligne. Ainsi, votre valeur sera imprimée et la ligne précédente sera "effacée".

Pendant cette procédure, il peut être avantageux de vérifier les interruptions de l'utilisateur (par exemple, si l'utilisateur appuie sur escape, il quitte le processus). Ainsi, j'ai inclus un appel à R_CheckUserInterrupt() .

Enfin, pour souligner qu'une mise à jour est en cours, j'ai choisi de lent la boucle en la forçant à se mettre en veille toutes les secondes environ.

#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();
  }

}

Exemple :

Progress Update

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X