std :: string转换为char *


335

我想将std :: string转换为char *char []数据类型。

std::string str = "string";
char* chr = str;

结果为:“错误:无法将'std :: string'转换为'char'...”

有什么方法可以做到这一点?

c++  string  char 

Answers:


671

它不会自动转换(感谢上帝)。您必须使用该方法c_str()来获取C字符串版本。

std::string str = "string";
const char *cstr = str.c_str();

注意它返回一个const char *; 您不允许更改所返回的C样式字符串c_str()。如果要处理它,则必须先复制它:

std::string str = "string";
char *cstr = new char[str.length() + 1];
strcpy(cstr, str.c_str());
// do stuff
delete [] cstr;

或在现代C ++中:

std::vector<char> cstr(str.c_str(), str.c_str() + str.size() + 1);

4
@Kerrek SB:这是一个示例,将在实际代码中使用智能指针,或更可能c_str完全避免这种疯狂。
orlp 2011年

14
答案是笨重,优雅,非本地的,使用原始数组,并且需要注意异常安全性。vector完全是作为动态数组的包装器而发明的,所以最好不要使用它似乎是一个错失的机会,并且最坏的情况是违反了C ++的精神。
Kerrek SB 2011年

21
首先,是的,答案是庞大的。首先,我std::string用一个简短的代码示例解释了OP的错误(认为会自动转换的错误),然后解释了他应该使用的错误。展望未来,我还将解释使用此功能的一些副作用,其中之一是您可能无法编辑所返回的字符串c_str()。您错误地将我的简短示例视为真正的解决问题的代码,事实并非如此。
orlp 2011年

8
我拒绝了答案。这个答案确实没有用,最不幸的是,这个答案被接受了。该答案完全无视C ++良好的编程习惯和异常安全性,并且还有许多出色的解决方案,其中一些是在该问题的其他答案中给出的(例如ildjarn给出的答案std::vector<char>)。
James McNellis 2011年

114
@詹姆斯- mcnellis,我拿起这个答案正确的,因为它回答确切地是什么我问了...没有多,不会少。我没有要求您认为我应该做什么,我没有要求针对您认为我正在做什么的解决方案,也没有要求良好的做法。您不知道我在做什么,我的代码将在哪里实现以及在什么条件下实现。有些人应该学会阅读,理解问题并回答实际提出的问题。无需在这里炫耀。

150

在此处此处有更多详细信息,但您可以使用

string str = "some string" ;
char *cstr = &str[0];

15
FWIW,在我的书中,这是对实际提出的问题的唯一正确答案。std :: string本质上是可变的:听起来好像修改字符串内容的人在某种程度上似乎是魔鬼的作品缺少了这一事实。
Jay Freeman -saurik-

2
是的,这是正确的答案。愚蠢的是,鉴于使用的频率,没有标准的方法来执行此操作,例如msoft的锁缓冲区。
Erik Aronesty,2015年

1
我将0更改为0u。因为某些编译器/库将(信不信由你)抱怨针对&str [0]构造完全打开警告时的模棱两可
Erik Aronesty,2015年

我怀疑删除str时,会将 char cstr设为null。所以我想这里只有字符串的指针分配给char指针。因此,字符串到char的转换实际上并不完整。字符串仅指向char *,但不转换其值。我对么???
Samitha Chathuranga 2015年

5
请注意,这仅是C ++ 11。以前的版本可能没有连续存储,或者缺少结尾的null
Flamefire '17

40

如果我需要c ++字符串内容的可变原始副本,则可以这样做:

std::string str = "string";
char* chr = strdup(str.c_str());

然后:

free(chr); 

那么,为什么不像其他任何人一样摆弄std :: vector或new []?因为当我需要一个可变的C风格的原始char *字符串时,然后因为我想调用更改字符串的C代码,并且C代码使用free()释放内容并使用malloc()分配内容(strdup使用malloc)。因此,如果我将原始字符串传递给用C编写的某个函数X 可能会对它必须在堆上分配的参数有约束(例如,如果函数可能想在参数上调用realloc)。但是,几乎不可能期望分配有(某些用户定义的)new []的参数!


您应该解释strdup来自哪里。
LF

22

(此答案仅适用于C ++ 98。)

请不要使用raw char*

std::string str = "string";
std::vector<char> chars(str.c_str(), str.c_str() + str.size() + 1u);
// use &chars[0] as a char*

1
实际上,我今天早些时候只需要这样的东西。我想知道,是否可以vector<char>(str.c_str(), str.c_str() + str.size() + 1)不将char指针分配给临时对象就可以说吗?
Kerrek SB 2011年

1
@Kerrek:是的,返回值std::basic_string<>::c_str()string更改或销毁之前一直有效。这也意味着只要string不修改,它在后续调用中将返回相同的值。
ildjarn 2011年

2
@friendzis:vector以这种方式使用不会产生速度或空间开销。而且,如果编写一个没有RAII机制的异常安全代码(即使用原始指针),则代码复杂度将比这种简单的单行代码高得多。
ildjarn 2011年

7
这是vector具有大量开销和复杂性的神话。如果您的要求是拥有可变的 char数组,则实际上chars向量几乎是理想的C ++包装器。如果您的需求实际上只是要求使用const-char指针,则只需使用c_str()就可以了。
Kerrek SB 2011年

3
@ildjarn:实际上,基本上是
Lightness Races in Orbit

15
  • 如果只需要一个表示相同内容的C样式字符串:

    char const* ca = str.c_str();
  • 如果您想要带有内容的C样式字符串,则一种方法(假设您在编译时不知道字符串大小)是动态分配:

    char* ca = new char[str.size()+1];
    std::copy(str.begin(), str.end(), ca);
    ca[str.size()] = '\0';

    以后不要忘记delete[]它。

  • 如果要使用静态分配的有限长度数组,请执行以下操作:

    size_t const MAX = 80; // maximum number of chars
    char ca[MAX] = {};
    std::copy(str.begin(), (str.size() >= MAX ? str.begin() + MAX : str.end()), ca);

