如何将std::string
转换为char*
或const char*
?
答案 0 :(得分:993)
如果您只想将std::string
传递给需要const char*
的功能,可以使用
std::string str;
const char * c = str.c_str();
如果您想获得可写副本,例如char *
,您可以这样做:
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;
修改:请注意,上述内容并非异常安全。如果new
通话和delete
通话之间发生任何异常,您将泄漏内存,因为没有任何内容会自动为您调用delete
。有两种方法可以解决这个问题。
boost::scoped_array
将在超出范围时为您删除内存:
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::vector
,它可以完全管理您的内存。
std::string str;
std::vector<char> writable(str.begin(), str.end());
writable.push_back('\0');
// get the char* using &writable[0] or &*writable.begin()
答案 1 :(得分:184)
答案 2 :(得分:33)
.c_str()
使用const char *
方法。
您可以使用&mystring[0]
获取char *
指针,但有几个问题:您不一定会得到一个零终止字符串,并且您将无法更改字符串的大小。你尤其要注意不要在字符串末尾添加字符,否则你会得到缓冲区溢出(并且可能会崩溃)。
在C ++ 11之前,无法保证所有字符都是同一个连续缓冲区的一部分,但实际上std::string
的所有已知实现都是这样的。见Does “&s[0]” point to contiguous characters in a std::string?。
请注意,许多string
成员函数将重新分配内部缓冲区,并使您可能已保存的任何指针无效。最好立即使用它们然后丢弃。
答案 3 :(得分:20)
C ++ 17 (即将推出的标准)更改了模板basic_string
的概要,添加了data()
的非常量重载:
来自
charT* data() noexcept;
返回:指针p,使得[0,size()]中每个i的p + i ==&amp;运算符。
CharT const *
的std::basic_string<CharT>
std::string const cstr = { "..." };
char const * p = cstr.data(); // or .c_str()
来自CharT *
std::basic_string<CharT>
std::string str = { "..." };
char * p = str.data();
CharT const *
的std::basic_string<CharT>
std::string str = { "..." };
str.c_str();
来自CharT *
std::basic_string<CharT>
从C ++ 11开始,标准说:
- 醇>
basic_string
对象中类似char的对象应连续存储。也就是说,对于任何basic_string
对象s
,&*(s.begin() + n) == &*s.begin() + n
的所有值都应保留n
,0 <= n < s.size()
。
- 醇>
const_reference operator[](size_type pos) const;
reference operator[](size_type pos);
如果
*(begin() + pos)
,则返回pos < size()
,否则引用CharT
类型为CharT()
的对象;参考值不得修改。
- 醇>
const charT* c_str() const noexcept;
{
{1}}返回:指针p,
const charT* data() const noexcept;
中每p + i == &operator[](i)
个i
。
有一些可以获得非常量字符指针的方法。
[0,size()]
<强>临强>
<强>缺点强>
std::string foo{"text"};
auto p = &*foo.begin();
不得更改/不一定是非常量内存的一部分。'\0'
std::vector<CharT>
<强>临强>
<强>缺点强>
std::string foo{"text"};
std::vector<char> fcv(foo.data(), foo.data()+foo.size()+1u);
auto p = fcv.data();
是编译时常量(并且足够小)std::array<CharT, N>
N
<强>临强>
<强>缺点强>
std::string foo{"text"};
std::array<char, 5u> fca;
std::copy(foo.data(), foo.data()+foo.size()+1u, fca.begin());
<强>临强>
<强>缺点强>
std::string foo{ "text" };
auto p = std::make_unique<char[]>(foo.size()+1u);
std::copy(foo.data(), foo.data() + foo.size() + 1u, &p[0]);
<强>临强>
<强> N 强>
答案 4 :(得分:9)
我正在使用包含许多函数的API作为输入char*
。
我创建了一个小班来面对这类问题,我已经实现了RAII习语。
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_; }
};
您可以将其用作:
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
我已调用类DeepString
,因为它正在创建现有字符串的深层且唯一的副本(DeepString
不可复制)。
答案 5 :(得分:7)
看看这个:
string str1("stackoverflow");
const char * str2 = str1.c_str();
但请注意,这将返回const char *
。对于char *
,请使用strcpy
将其复制到另一个char
数组中。
答案 6 :(得分:7)
char* result = strcpy((char*)malloc(str.length()+1), str.c_str());
答案 7 :(得分:0)
让我们说, string str="stack";
1)将字符串转换为字符*
char* s_rw=&str[0];
上面的char*(即s_rw)是可读可写的,并且指向基数 需要转为char*的字符串地址
2)字符串转const char*
const char* s_r=&str[0];
上面的const char*(即s_r)可读但不可写,并且指向 字符串的基地址。
答案 8 :(得分:-4)
试试这个
std::string s(reinterpret_cast<const char *>(Data), Size);