Thread: Getting a non-const c_str from a string

  1. #1
    Registered User
    Join Date
    Dec 2006
    Posts
    69

    Getting a non-const c_str from a string

    How could I get a normal, non-const char array (c-style string) from a string object? I need this because I have a function that requires a char* (non-const) and using string.c_str() returns a const char*.. The function that requires the char* doesn't appear to be altering the string, but since I haven't written the function, I can't just go and change it.

  2. #2
    Confused Magos's Avatar
    Join Date
    Sep 2001
    Location
    Sweden
    Posts
    3,145
    const_cast<char*>(Text.c_str())
    MagosX.com

    Give a man a fish and you feed him for a day.
    Teach a man to fish and you feed him for a lifetime.

  3. #3
    Registered User
    Join Date
    Dec 2006
    Posts
    69
    Thanks for the fast reply. Works perfectly.

  4. #4
    Registered User
    Join Date
    Apr 2003
    Posts
    2,663
    Too ugly. All you need to do is copy the characters in the const cstring to the location of a non-constant variable you declare. You can use strcpy() if you want, or you can use this elegant solution posted by Daved earlier this week:
    Code:
    #include<iostream>
    #include<string>
    #include<vector>
    using namespace std;
    
    void some_func(char* s)
    {
    	s[0] = 'X';
    	cout<<s<<endl;
    }
    
    int main()
    {
    	string myStr = "hello";
    	
    	vector<char> str(myStr.begin(), myStr.end());
    	str.push_back('\0');
    
    	some_func(&str[0]);
    
    	return 0;
    }

  5. #5
    Registered User
    Join Date
    Dec 2006
    Posts
    69
    Hi 7stud,

    What is wrong with the const_cast? Where could this lead to problems, and how is it ugly (at first glance, it seems like it will clutter my code much less than Daved's code)? I have heard that casting in general is 'bad', but I cannot remember the rationale behind it. I'm quite new to C++..
    Last edited by C+/-; 01-20-2007 at 07:24 AM.

  6. #6
    erstwhile
    Join Date
    Jan 2002
    Posts
    2,227
    The std::string manages it's own memory internally which is why, when it returns a pointer to that memory directly as it does with the c_str() function it makes sure it's constant so that your compiler will warn you if you try to do something incredibly silly like attempt to change it.

    Using const_cast in that way literally casts away such safety and is only an arguably acceptable practice if you are absolutely sure that memory will not be modified. If you can't guarantee this then you must copy the string and use the copy; it's certainly a lot safer to do this in any event.

    Here's a variation of 7stud's safe approach:.
    Code:
    #include <iostream>
    #include <string>
    #include <vector>
    
    namespace 
    {
      char* GetNonConstStr(const std::string& s)
      {
      //return non-constant copy of s.c_str()
      static std::vector<char> var;
      var.assign(s.begin(),s.end());
      var.push_back('\0');
      return &var[0];
      }
      
      void someCFunction(char* str)
      {
        std::cout<<str<<std::endl;
      }
    }
    
    int main()
    {
    std::string s("hello world");
    std::string t("hello multiverse");
    
    someCFunction(GetNonConstStr(s));
    someCFunction(GetNonConstStr(t));
    }
    CProgramming FAQ
    Caution: this person may be a carrier of the misinformation virus.

  7. #7
    Hurry Slowly vart's Avatar
    Join Date
    Oct 2006
    Location
    Rishon LeZion, Israel
    Posts
    6,788
    problem with the last solution - it uses static local var, so is not thread safe and return value of two calls cannot be used together
    All problems in computer science can be solved by another level of indirection,
    except for the problem of too many layers of indirection.
    – David J. Wheeler

  8. #8
    Confused Magos's Avatar
    Join Date
    Sep 2001
    Location
    Sweden
    Posts
    3,145
    If the function doesn't modify the string (as stated by the OP) it's perfectly valid to use const_cast. Many older (or poorly engineered) libs tend to use char* instead of const char* as string arguments.
    MagosX.com

    Give a man a fish and you feed him for a day.
    Teach a man to fish and you feed him for a lifetime.

  9. #9
    Registered User
    Join Date
    May 2003
    Posts
    1,619
    Yeah, you would ONLY want to cast if you were sure that the function was const-incorrect, and that it didn't actually modify.
    You ever try a pink golf ball, Wally? Why, the wind shear on a pink ball alone can take the head clean off a 90 pound midget at 300 yards.

  10. #10
    Registered User
    Join Date
    Jun 2005
    Posts
    6,815
    Quote Originally Posted by Magos
    If the function doesn't modify the string (as stated by the OP) it's perfectly valid to use const_cast. Many older (or poorly engineered) libs tend to use char* instead of const char* as string arguments.
    True. But the OP actually stated a belief that the function doesn't modify its string argument. I would want to know before using const_cast<> to pass const data. The OP did not state how he came to that conclusion. For example, did the documentation for the function he's calling state the argument is not modified? Or was that belief based on a couple of test cases which may or may not support a general conclusion? In the interests of having better assurances of safety, I would copy it. Then the only possibility of undefined behaviour is the function falling off the end of the array.

    In any event, there is nothing in principle from stopping std::string.c_str() returning a copy of its internal data (as, internally, there is no requirement that a std::string be terminated by NULL byte). So the worst case performance of making a copy is no worse than the worst case of using c_str() and const_cast<>. But making a copy offers better chance of behaving correctly.

  11. #11
    Registered User
    Join Date
    Apr 2003
    Posts
    2,663
    In any event, there is nothing in principle from stopping std::string.c_str() returning a copy of its internal data (as, internally, there is no requirement that a std::string be terminated by NULL byte).
    I don't think that is correct. I think c_str() is guaranteed to return you a cstyle string with a terminating '\0' regardless of what is stored internally in the string object. I haven't dug up the code to look at it, but every description of c_str() I've ever read says it returns a cstyle string with a terminating '\0'.
    Last edited by 7stud; 01-21-2007 at 07:22 AM.

  12. #12
    Algorithm Dissector iMalc's Avatar
    Join Date
    Dec 2005
    Location
    New Zealand
    Posts
    6,318
    Just use const_cast if you are totally sure that the function does not modify the passed parameter.
    That is exactly what it is for, afterall!

  13. #13
    Registered User
    Join Date
    Jun 2005
    Posts
    6,815
    Quote Originally Posted by 7stud
    I don't thing that is correct. I think c_str() is guaranteed to return you a cstyle string with a terminating '\0' regardless of what is stored internally in the string object. I haven't dug up the code to look at it, but every description of c_str() I've ever read says it returns a cstyle string with a terminating '\0'.
    c_str() is guaranteed to return a c-style string. What I was saying is that, internally, a std::string is not required to store it's data as a c-style string.

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. String Class
    By BKurosawa in forum C++ Programming
    Replies: 117
    Last Post: 08-09-2007, 01:02 AM
  2. We Got _DEBUG Errors
    By Tonto in forum Windows Programming
    Replies: 5
    Last Post: 12-22-2006, 05:45 PM
  3. Calculator + LinkedList
    By maro009 in forum C++ Programming
    Replies: 20
    Last Post: 05-17-2005, 12:56 PM
  4. Linked List Help
    By CJ7Mudrover in forum C Programming
    Replies: 9
    Last Post: 03-10-2004, 10:33 PM
  5. Something is wrong with this menu...
    By DarkViper in forum Windows Programming
    Replies: 2
    Last Post: 12-14-2002, 11:06 PM