メモ:Rcppでマルチバイト文字を表示するときはRf_translateChar()でデフォルトの文字コードに変換してから

メッセージを表示するにはRcpp::Rcoutを使えばいい。与えた文字列をそのままダンプするような関数はこんな感じ。

Rcpp::cppFunction(
'void my_print(CharacterVector x) {
  for (CharacterVector::iterator i = x.begin(); i != x.end(); i++){
    String str(*i);
    Rcpp::Rcout << str.get_cstring() << std::endl;
  }
}')

my_print("あ")
#> あ

これで一見動いているように見えるけど、WindowsではUTF-8の文字列を渡すと文字化けする。

my_print(enc2utf8("あ"))
#> 縺・

どうやらRcpp::Rcoutにはデフォルトの文字コードの文字列を渡さないといけない。

文字列をデフォルトの文字コードに変換するにはRf_translateChar()を使う。Rf_translateChar()が返すのはconst char*なので文字コード情報は引き継がれない。String()には文字コードを明示する必要がある。

Rcpp::cppFunction(
'void my_print2(CharacterVector x) {
  for (CharacterVector::iterator i = x.begin(); i != x.end(); i++){
    String str(Rf_translateChar(*i), CE_NATIVE);
    Rcpp::Rcout << str.get_cstring() << std::endl;
  }
}')

my_print2("あ")
#> あ
my_print2(enc2utf8("あ"))
#> あ

ただ、今回欲しいのは、デフォルトの文字コードになったCの文字列なので、Stringをかまさずに直接こうすればいい。

void my_print3(CharacterVector x) {
  for (CharacterVector::iterator i = x.begin(); i != x.end(); i++){
    Rcpp::Rcout << Rf_translateChar(*i) << std::endl;
  }
}

あと、UTF-8に変換するときはこっちを使う。

Rf_translateCharUTF8()

参考: