【发布时间】:2011-11-13 04:55:13
【问题描述】:
我想将 std::string 转换为 char* 或 char[] 数据类型。
std::string str = "string";
char* chr = str;
导致:“错误:无法将‘std::string’转换为‘char’...”.
有哪些方法可以做到这一点?
【问题讨论】:
我想将 std::string 转换为 char* 或 char[] 数据类型。
std::string str = "string";
char* chr = str;
导致:“错误:无法将‘std::string’转换为‘char’...”.
有哪些方法可以做到这一点?
【问题讨论】:
它不会自动转换(谢天谢地)。您必须使用方法c_str() 来获取C 字符串版本。
std::string str = "string";
const char *cstr = str.c_str();
注意它返回一个const char *;您不能更改 c_str() 返回的 C 风格字符串。如果你想处理它,你必须先复制它:
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);
【讨论】:
c_str 疯狂。
vector 正是作为动态数组的包装器而发明的,因此不使用它充其量似乎是错失良机,最坏的情况是违反了 C++ 的精神。
std::string 会自动转换),然后我用一个简短的代码示例解释他应该使用什么。向前思考我还解释了使用此函数的一些副作用,其中一个是您可能无法编辑c_str()返回的字符串。您错误地将我的简短示例视为真正解决问题的代码,但事实并非如此。
std::vector<char>)。
假设您只需要一个 C 风格的字符串作为输入传递:
std::string str = "string";
const char* chr = str.c_str();
【讨论】:
如果你只想要一个代表相同内容的 C 风格字符串:
char const* ca = str.c_str();
如果你想要一个带有 new 内容的 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
【讨论】:
&str.front(), &str.back()(C++03 中不存在)而不是更常见的str.begin() 和str.end()?
str.begin(),甚至std::begin(str),类似迭代器呢?我不相信string 有任何义务像vector 那样在连续的记忆中,或者有吗?
&back() + 1,而不是&back()
(此答案仅适用于 C++98。)
请不要使用原始的char*。
std::string str = "string";
std::vector<char> chars(str.c_str(), str.c_str() + str.size() + 1u);
// use &chars[0] as a char*
【讨论】:
vector<char>(str.c_str(), str.c_str() + str.size() + 1),而不将 char 指针分配给临时对象吗?
std::basic_string<>::c_str() 的返回值一直有效,直到 string 被更改或销毁。这也意味着只要 string 未被修改,它就会在后续调用中返回相同的值。
vector 没有速度或空间开销。如果要在没有 RAII 机制(即使用原始指针)的情况下编写异常安全代码,则代码复杂度将远高于这种简单的单行代码。
vector 具有大量开销和复杂性是一个神话。如果您的要求是您有一个 mutable 字符数组,那么实际上字符向量几乎是理想的 C++ 包装器。如果您的要求实际上只需要一个 const-char 指针,那么只需使用 c_str() 就可以了。
严格来说,您不能“将 std::string 转换为 char* 或 char[] 数据类型”。
正如其他答案所示,您可以将 std::string 的内容复制到 char 数组,或将 const char* 制作为 std::string 的内容,以便您可以在 " C 风格”。
如果您尝试更改 std::string 的内容,std::string 类型具有执行您可能需要对其执行的任何操作的所有方法。
如果你试图将它传递给某个接受 char* 的函数,则有 std::string::c_str()。
【讨论】:
如果我需要一个 c++ 字符串内容的可变原始副本,那么我会这样做:
std::string str = "string";
char* chr = strdup(str.c_str());
及以后:
free(chr);
那么我为什么不像其他人一样摆弄 std::vector 或 new[] 呢?因为 当我需要一个可变的 C 风格的原始 char* 字符串时,然后因为我想调用 C 代码来更改字符串,而 C 代码使用 free() 释放东西并使用 malloc() 分配(strdup 使用 malloc)。因此,如果我将原始字符串传递给某个函数 X 用 C 编写,它 可能 对其参数有一个约束,它必须在堆上分配(例如,如果函数可能想在参数上调用 realloc)。但它极不可能期望分配有(某些用户重新定义的)new[] 的参数!
【讨论】:
strdup来自哪里。
More details here 和 here 但你可以使用
string str = "some string" ;
char *cstr = &str[0];
从 C++11 开始,您还可以使用 str.data() 成员函数,它返回 char *
string str = "some string" ;
char *cstr = str.data();
【讨论】:
c_str() 一直停在我的空字节处,即使我的读数似乎表明它不应该。也许我在其他地方做错了什么,但是用这个(甚至 &str.first())交换 c_str() 效果很好
为了完整起见,不要忘记std::string::copy()。
std::string str = "string";
const size_t MAX = 80;
char chrs[MAX];
str.copy(chrs, MAX);
std::string::copy() 不会 NUL 终止。如果您需要确保在 C 字符串函数中使用 NUL 终止符:
std::string str = "string";
const size_t MAX = 80;
char chrs[MAX];
memset(chrs, '\0', MAX);
str.copy(chrs, MAX-1);
【讨论】:
这也可以
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;
【讨论】:
char* result = strcpy((char*)malloc(str.length()+1), str.c_str());
【讨论】:
或者,您可以使用向量来获得可写的 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
【讨论】:
这是来自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
【讨论】:
if (str[str.length()-1] != 0) str.push_back(0)
你可以使用迭代器来实现它。
std::string str = "string";
std::string::iterator p=str.begin();
char* chr = &(*p);
祝你好运。
【讨论】:
使用 unique_ptr 的 orlp 的 char* 答案的安全版本:
std::string str = "string";
auto cstr = std::make_unique<char[]>(str.length() + 1);
strcpy(cstr.get(), str.c_str());
【讨论】:
作为对 bobobobo 答案的评论会更好,但我没有代表。它完成了同样的事情,但有更好的做法。
虽然其他答案很有用,但如果您需要在没有 const 的情况下将 std::string 显式转换为 char*,const_cast 是您的朋友。
std::string str = "string";
char* chr = const_cast<char*>(str.c_str());
请注意,这不会为您提供数据的副本;它会给你一个指向字符串的指针。因此,如果您修改chr 的元素,您将修改str。
【讨论】:
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")
【讨论】:
要从std::string 获取const char *,请使用c_str() 成员函数:
std::string str = "string";
const char* chr = str.c_str();
要从std::string 中获取非常量char *,您可以使用data() 成员函数,它从C++17 开始返回非常量指针:
std::string str = "string";
char* chr = str.data();
对于旧版本的语言,您可以使用范围构造将字符串复制到可以从中获取非常量指针的向量中:
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() 之前不能保证为空终止。
【讨论】:
没有人提到过 sprintf?
std::string s;
char * c;
sprintf(c, "%s", s.c_str());
【讨论】: