Can I get a non-const C string back from a C++ string?

前端 未结 13 1184
借酒劲吻你
借酒劲吻你 2020-12-01 15:33

Const-correctness in C++ is still giving me headaches. In working with some old C code, I find myself needing to assign turn a C++ string object into a C string and assign i

相关标签:
13条回答
  • 2020-12-01 16:06

    Is it really that difficult to do yourself?

    #include <string>
    #include <cstring>
    
    char *convert(std::string str)
    {
        size_t len = str.length();
        char *buf = new char[len + 1];
        memcpy(buf, str.data(), len);
        buf[len] = '\0';
        return buf;
    }
    
    char *convert(std::string str, char *buf, size_t len)
    {
        memcpy(buf, str.data(), len - 1);
        buf[len - 1] = '\0';
        return buf;
    }
    
    // A crazy template solution to avoid passing in the array length
    // but loses the ability to pass in a dynamically allocated buffer
    template <size_t len>
    char *convert(std::string str, char (&buf)[len])
    {
        memcpy(buf, str.data(), len - 1);
        buf[len - 1] = '\0';
        return buf;
    }
    

    Usage:

    std::string str = "Hello";
    // Use buffer we've allocated
    char buf[10];
    convert(str, buf);
    // Use buffer allocated for us
    char *buf = convert(str);
    delete [] buf;
    // Use dynamic buffer of known length
    buf = new char[10];
    convert(str, buf, 10);
    delete [] buf;
    
    0 讨论(0)
  • 2020-12-01 16:10

    In CPP, if you want a char * from a string.c_str() (to give it for example to a function that only takes a char *), you can cast it to char * directly to lose the const from .c_str()

    Example:

    launchGame((char *) string.c_str());
    
    0 讨论(0)
  • 2020-12-01 16:13

    You can use the copy method:

    len = myStr.copy(cStr, myStr.length());
    cStr[len] = '\0';
    

    Where myStr is your C++ string and cStr a char * with at least myStr.length()+1 size. Also, len is of type size_t and is needed, because copy doesn't null-terminate cStr.

    0 讨论(0)
  • 2020-12-01 16:13
    std::string vString;
    vString.resize(256); // allocate some space, up to you
    char* vStringPtr(&vString.front());
    // assign the value to the string (by using a function that copies the value).
    // don't exceed vString.size() here!
    // now make sure you erase the extra capacity after the first encountered \0.
    vString.erase(std::find(vString.begin(), vString.end(), 0), vString.end());
    // and here you have the C++ string with the proper value and bounds.
    

    This is how you turn a C++ string to a C string. But make sure you know what you're doing, as it's really easy to step out of bounds using raw string functions. There are moments when this is necessary.

    0 讨论(0)
  • 2020-12-01 16:14

    There is an important distinction you need to make here: is the char* to which you wish to assign this "morally constant"? That is, is casting away const-ness just a technicality, and you really will still treat the string as a const? In that case, you can use a cast - either C-style or a C++-style const_cast. As long as you (and anyone else who ever maintains this code) have the discipline to treat that char* as a const char*, you'll be fine, but the compiler will no longer be watching your back, so if you ever treat it as a non-const you may be modifying a buffer that something else in your code relies upon.

    If your char* is going to be treated as non-const, and you intend to modify what it points to, you must copy the returned string, not cast away its const-ness.

    0 讨论(0)
  • 2020-12-01 16:20

    If you know that the std::string is not going to change, a C-style cast will work.

    std::string s("hello");
    char *p = (char *)s.c_str();
    

    Of course, p is pointing to some buffer managed by the std::string. If the std::string goes out of scope or the buffer is changed (i.e., written to), p will probably be invalid.

    The safest thing to do would be to copy the string if refactoring the code is out of the question.

    0 讨论(0)
提交回复
热议问题