// USING ANOTHER STRING - AUTO MEMORY MANAGEMENT, EXCEPTION SAFEstd::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++03std::vector<char> old_x(x.data(), x.data() + x.size()); // without the NULstd::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 shortery[N] = '\0'; // ensure NUL terminated
// USING THE STACK TO HANDLE x OF UNKNOWN (BUT SANE) LENGTHchar* 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 SAFETYchar* 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 SAFETYchar* y = strdup(x.c_str());// use y...free(y);
void aFunctionAPI(char* input);
// other stuff
aFunctionAPI("Foo"); //this call is not safe. if the function modified the//literal string the program will crashstd::string myFoo("Foo");aFunctionAPI(myFoo.c_str()); //this is not compilingaFunctionAPI(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
// char stringchar chText[20];
// c++ stringstring text = "I am a Programmer";
// conversion from c++ string to char string// this function does not append a null character at the end of operationtext.copy(chText, text.size(), 0);
// we need to put it manuallychText[text.size()] = '\0';
// below statement prints "I am a Programmer"cout << chText << endl;
反之亦然从C样式字符串转换为C++std字符串要容易得多
有三种方法可以将C样式字符串转换为C++std字符串
第一个是使用构造函数,
char chText[20] = "I am a Programmer";// using constructorstring text(chText);
第二个是使用string::assign方法
// char stringchar chText[20] = "I am a Programmer";
// c++ stringstring text;
// convertion from char string to c++ string// using assign functiontext.assign(chText);
第三个是赋值操作符(=),其中字符串类使用运算符重载
// char stringchar chText[20] = "I am a Programmer";
// c++ string// convertion from char string to c++ string using assignment operator overloadingstring text = chText;
第三个也可以写如下-
// char stringchar chText[20] = "I am a Programmer";
// c++ stringstring text;
// convertion from char string to c++ stringtext = chText;
#include <string>constexpr size_t BUFFER_SIZE = 100;std::string str;// IMPORTANT: pre-allocate the underlying buffer to guarantee what size it isstr.resize(BUFFER_SIZE);
// -----------------------------------------------------------------------------// Get read-writeable access to the underlying `char*` C-string at index i// -----------------------------------------------------------------------------
char* c_str1 = &str[i]; // <=== my favorite!char* c_str2 = str.data() + i;char* c_str3 = &(*str.begin()) + i;
// NB: the C-strings above are NOT guaranteed to be null-terminated, so manually// write in a null terminator at the index location where you want it if// desired. Ex://// 1. write a null terminator at some arbitrary position you choose (index 10// here)c_str1[10] = '\0';// 2. write a null terminator at the last guaranteed valid position in the// underlying C-string/array of charsc_str2[str.size() - i - 1] = '\0';
// -----------------------------------------------------------------------------// Get read-only access to the underlying `const char*` C-string at index i// -----------------------------------------------------------------------------const char* const_c_str1 = &str[i];const char* const_c_str2 = str.c_str() + i; // guaranteed to be null-terminated,// but not necessarily at the// position you desire; the// guaranteed null terminator will// be at index location// `str.size()`
#include <string>
constexpr size_t BUFFER_SIZE = 100;
std::string str;// IMPORTANT: pre-allocate the underlying buffer to guarantee what size it isstr.resize(BUFFER_SIZE);
// =============================================================================// Now you can use the `std::string`'s underlying buffer directly as a C-string// =============================================================================
// ---------------------------------------------------------// A. As a read-writeable `char*` C-string// ---------------------------------------------------------
// Technique 1 [best option if using C++11]: array indexing using `operator[]`// to obtain a char, followed by obtaining its address with `&`// - Documentation:// https://en.cppreference.com/w/cpp/string/basic_string/operator_atchar* c_str1 = &str[0];char* c_str2 = &str[10];char* c_str3 = &str[33];// etc.
// Technique 2 [best option if using C++17]: use the `.data()` method to obtain// a `char*` directly.// - Documentation:// https://en.cppreference.com/w/cpp/string/basic_string/datachar* c_str11 = str.data(); // same as c_str1 abovechar* c_str12 = str.data() + 10; // same as c_str2 abovechar* c_str13 = str.data() + 33; // same as c_str3 above
// Technique 3 [fine in C++11 or later, but is awkward, so don't do this. It is// for demonstration and learning purposes only]: use the `.begin()` method to// obtain an iterator to the first char, and then use the iterator's// `operator*()` dereference method to obtain the iterator's `char`// `value_type`, and then take the address of that to obtain a `char*`// - Documentation:// - https://en.cppreference.com/w/cpp/string/basic_string/begin// - https://en.cppreference.com/w/cpp/named_req/RandomAccessIteratorchar* c_str21 = &(*str.begin()); // same as c_str1 and c_str11 abovechar* c_str22 = &(*str.begin()) + 10; // same as c_str2 and c_str12 abovechar* c_str23 = &(*str.begin()) + 33; // same as c_str3 and c_str13 above
// ---------------------------------------------------------// B. As a read-only, null-terminated `const char*` C-string// ---------------------------------------------------------
// - Documentation:// https://en.cppreference.com/w/cpp/string/basic_string/c_str
const char* const_c_str1 = str.c_str(); // a const version of c_str1 aboveconst char* const_c_str2 = str.c_str() + 10; // a const version of c_str2 aboveconst char* const_c_str3 = str.c_str() + 33; // a const version of c_str3 above
std::string str2;std::string* pstr = &str2;pstr->resize(BUFFER_SIZE);c_str = &(*pstr)[0]; // <=== dereference the ptr 1st before indexing into it// Or, to make the order of precedence// (https://en.cppreference.com/w/cpp/language/operator_precedence) really// obvious, you can optionally add extra parenthesis like this:c_str = &((*pstr)[0]);
技巧2[使用C++17时的最佳选择]:使用#0方法直接获得#1。例如:
char* c_str;c_str = str.data();c_str = str.data() + 5;// etc.
// Write these 2 C-strings into the `std::string`'s underlying bufferstrcpy(str.data(), cstr1);strcpy(str.data() + (sizeof(cstr1) - 1), cstr2); // `- 1` to overwrite the// first null terminator
// print the stringstd::cout << str << "\n"; // output: `abcde fghijk`
std::cout << strlen(str.c_str()) << "\n"; // prints `12` in the examples above
// instead of:std::cout << str.size() << "\n"; // prints `100` in the examples above