[Rcpp-devel] Bug: replace_last()

Kevin Ushey kevinushey at gmail.com
Mon May 16 20:04:51 CEST 2016


Thanks -- it looks to me like there is something more fundamentally
wrong with the 'replace_first' and 'replace_last' methods; ie, I don't
think we want to be using 'find_first_of' and 'find_last_of'
functions.

Ie, when writing

    string.replace_first("foo", "bar");

I imagine we want to replace the first occurrence of 'foo' with 'bar',
and not the first discovered character of 'f' and 'o'.

A simple repro for the bogus behavior:

#include <Rcpp.h>
using namespace Rcpp;

// [[Rcpp::export]]
String replace() {
  String foo("abba");
  return foo.replace_first("ba", "BA");
}

/*** R
replace()
*/

gives

> replace()
[1] "BAba"

which is I doubt what anyone would expect.

On Sun, May 8, 2016 at 6:14 AM, 津田真樹 <teuder at gmail.com> wrote:
> I find a bug in String::replace_last().
>
> I can reproduce the bug with the following code.
> (I also showed output of replace_first and replace_all for comparison.)
>
>
> =============
> // [[Rcpp::export]]
> void rcpp_string(){
>
>     String s("abcdabcd");
>     Rcout << "replace_first()\n";
>     Rcout << s.replace_first("ab", "AB").get_cstring() << "\n";
>     Rcout << "\n";
>
>     s="abcdabcd";
>     Rcout << "replace_last()\n";
>     Rcout << s.replace_last("ab", "AB").get_cstring()  << "\n";
>     Rcout << "\n";
>
>     s="abcdabcd";
>     Rcout << "replace_all()\n";
>     Rcout << s.replace_all("ab", "AB").get_cstring()  << "\n";
>     Rcout << "\n";
> }
> =============
>
> output
> =============
> replace_first()
> ABcdabcd
>
> replace_last()
> abcdaABd
>
> replace_all()
> ABcdABcd
> =============
>
>
> I also tried to fix the bug with following code. And the bug seems to be fixed.
>
> =============
> inline String& replace_last(const char* s, const char* news) {
>     RCPP_STRING_DEBUG_2("String::replace_last(const char* = '%s' , const char* = '%s')", s, news);
>     if (is_na()) return *this;
>     setBuffer();
>     //size_t index = buffer.find_last_of(s);
>     size_t index = buffer.find_last_of(s) - (strlen(s)-1);
>     Rcout << "A" << index << "\n";
>     if (index != std::string::npos) buffer.replace(index, strlen(s), news);
>     valid = false;
>     return *this;
> }
> =============
>
> output
> =============
> replace_first()
> ABcdabcd
>
> replace_last()
> abcdABcd
>
> replace_all()
> ABcdABcd
> =============
>
>
> Mac OS 10.10.5
> R version 3.2.3
> Rcpp 0.12.4
>
>
> _______________________________________________
> Rcpp-devel mailing list
> Rcpp-devel at lists.r-forge.r-project.org
> https://lists.r-forge.r-project.org/cgi-bin/mailman/listinfo/rcpp-devel


More information about the Rcpp-devel mailing list