std::string不会隐式转换为这些类型,原因很简单,因为这样做通常是一种设计气味。确保您确实需要它。

如果您确实需要char*最好的方法可能是:

vector<char> v(str.begin(), str.end());
char* ca = &v[0]; // pointer to start of vector

1
为什么&str.front(), &str.back()(在C ++ 03中不存在)而不是更常见的str.begin()and str.end()
Armen Tsirunyan 2011年

1
怎么样str.begin(),甚至std::begin(str),类迭代器?我不相信string有像这样的连续记忆的义务vector吗?
xtofl 2011年

1
@xtofl:我已经在其中进行了编辑。是的,从C ++ 11开始,有义务;这在C ++ 03中是隐式的。
Lightness Races in Orbit

@xtofl:不在C ++ 03中。在C ++ 11中,我们具有保证,以及无论如何都在原始答案中滥用的front()和back()函数
Armen Tsirunyan 2011年

1
@Tomalak:他们被滥用是因为您需要&back() + 1,而不是&back()
Armen Tsirunyan 2011年

12

作为对bobobobo答案的评论,这会更好,但我没有代表。它可以完成相同的任务,但是具有更好的实践。

尽管其他答案很有用,但是如果您需要在不使用const的情况下std::string进行char*显式转换,const_cast则还是您的朋友。

std::string str = "string";
char* chr = const_cast<char*>(str.c_str());

请注意,这不会给您数据的副本。它会给你一个指向字符串的指针。因此,如果您修改的元素chr,则会修改str


7

假设您只需要一个C样式的字符串即可作为输入传递:

std::string str = "string";
const char* chr = str.c_str();

5

要严格学究,您不能“将std :: string转换为char *或char []数据类型”。

如其他答案所示,您可以将std :: string的内容复制到char数组,或将const char *复制到std :: string的内容,以便可以使用“ C样式”进行访问。

如果您尝试更改std :: string的内容,则std :: string类型具有所有方法来执行可能需要执行的操作。

如果您试图将其传递给某个采用char *的函数,则有std :: string :: c_str()。


4

为了完整起见,请不要忘记std::string::copy()

std::string str = "string";
const size_t MAX = 80;
char chrs[MAX];

str.copy(chrs, MAX);

std::string::copy()不终止。如果需要确保在C字符串函数中使用NUL终止符,请执行以下操作:

std::string str = "string";
const size_t MAX = 80;
char chrs[MAX];

memset(chrs, '\0', MAX);
str.copy(chrs, MAX-1);

4

这是来自 Protocol Buffer

char* string_as_array(string* str)
{
    return str->empty() ? NULL : &*str->begin();
}

// test codes
std::string mystr("you are here");
char* pstr = string_as_array(&mystr);
cout << pstr << endl; // you are here

+1用于检查字符串是否为空。我还要添加一个检查以确保该字符串以零终止: if (str[str.length()-1] != 0) str.push_back(0)
GaspardP '16

4

OOP样式的转换

converter.hpp

class StringConverter {
    public: static char * strToChar(std::string str);
};

converter.cpp

char * StringConverter::strToChar(std::string str)
{
    return (char*)str.c_str();
}

用法

StringConverter::strToChar("converted string")

我喜欢转换为char *的方式如何从c_str的输出中消除const,我认为c_str返回const char *的原因是通过提供事物的只读版本来消除潜在的内存访问问题。OP希望有一个char *,但是我认为他可以由c_str的const char *输出更好地服务,因为那样更安全,并且采用char *的函数通常也采用const char *(假设函数没有)做任何改变输入的操作,一般来说,这是不应该的)。
费利佩·瓦尔德斯


3

另外,您可以使用向量获取可写char *,如下所示;

//this handles memory manipulations and is more convenient
string str;
vector <char> writable (str.begin (), str.end) ;
writable .push_back ('\0'); 
char* cstring = &writable[0] //or &*writable.begin () 

//Goodluck  

这将为向量分配新的内存,然后复制每个字符。std :: string已经是一个容器,您不妨在字符串上push_back(0)并执行&str [0]
GaspardP

3

您可以使用迭代器来实现。

std::string str = "string";
std::string::iterator p=str.begin();
char* chr = &(*p);

祝好运。


3

使用unique_ptr的orlp char *答案的安全版本:

std::string str = "string";
auto cstr = std::make_unique<char[]>(str.length() + 1);
strcpy(cstr.get(), str.c_str());

3

为了获得const char *从一个std::string使用c_str()成员函数:

std::string str = "string";
const char* chr = str.c_str();

要从中获取非常量char *std::string您可以使用data()成员函数,该函数从C ++ 17开始返回非常量指针:

std::string str = "string";
char* chr = str.data();

对于较旧的语言版本,可以使用范围构造将字符串复制到向量中,从该向量中可以获取非const指针:

std::string str = "string";
std::vector<char> str_copy(str.c_str(), str.c_str() + str.size() + 1);
char* chr = str_copy.data();

但是请注意,这不会让您修改包含的字符串str,只能以这种方式更改副本的数据。请注意,在此语言的较旧版本中使用它特别重要,c_str()因为在那时std::string,直到c_str()被调用之前,都不能保证以null结尾。


2

这也可以

std::string s;
std::cout<<"Enter the String";
std::getline(std::cin, s);
char *a=new char[s.size()+1];
a[s.size()]=0;
memcpy(a,s.c_str(),s.size());
std::cout<<a;  
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.