replace(char) String function? [SOLVED]



  • On 25/10/2014 at 10:47, xxxxxxxx wrote:

    User Information:
    Cinema 4D Version:   13 
    Platform:   Windows  ;   
    Language(s) :     C++  ;

    ---------
    Hi,
    Is there a replace function for strings in the SDK?

    I have a string like this: Foo%20Foo%20Foo%20/index.html
    And I wat to convert it to this: Foo Foo Foo/index.html

    The %20 stuff is coming from my htmlViewerCallback() SDK function.
    And I'd like to convert it to a regular Filename format with spaces.
    Replacing every %20 instance with a space.

    -ScottA



  • On 25/10/2014 at 16:03, xxxxxxxx wrote:

    I had to do this same thing recently, and couldn't find such a function in the SDK. You can write one yourself though, it's very easy.

    Steve



  • On 25/10/2014 at 16:27, xxxxxxxx wrote:

    I was afraid of that Steve,
    I ended up using the STL regex to do it. Because the RegularExprParser in the SDK seem to be far too primitive to do this without writing a ton of code.
    I'd prefer to stick to using the SDK as much as possible. But that R.E.P. class really needs some TLC by Maxon.

    void htmlViewerCallback(void *user_data, const String &url, LONG encoding, void *reserved)  
    {  
      //Prints the path to the webpage in the console when the hyperlink is clicked on  
      //This takes some time because it fetches the webpage..that's why a callback function is required  
      //GePrint(url);  
      
      //The url string value returned is formatted with %20 for spaces. And forward leaning slashes  
      //So this is how to convert it to a normal Windows file path type string result  
      
      CHAR buffer[1024];  
      
      //First convert the forward leaning slashes to backwards leaning slashes  
      url.GetCString(buffer, sizeof(buffer));  
      std::string stlurl = buffer;  
      std::tr1::regex rx1("/");  
      std::string replacement1 = "\\";  
      std::string result1 = std::tr1::regex_replace(stlurl, rx1, replacement1);  
      
      //Next replace the %20 instances with spaces  
      std::string stlur2 = result1;  
      std::tr1::regex rx2("%(..)");  
      std::string replacement2 = " ";  
      std::string result = std::tr1::regex_replace(stlur2, rx2, replacement2);  
      String c4dURLresult = result.c_str();  
      
      //Now we need to delete the file:/// crap at the start of the url string  
      for(LONG i=0; i<8; i++)  
      {  
          c4dURLresult _= '\n';  
      }  
      
      //The url converted to a regular filename  
      GePrint(c4dURLresult);  
    }
    

    -ScottA
    _



  • On 26/10/2014 at 01:33, xxxxxxxx wrote:

    Hi Scott,

    I'm not too sure about your code.

    First of all, I have to do strange things to get std::string and regex through the compiler within the SDK. Mainly because regex demands to have exceptions. To work around this with a define or (even worse) by enabling exceptions for the SDK is dangerous. The SDK disables exception handling, as handling exceptions (and potential cleanup needs due to an exception) is tricky in a multithreaded environment.

    I really disadvise to enable exception handling for your plugins. If you really need to, you will have to understand exactly what is happening and be aware of the thread context your functions are called in.

    Next, probably just caused by posting this as an example, is the for loop in the end. It simply doesn't do what the comment says it would. Furthermore, it it's not iterating (c4dURLresult is constant). It's simply replacing the string eight times with a linefeed.

    Finally, I don't understand, why you need regular expressions at all in this case.
    Here's my attempt on your htmlViewerCallback():

    void htmlViewerCallback(void *user_data, const String &url, LONG encoding, void *reserved)
    {
      String sResult = url;
      LONG   iPos;
      //Prints the path to the webpage in the console when the hyperlink is clicked on
      //This takes some time because it fetches the webpage..that's why a callback function is required
      GePrint("Before: " + sResult);
      // First we need to delete the file:/// crap at the start of the url string
      if (!sResult.ComparePart("file:///", 8, 0)) {
        sResult.Delete(0, 8);
      }
      // Then convert the forward leaning slashes to backwards leaning slashes
      while (sResult.FindFirst("/", &iPos, 0)) {
        sResult.Delete(iPos, 1);
        sResult.Insert(iPos, "\\");
      }
      // Lastly replace the %20 instances with spaces
      while (sResult.FindFirst("\%20", &iPos, 0)) {
        sResult.Delete(iPos, 3);
        sResult.Insert(iPos, " ");
      }
      GePrint("After: " + sResult);
    }
    

    This is just a quick example and certainly could be done faster and more generic.



  • On 26/10/2014 at 04:12, xxxxxxxx wrote:

    Please note that the replacement of the forward slash to a back slash in an url is only necessary on non-Unix systems (-> Windows).

    If you apply this conversion (of the slashes) to a Unix compatible system (OS X, Linux) then you create a wrong Filename that won't work.

    Best regards,

    Wilfried



  • On 26/10/2014 at 04:14, xxxxxxxx wrote:

    Andreas is absolutely right, just keep it simple and forget all that regular expression stuff. It doesn't need it for something so very simple.



  • On 26/10/2014 at 07:08, xxxxxxxx wrote:

    My code works just fine for me. And I didn't need to enable exceptions. Or do anything special for regex to work Andreas.
    All I did was #include <regex>. And then wrote the code I posted.
    I'm still using VS2010 most of time. I don't know if that matters?

    Thanks for posting your version though.

    -ScottA



  • On 26/10/2014 at 07:13, xxxxxxxx wrote:

    Scott,
    I think this matters, as it may not warn about this with older compiler versions (or if you are lucky the old standard lib doesn't use exceptions for regex).
    I can only stress my words, I disadvise to use any external libraries which may need or make use of exceptions. We won't be able to help, if you run into problems with such stuff.
    Of course there are cases you will need to use external libraries, I fully understand. All I'm saying, I wouldn't do so, if there's no need for it.



  • On 26/10/2014 at 07:17, xxxxxxxx wrote:

    One question to the community, as Scott says, his code is working as posted. How does the following loop help to eliminate the "file:///" prefix, I don't get it?

    for(LONG i=0; i<8; i++) {
      c4dURLresult = '\n';
    }
    


  • On 26/10/2014 at 07:17, xxxxxxxx wrote:

    Ok. Thanks.
    I'm very comfortable using the STL in my code but...

    Originally posted by xxxxxxxx

    I'd prefer to stick to using the SDK as much as possible. __

    -ScottA



  • On 26/10/2014 at 07:19, xxxxxxxx wrote:

    😉



  • On 26/10/2014 at 11:40, xxxxxxxx wrote:

    Actually. That for() loop does NOT work properly.
    The C4D console reports that it does...But it's evil. It's lying to us. Evil Smile
    The C4D console does not show the correct carriage returns, like the VS console does (it removes them).
    I'm glad you mentioned it Andreas. Because I would have wondered what the heck was going on later when I used the returned string.

    This should work better when using the STL regex class.
    But I'm going to use your SDK based code instead.

      
    #include <regex>  
    void htmlViewerCallback(void *user_data, const String &url, LONG encoding, void *reserved)  
    {  
      //Prints the path to the webpage in the console when the hyperlink is clicked on  
      //This takes some time because it fetches the webpage..that's why a callback function is required  
      //GePrint(url);  
      
      //The url string value returned is formatted with %20 for spaces. And forward leaning slashes  
      //So this is how to convert it to a normal Windows file path type string result  
      
      CHAR buffer[1024];  
      
      //First convert the forward leaning slashes to backwards leaning slashes  
      url.GetCString(buffer, sizeof(buffer));  
      std::string stlurl = buffer;  
      std::tr1::regex rx1("/");  
      std::string replacement1 = "\\";  
      std::string result1 = std::tr1::regex_replace(stlurl, rx1, replacement1);  
      
      //Next replace the %20 instances with spaces  
      std::string stlur2 = result1;  
      std::tr1::regex rx2("%(..)");  
      std::string replacement2 = " ";  
      std::string result = std::tr1::regex_replace(stlur2, rx2, replacement2);  
      
      //Now we need to delete the file:/// crap at the start of the url string      
      for(int i=0; i<8; i++)  
      {  
          result.erase(result.begin());  
      }  
      
      //The url converted to a regular filename  
      String c4dURLresult = result.c_str();  
      GePrint(c4dURLresult);  
    }
    

    Thanks for the help guys,
    -ScottA



  • On 26/10/2014 at 13:09, xxxxxxxx wrote:

    I marked this solved.
    Yet, I want to emphasize Wilfried's post. You'll have to care for more systems but Windows.



  • On 27/10/2014 at 09:13, xxxxxxxx wrote:

    Btw, there's std::string::substr() and String::SubStr(). Easier to read and by far more efficient than
    erasing the first character in a for loop.


Log in to reply