Вопрос, почему две строки не проверяют identical
, трудно объяснить - две строки, безусловно, выглядят одинаково при проверке своих необработанных байтов (через charToRaw
), они не несут атрибутов и не иметь набор кодировки. Так что, на самом деле, они должны быть идентичны.
Чтобы разгадать тайну, нам нужно понять, что на самом деле делает ваш код C ++. Более конкретно, что делает приведение C в стиле C_toupper_String
. Из-за их опасности, вы должны никогда использовать C стиль приведения . Ваш код сталкивается с проблемами исключительно из-за этого приведения.
Почему? Потому что String::get_cstring
возвращает char const*
. Вы отбрасываете его на char*
и тем самым отбрасываете его const
. Это может быть безопасным, но только если базовое хранилище не const
. В противном случае это неопределенное поведение (UB) . Эффекты UB трудно предсказать из-за переписывания кода (например, оптимизации). В этом случае кажется, что он создает код, который портит внутреннюю строку строки R.
Вы принципиально не можете изменять Rcpp::String
объекты на месте, они не позволяют это , Но если вы просто хотите избежать копирования, тогда ваш код все равно не достигает своей цели, поскольку ваша C_toupper
функция явно копирует ввод на первом шаге.
Как сказал Дирк, правильный способ решения этой проблемы - использовать доступный R cpp API. А в случае модификаций строк это означает преобразование вашего ввода в std::string
, выполнение изменений, а затем обратное преобразование. Это копирует, но ваш текущий код тоже. Вот один хороший способ написания этого кода:
#include <Rcpp.h>
#include <cctype>
#include <string>
// [[Rcpp::export]]
Rcpp::StringVector C_toupper(Rcpp::StringVector const& vec) {
std::vector<std::string> res(vec.begin(), vec.end());
for (std::string& str : res) {
for (char& c : str) c = std::toupper(c);
}
return Rcpp::wrap(res);
}
Обратите внимание, что это будет иногда давать неправильные результаты, потому что std::toupper
принципиально не может иметь дело с определенными характеристиками Unicode. R's toupper
делает лучше, но также имеет некоторые проблемы. Правильное решение использует пакеты {stringr} или {stringi}.