1

Suppose I have a really complicated buffer scrambling function that does something with the following prototype:

void do_something(char * thebuffer, int thelength);

And suppose I need to get the function working on an std::string. But std::string.c_str() returns const char*, which is not mutable.

Besides making a new char* buffer, and passing it to do_something, is it possible to use do_something for an std::string?

My situation is actually currently the other way around (a char *, int into a std::string& taking function).

Or is the only way to go around this, is to go make a new copy of the function, which does the same thing? (which doesn't really scream good style)

kamziro
  • 7,882
  • 9
  • 55
  • 78
  • 1
    How big is your string? why don't you want to copy? – OSH Nov 30 '11 at 07:02
  • 1
    side note: `std::vector` is a better type for a buffer than a string. Than you would just use `&myvec[0]` as a `char*`. – Joe McGrath Nov 30 '11 at 07:06
  • "(which doesn't really scream good style)" - one overload can be implemented in terms of another overload, you shouldn't duplicate code itself. – UncleBens Nov 30 '11 at 07:21

3 Answers3

5

You can safely cast it as long as it doesn't go past the size

do_something((char *)mystring.c_str(), mystring.size());

or

do_something(&mystring[0], mystring.size());

or more C++ish

do_something(const_cast<char *>(mystring.c_str()), mystring.size());

side note:

std::vector<char> is a better type for a buffer than a string. Than you would just use &myvec[0] as a char*

Joe McGrath
  • 1,481
  • 10
  • 26
  • Be carefull, as in C++03, the std::string class is not required to use contiguous memory for it's representation (http://stackoverflow.com/questions/1986966/does-s0-point-to-contiguous-characters-in-a-stdstring). Hopefully it will be in C++0x (http://stackoverflow.com/questions/6077189/will-stdstring-always-be-null-terminated-in-c0x) – Drahakar Nov 30 '11 at 06:59
  • @Drahakar but there is no other (sensible) way to implement it. It has to be able to return c_str(); – Joe McGrath Nov 30 '11 at 07:00
  • 1
    at least use a C++ cast (const_cast) – AndersK Nov 30 '11 at 07:01
  • You can't reduce the size as well. – OSH Nov 30 '11 at 07:01
  • I remember reading a long time ago in the documentation that in future versions of STL a string might not be implemented as an array (optimization for very long strings?) so using c_str that way is not best practice, but it's probably fine, I doubt they will ever implement string any other way than an array. – sashoalm Nov 30 '11 at 07:01
  • @OrenS. strings can contain '\0' – Joe McGrath Nov 30 '11 at 07:02
  • 1
    If we can assume contiguous memory, then `&str[0]` should be OK for a string as well. – UncleBens Nov 30 '11 at 07:19
  • @Joe McGrath. If you reduce the string size the old c method, and then attempt to use .length() you will get some nice bugs. Future generations will remember you... :) – OSH Nov 30 '11 at 08:02
  • if the function puts a 0 in your string all you need is a `std::string a = b.c_str();` not sure how that is worse than using a character array the whole time. Question said it is "scrambling a buffer". Regardless I wouldn't use a string for this. – Joe McGrath Nov 30 '11 at 08:23
  • Be careful though to use another string, a = b.c_str() is fine but b = b.c_str() might crash I think. – sashoalm Nov 30 '11 at 09:59
1

You can make it a template function and then pass it a string::iterator instead of char*. Or simply make it accept string::iterator. If you only use sequential access you might not need to rewrite anything else in your function.

void do_something(string::iterator thebuffer, int thelength);
sashoalm
  • 75,001
  • 122
  • 434
  • 781
0

Not make a new function, but overload the current one and just pass stuff through.

void do_something(std::vector<char>& buf){
  do_something(&buf[0], buf.size());
}

Saves you from the hassle of casting and stuff when calling your function.

Xeo
  • 129,499
  • 52
  • 291
  • 397