C++ 自制toupper:外观相同,但不完全相同

C++ 自制toupper:外观相同,但不完全相同,c++,r,string,rcpp,toupper,C++,R,String,Rcpp,Toupper,对于我的优化,我希望在Rcpp中获得一个像样的toupper。我对C++非常陌生,至于我已经做过了: #包括 使用名称空间Rcpp; 无效C_-toupper_字符串(常量字符串&s){ 对于(char*p=(char*)s.get_cstring();*p!=0;p++)*p=toupper(*p); } //[[Rcpp::导出]] StringVector C_toupper(StringVector常量和向量){ StringVector res=克隆(vecteur); for(int

对于我的优化,我希望在Rcpp中获得一个像样的
toupper
。我对C++非常陌生,至于我已经做过了:

#包括
使用名称空间Rcpp;
无效C_-toupper_字符串(常量字符串&s){
对于(char*p=(char*)s.get_cstring();*p!=0;p++)*p=toupper(*p);
}
//[[Rcpp::导出]]
StringVector C_toupper(StringVector常量和向量){
StringVector res=克隆(vecteur);
for(int i(0);iTestStult

为什么不使用C++库来使用一行?除非你真的有C++经验,否则你可能不太可能打败它。下面的代码只是缩进显示在这里,它是我的R会话中的一行

R> Rcpp::cppFunction("std::string tU(std::string s) { std::string u(s); \
 for (unsigned int i=0; i<u.length(); i++) u[i] = std::toupper(u[i]); return(u); }")
R> tU("aBcDe")
[1] "ABCDE"
R> 
R>Rcpp::cppFunction(“std::stringtu(std::strings){std::stringu(s)\

对于(unsigned int i=0;i这两个字符串为什么不测试
相同的
这个问题很难解释-当检查它们的原始字节时(通过
charToRaw
),这两个字符串看起来肯定是相同的,它们不携带属性,也没有编码集。因此,实际上,它们应该是相同的

为了解决这个谜团,我们需要了解C++代码实际上在做什么。更具体地说,C代码风格的代码在Cux> CuTouPiPrSype 中做了什么。因为它们的危险性。 为什么?因为返回

char-const*
。您将其强制转换为
char*
,从而丢弃其
常量。这可能是安全的,但前提是基础存储不是
const
。否则它是安全的。由于代码重写(例如优化),UB的影响很难预测.在本例中,它似乎生成了弄乱R字符串内部的代码


从根本上说,您无法在适当的位置修改
Rcpp::String
对象,因为它们不允许这样做。但是,如果您只是想避免复制,那么您的代码无论如何都无法达到目的,因为
C\u toupper
函数在第一步中显式复制输入

正如Dirk所说,解决此问题的正确方法是使用可用的Rcpp API。在字符串修改的情况下,这意味着将您的输入转换为
std::string
,执行修改,然后再转换回。这会复制,但您当前的代码也会复制。下面是编写此代码的一种好方法:

#包括
#包括
#包括
//[[Rcpp::导出]]
Rcpp::StringVector C_toupper(Rcpp::StringVector const&vec){
向量res(vec.begin(),vec.end());
for(std::string和str:res){
对于(char&c:str)c=std::toupper(c);
}
返回Rcpp::wrap(res);
}

请注意,这有时会产生错误的结果,因为
std::toupper
根本无法处理某些Unicode特征。R的
toupper
做得更好,但也有一些问题。一个正确的解决方案是使用or{stringi}包。

我不确定自
Rcpp::clone以来您试图实现什么()
将复制您的数据。拉尔夫·斯塔布纳:我想在我想要的时候做,而不是在我不想做的时候做。我想了解Rcpp::String是如何工作的,并能够直接安全地修改它。无论如何,它甚至不会复制数据,因为我注意到测试字符串被修改了……这是一个完全失败的lol get\u cstring正在制作一个co所以你修改了副本,而不是原始版本是什么让你认为在Rcpp中重新实现会比R的内置
toupper
函数快?@OlivierSohn这是不正确的,链接也没有声明这一点。这并不能解释为什么OP的代码会产生一个看起来相同但测试
不相同的字符串
toupper
(或您的代码)的结果。即使用
charToRaw
检查它们也没有任何区别,它们的编码是相同的,而且似乎没有任何属性。谢谢你的回答。但是,正如我所说的,我宁愿避免使用std::字符串。正如@KonradRudolph所说的,主要的一点是不理解发生了什么。@Konrad:当然,但正如bee所说的那样n如前所述,如果一个人的目标是射中自己的脚,那么直接进入C级例程是一个不错的选择;-)如果OP编造了一些不通过
相同的
,这不是我的问题。我们(字面上)有数千个Rcpp代码的入口点通过了。这是他的问题,不是我的问题。这对他来说肯定是一个很好的学习机会。或者用不同的措辞:我们的目标是提供更高级别的访问,这样用户就不必担心按位标识。人们通常只是免费获得它:Rcpp创建的对象通常与R创建的对象没有区别一个。在这里,他设法打破了这一局面,用国产代码绕过了我们的结构。这将是…他的问题不是我的,但正如a所说,这可能是一个很好的学习和调试机会。@Dirkedelbuettel说到正确的教学方法,我完全站在你一边,而不是给出XY问题的字面答案。然而,你在刷牙撇开一个非常有趣的问题不谈吧:
idential
失败的原因绝对不明显——事实上,即使在查看了
R\u compute\u idential
的源代码后,我也不知道这里会发生什么。我唯一能看到的是,他们的
sxpinfo->obj
标志不同C++上的馅饼听起来很愚蠢。有比OP的方法更好的方法。好的回答,谢谢你花时间做这件事。谢谢。我知道,直接处理内存是不安全的。我会检查我的代码,看看我在其他地方没有破解。我猜这个存储是MOR。e比单个字符链复杂。@ArnaudFeld它或多或少是存储字符串dat的字符数组+头