61513

c++ strtok in function changes original string value as parameter

Question:

when I use strtok to tokenize a c++ string, it happens a confusing problem, see the simple code below:

void a(string s){ strtok((char*)s.c_str(), " "); } int main(){ string s; s = "world hello"; a(s); cout<<s<<endl; return 0; }

the program outputs "world". Shouldn't it output "world hello"? Because I pass the string as a value parameter to function a, the strtok shouldn't modify the original s... Can anyone explain this trick. thank you.

Answer1:

The problem is (char*)s.c_str(), you are casting the constness away and modified the string contents in a way that you are not supposed to. While the original s should not be modified, I pressume you may have been hit by a smart optimization that expects you to play by the rules. For instance, a COW implementation of string would happen to show that behavior.

Answer2:

c_str() returns a const pointer, which is a promise to the compiler that the thing being pointed at won't be modified. And then you're calling strtok which modifies it.

When you lie to the compiler, you will be punished.

Answer3:

That's the way strtok() works. It use the first parameter as a buffer. By casting it to a char*, you allow it to modify the string. strtok() does not known about the original std::string. It also store the string pointer in a static variable, that's why you have to call it with a null pointer the next times to continue to parse the same string.

By the way, in c++, you should use std::istringstream instead. It does not use an internal static variable, which is not thread-safe. And you can extract the parameters directly into int, double, etc like we do with cin. std::ostringstring replace sprintf().

Recommend

  • Behavior of self-assignment with const ref parameter
  • How to access an object representation according to the c++ standard?
  • Multiple Dispatch with Generics
  • OpenCV imread with foreign characters
  • Cast uint -> double invalid?
  • Is it possible to specialize on a static lifetime?
  • How to eliminate warning for passing multidimensional array as const multidimensional array?
  • Quick Question About Get and Set
  • @tailrec why does this method not compile with 'contains a recursive call not in tail position&
  • What command do i need to pass in SabreCommandLLSRQ to get current price of PNR?
  • redirect_to root_url and return unless @user.activated
  • JSR-330 support in Picocontainer : @Inject … @Named(\"xxx)
  • SQL Query - Table Joining Problems
  • Creating a DropDownList
  • How to autopopulate a field in SugarCRM form
  • Who propagate bugfixes across branches (corporate development)?
  • Cannot get the UserManager class
  • xcode don't localize specific strings
  • C++ pointer value changes with static_cast
  • Zurb Foundation _global.scss meta styles for js?
  • Unable to decode certificate at client new X509Certificate2()
  • OOP Javascript - Is “get property” method necessary?
  • Needing to do .toArray() to get output of mongodb .find() on key name not value
  • Scrapy recursive link crawler
  • ilmerge with a PFX file
  • Master page gives error
  • TFS: Get latest causes slow project reloading
  • Deserializing XML into class C#
  • Symfony2: How to get request parameter
  • Redux, normalised entities and lodash merge
  • ORA-29908: missing primary invocation for ancillary operator
  • Function pointer “assignment from incompatible pointer type” only when using vararg ellipsis
  • python draw pie shapes with colour filled
  • Django query for large number of relationships
  • Running Map reduces the dimensions of the matrices
  • Binding checkboxes to object values in AngularJs
  • How to Embed XSL into XML
  • Net Present Value in Excel for Grouped Recurring CF
  • jQuery Masonry / Isotope and fluid images: Momentary overlap on window resize
  • How to load view controller without button in storyboard?