如何将std :: string转换为const char *或char *?

时间:2008-12-07 19:30:57

标签: c++ string char const

如何将std::string转换为char*const char*

9 个答案:

答案 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。有两种方法可以解决这个问题。

升压:: scoped_array

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 ::矢量

这是标准方式(不需要任何外部库)。您使用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

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();

C ++ 11

来自CharT const *

std::basic_string<CharT>
std::string str = { "..." };
str.c_str();
来自CharT *

std::basic_string<CharT>

从C ++ 11开始,标准说:

  
      
  1. basic_string对象中类似char的对象应连续存储。也就是说,对于任何basic_string对象s&*(s.begin() + n) == &*s.begin() + n的所有值都应保留n0 <= n < s.size()
  2.               
        
    1. const_reference operator[](size_type pos) const;
      reference operator[](size_type pos);

           

      如果*(begin() + pos),则返回pos < size(),否则引用CharT类型为CharT()的对象;参考值不得修改。

    2.               
          
      1. const charT* c_str() const noexcept; {
        {1}}

             

        返回:指针p,const charT* data() const noexcept;中每p + i == &operator[](i)i

      2.   

有一些可以获得非常量字符指针的方法。

1。使用C ++ 11

的连续存储
[0,size()]

<强>临

  • 简单
  • 快速(仅涉及无复制的方法)

<强>缺点

  • 最终std::string foo{"text"}; auto p = &*foo.begin(); 不得更改/不一定是非常量内存的一部分。

2。使用'\0'

std::vector<CharT>

<强>临

  • 简单
  • 自动内存处理
  • 动态

<强>缺点

  • 需要字符串副本

3。如果std::string foo{"text"}; std::vector<char> fcv(foo.data(), foo.data()+foo.size()+1u); auto p = fcv.data(); 是编译时常量(并且足够小)

,请使用std::array<CharT, N>
N

<强>临

  • 简单
  • 堆栈内存处理

<强>缺点

  • 静态
  • 需要字符串副本

4。具有自动存储删除的原始内存分配

std::string foo{"text"};
std::array<char, 5u> fca;
std::copy(foo.data(), foo.data()+foo.size()+1u, fca.begin());

<强>临

  • 占用内存不足
  • 自动删除
  • 简单

<强>缺点

  • 需要字符串副本
  • 静态(动态使用需要更多代码)
  • 比矢量或数组少的功能

5。手动处理的原始内存分配

std::string foo{ "text" };
auto p = std::make_unique<char[]>(foo.size()+1u);
std::copy(foo.data(), foo.data() + foo.size() + 1u, &p[0]);

<强>临

  • 最高&#39;控制&#39;

<强> 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);