How to convert a std::string to const char* or char*?
如何将
如果只想将
1 2 | std::string str; const char * c = str.c_str(); |
如果你想得到一个可写的副本,比如
1 2 3 4 5 6 7 | std::string str; char * writable = new char[str.size() + 1]; std::copy(str.begin(), str.end(), writable); writable[str.size()] = '\0'; // don't forget the terminating 0 // don't forget to free the string after finished using it delete[] writable; |
编辑:请注意,上述内容并非异常安全。如果
当超出范围时,
1 2 3 4 5 6 7 8 9 | std::string str; boost::scoped_array<char> writable(new char[str.size() + 1]); std::copy(str.begin(), str.end(), writable.get()); writable[str.size()] = '\0'; // don't forget the terminating 0 // get the char* using writable.get() // memory is automatically freed if the smart pointer goes // out of scope |
STD::载体
这是标准方法(不需要任何外部库)。您使用
1 2 3 4 5 | std::string str; std::vector<char> writable(str.begin(), str.end()); writable.push_back('\0'); // get the char* using &writable[0] or &*writable.begin() |
给定的说………………… </P >好。
1 | std::string x ="hello"; |
(一)"越来越"或"char * const char *"从"字符串"
(一)技术对山羊是字符指针的有效输入范围随
C + + 11 simplifies下面所有的东西;给访问同样的内部缓冲区的字符串: </P >好。
1 2 3 4 5 | const char* p_c_str = x.c_str(); const char* p_data = x.data(); const char* p_x0 = &x[0]; char* p_x0_rw = &x[0]; // compiles iff x is not const... |
所有以上分将保持同样的地址值的第一个字符的缓冲区。甚至有一个空字符串"的第一个字符在缓冲区",因为C + +包一直保持到11个额外的现在。/ 0字符后的《终结者explicitly指定字符串的内容(例如
在给定的任何部分: </P >好。
1 2 | char c = p[n]; // valid for n <= x.size() // i.e. you can safely read the NUL at p[x.size()] |
仅用于非
1 2 | p_x0_rw[n] = c; // valid for n <= x.size() - 1 // i.e. don't overwrite the implementation maintained NUL |
A现在。在写作《字符串是不变化的
C++ 03,事情更复杂的是considerably(关键的差异highlighted): </P >好。
-
x.data() </P >好。- 剧情
const char* 到字符串的内部缓冲区,这我不需要到农村,和一个标准的conclude(即现在。其次可能会问['h', 'e', 'l', 'l', 'o'] 村未初始化存储或垃圾值,与accidental accesses thereto具有undefined行为)。-
x.size() 读人物是安全的",即x[x.size() - 1] x[0] 通 - 为空字符串,y-o-u-r-e保证和控制的一些非空指针,车辆可以做safely添加0(hurray!)不,但你是指针的引用。
-
- 剧情
-
&x[0] </P >好。- 这就为空字符串(undefined行为21.3.4)
- 例如,给定的
f(const char* p, size_t n) { if (n == 0) return; ...whatever... } 你不要的f(&x[0], x.size()); 呼叫时使用f(x.data(), ...) x.empty() 哦。
- 例如,给定的
- 此外,作为一
x.data() 但:- 非
const yieldsx 这一非const char* 指针;你可以overwrite字符串的内容
- 非
- 这就为空字符串(undefined行为21.3.4)
-
x.c_str() </P >好。- 剧情
const char* 安(到现在。asciiz端基)表示的值(即"H"、"E"、"L"、"L"、"O"、"0"])。 - 尽管少,如果选择了做任何implementations SO,《C++ 03标准是worded to allow the字符串执行"create a成不同的自由到现在。-封端的缓冲区的运行,从潜在的非现在。端缓冲区的"暴露"和
&x[0] x.data() 村 -
x.size() + 1的特点是"安全"的读。 - 安全保证和控制,甚至为空字符串("0")。
- 剧情
访问的法律后果外指数
whichever路你得到一个指针,你必须不访问存储器,从指针的存在进一步保证和控制的礼物比人物的描述上。attempts做这么有undefined行为,和一个非常好的实时应用程序crashes和垃圾的结果,即使在读取数据,和additionally批发业务,把腐败和/或安全vulnerabilities writes指南。 </P >好。 这些指针何时失效?
如果调用某个修改
另请参阅如何获取即使在
从C++ 11,使用ECDCX1,4为ASCIZ数据,EDCOX1,5为"二进制"数据(下面进一步解释)。好的。
在C++ 03中,使用EDCOX1 OR 4 }除非EDCOX1〔5〕是足够的,并且在EDCOX1×9的条件下更倾向于EDCOX1×5,因为它对于空字符串是安全的。好的。
…尽量理解程序,在适当的时候使用
由
给定C++ 03的EDCOX1,4的关于返回的缓冲区的保证是EDOCX1×5的超级集合,您总是可以安全地使用EDCOX1×4,但是人们有时不这样做是因为:好的。
- 使用
.data() 与其他读取源代码的程序员通信,数据不是asciiz(相反,您使用字符串来存储数据块(有时甚至不是真正的文本数据块),或者将其传递给另一个将其视为"二进制"数据块的函数。这对于确保其他程序员的代码更改继续正确地处理数据是至关重要的。 - C++ 03:只有一个机会,您的EDCOX1×0实现需要进行额外的内存分配和/或数据复制,以准备NUL终止的缓冲区。
作为进一步的提示,如果函数的参数需要(
您需要将
要将文本从
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 | // USING ANOTHER STRING - AUTO MEMORY MANAGEMENT, EXCEPTION SAFE std::string old_x = x; // - old_x will not be affected by subsequent modifications to x... // - you can use `&old_x[0]` to get a writable char* to old_x's textual content // - you can use resize() to reduce/expand the string // - resizing isn't possible from within a function passed only the char* address std::string old_x = x.c_str(); // old_x will terminate early if x embeds NUL // Copies ASCIIZ data but could be less efficient as it needs to scan memory to // find the NUL terminator indicating string length before allocating that amount // of memory to copy into, or more efficient if it ends up allocating/copying a // lot less content. // Example, x =="ab\0cd" -> old_x =="ab". // USING A VECTOR OF CHAR - AUTO, EXCEPTION SAFE, HINTS AT BINARY CONTENT, GUARANTEED CONTIGUOUS EVEN IN C++03 std::vector<char> old_x(x.data(), x.data() + x.size()); // without the NUL std::vector<char> old_x(x.c_str(), x.c_str() + x.size() + 1); // with the NUL // USING STACK WHERE MAXIMUM SIZE OF x IS KNOWN TO BE COMPILE-TIME CONSTANT"N" // (a bit dangerous, as"known" things are sometimes wrong and often become wrong) char y[N + 1]; strcpy(y, x.c_str()); // USING STACK WHERE UNEXPECTEDLY LONG x IS TRUNCATED (e.g. Hello\0->Hel\0) char y[N + 1]; strncpy(y, x.c_str(), N); // copy at most N, zero-padding if shorter y[N] = '\0'; // ensure NUL terminated // USING THE STACK TO HANDLE x OF UNKNOWN (BUT SANE) LENGTH char* y = alloca(x.size() + 1); strcpy(y, x.c_str()); // USING THE STACK TO HANDLE x OF UNKNOWN LENGTH (NON-STANDARD GCC EXTENSION) char y[x.size() + 1]; strcpy(y, x.c_str()); // USING new/delete HEAP MEMORY, MANUAL DEALLOC, NO INHERENT EXCEPTION SAFETY char* y = new char[x.size() + 1]; strcpy(y, x.c_str()); // or as a one-liner: char* y = strcpy(new char[x.size() + 1], x.c_str()); // use y... delete[] y; // make sure no break, return, throw or branching bypasses this // USING new/delete HEAP MEMORY, SMART POINTER DEALLOCATION, EXCEPTION SAFE // see boost shared_array usage in Johannes Schaub's answer // USING malloc/free HEAP MEMORY, MANUAL DEALLOC, NO INHERENT EXCEPTION SAFETY char* y = strdup(x.c_str()); // use y... free(y); |
希望从
因此,在上面,您已经看到了如何获取(
- 将"C"代码访问到C++ EDCOX1×2的文本,如EDCOX1×7
- 将
x 的文本复制到函数调用方(如strncpy(callers_buffer, callers_buffer_size, x.c_str()) 指定的缓冲区)或用于设备I/O的易失性内存(如for (const char* p = x.c_str(); *p; ++p) *p_device = *p; 指定的缓冲区中。 - 将
x 的文本附加到已经包含某些asciiz文本(例如strcat(other_buffer, x.c_str()) 的字符数组)的字符数组中-注意不要溢出缓冲区(在许多情况下,可能需要使用strncat ) - 从函数返回
const char* 或char* (可能是由于历史原因-客户端正在使用您现有的API-或出于C兼容性,您不想返回std::string ,但确实想为调用者在某处复制您的string 的数据)- 注意不要返回指针指向的本地
string 变量离开作用域后调用方可能取消引用的指针。 - 某些具有为不同
std::string 实现编译/链接的共享对象的项目(例如stlport和compiler native)可能将数据作为asciiz传递,以避免冲突。
- 注意不要返回指针指向的本地
好啊。
对
您可以使用
没有保证所有的字符都是同一个连续缓冲区的一部分,直到C++ 11,但是实际上,所有已知的
注意,许多
C++ 17
C++ 17(即将到来的标准)改变模板EDCOX1的大纲(21):添加EconCx1的非const过载(22):
charT* data() noexcept; Returns: A pointer p such that p + i == &operator for each i in [0,size()].
来自
1 2 | std::string const cstr = {"..." }; char const * p = cstr.data(); // or .c_str() |
来自
1 2 | std::string str = {"..." }; char * p = str.data(); |
C++ 11来自
1 2 | std::string str = {"..." }; str.c_str(); |
来自
从C++ 11开始,该标准称:
The char-like objects in a basic_string object shall be stored contiguously. That is, for anybasic_string objects , the identity&*(s.begin() + n) == &*s.begin() + n shall hold for all values ofn such that0 <= n < s.size() .
const_reference operator[](size_type pos) const;
reference operator[](size_type pos); Returns:
*(begin() + pos) ifpos < size() , otherwise a reference to an object of typeCharT with valueCharT() ; the referenced value shall not be modified.
const charT* c_str() const noexcept; const charT* data() const noexcept; Returns: A pointer p such that
p + i == &operator[](i) for eachi in[0,size()] .
有几种可能的方法来获取非常量字符指针。
1。使用C++ 11的连续存储1 2 | std::string foo{"text"}; auto p = &*foo.begin(); |
赞成
- 简单和简短
- 快速(仅限不涉及副本的方法)
欺骗
- 最终的
'\0' 不需要改变/不一定是非常量存储器的一部分。
2。使用
1 2 3 | std::string foo{"text"}; std::vector<char> fcv(foo.data(), foo.data()+foo.size()+1u); auto p = fcv.data(); |
赞成
- 简单的
- 自动内存处理
- 动态的
欺骗
- 需要字符串副本
三。如果
1 2 3 | std::string foo{"text"}; std::array<char, 5u> fca; std::copy(foo.data(), foo.data()+foo.size()+1u, fca.begin()); |
赞成
- 简单的
- 堆栈内存处理
欺骗
- 静态的
- 需要字符串副本
4。自动删除存储的原始内存分配
1 2 3 | std::string foo{"text" }; auto p = std::make_unique<char[]>(foo.size()+1u); std::copy(foo.data(), foo.data() + foo.size() + 1u, &p[0]); |
赞成
- 内存占用小
- 自动删除
- 简单的
欺骗
- 需要字符串副本
- 静态(动态使用需要更多的代码)
- 比向量或数组的特征少
5。手动处理的原始内存分配
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | std::string foo{"text" }; char * p = nullptr; try { p = new char[foo.size() + 1u]; std::copy(foo.data(), foo.data() + foo.size() + 1u, p); // handle stuff with p delete[] p; } catch (...) { if (p) { delete[] p; } throw; } |
赞成
- 最大"控制"
反对的论点
- 需要字符串副本
- 最大责任/错误敏感性
- 复合物
我正在使用一个API,它有许多函数get作为输入a
我创建了一个小类来面对这种问题,我已经实现了raii习语。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 | class DeepString { DeepString(const DeepString& other); DeepString& operator=(const DeepString& other); char* internal_; public: explicit DeepString( const string& toCopy): internal_(new char[toCopy.size()+1]) { strcpy(internal_,toCopy.c_str()); } ~DeepString() { delete[] internal_; } char* str() const { return internal_; } const char* c_str() const { return internal_; } }; |
您可以将其用作:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | void aFunctionAPI(char* input); // other stuff aFunctionAPI("Foo"); //this call is not safe. if the function modified the //literal string the program will crash std::string myFoo("Foo"); aFunctionAPI(myFoo.c_str()); //this is not compiling aFunctionAPI(const_cast<char*>(myFoo.c_str())); //this is not safe std::string //implement reference counting and //it may change the value of other //strings as well. DeepString myDeepFoo(myFoo); aFunctionAPI(myFoo.str()); //this is fine |
我之所以称为
1 | char* result = strcpy((char*)malloc(str.length()+1), str.c_str()); |
看看这个:
1 2 | string str1("stackoverflow"); const char * str2 = str1.c_str(); |
但是,请注意,这将返回一个
试试这个
1 | std::string s(reinterpret_cast<const char *>(Data), Size); |