Câu trả lời:
Nó sẽ không tự động chuyển đổi (cảm ơn chúa). Bạn sẽ phải sử dụng phương thức c_str()
để có được phiên bản chuỗi C.
std::string str = "string";
const char *cstr = str.c_str();
Lưu ý rằng nó trả về a const char *
; bạn không được phép thay đổi chuỗi kiểu C được trả về c_str()
. Nếu bạn muốn xử lý nó, bạn sẽ phải sao chép nó trước:
std::string str = "string";
char *cstr = new char[str.length() + 1];
strcpy(cstr, str.c_str());
// do stuff
delete [] cstr;
Hoặc trong C ++ hiện đại:
std::vector<char> cstr(str.c_str(), str.c_str() + str.size() + 1);
vector
đã được phát minh chính xác như một trình bao bọc cho các mảng động, do đó, không sử dụng nó có vẻ như là một cơ hội bị bỏ lỡ tốt nhất và vi phạm tinh thần của C ++ ở mức tồi tệ nhất.
std::string
sẽ tự động chuyển đổi) và sau đó tôi giải thích anh ta nên sử dụng cái gì, với một mẫu mã ngắn. Suy nghĩ về phía trước tôi cũng giải thích một số tác dụng phụ của việc sử dụng chức năng này, trong đó một tác dụng là bạn không thể chỉnh sửa chuỗi được trả về c_str()
. Bạn nhầm tưởng các ví dụ ngắn của tôi là mã giải quyết vấn đề thực sự, nhưng thực tế không phải vậy.
std::vector<char>
).
Thêm chi tiết ở đây , và ở đây nhưng bạn có thể sử dụng
string str = "some string" ;
char *cstr = &str[0];
Nếu tôi cần một bản sao thô có thể thay đổi của nội dung chuỗi của c ++, thì tôi sẽ làm điều này:
std::string str = "string";
char* chr = strdup(str.c_str());
và sau đó:
free(chr);
Vậy tại sao tôi không nghịch ngợm với std :: vector hoặc [] mới như bất kỳ ai khác? Bởi vì khi tôi cần một chuỗi char * kiểu thô có thể thay đổi, thì vì tôi muốn gọi mã C làm thay đổi chuỗi và mã C xử lý công cụ với free () và cấp phát với malloc () (strdup sử dụng malloc) . Vì vậy, nếu tôi chuyển chuỗi thô của mình cho một số hàm X được viết bằng C, nó có thể có một ràng buộc đối với đối số của nó là nó phải được phân bổ trên heap (ví dụ nếu hàm có thể muốn gọi realloc trên tham số). Nhưng rất khó có khả năng nó sẽ mong đợi một đối số được phân bổ với (một số người dùng được xác định lại) mới []!
strdup
đến.
(Câu trả lời này chỉ áp dụng cho C ++ 98.)
Xin vui lòng, không sử dụng một nguyên 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)
, mà không gán con trỏ char tạm thời?
std::basic_string<>::c_str()
là hợp lệ cho đến khi string
thay đổi hoặc bị hủy. Điều này cũng ngụ ý rằng nó trả về cùng một giá trị cho các cuộc gọi tiếp theo miễn string
là không được sửa đổi.
vector
theo cách này. Và nếu người ta viết mã an toàn ngoại lệ mà không có cơ chế RAII (nghĩa là sử dụng các con trỏ thô), thì độ phức tạp của mã sẽ cao hơn nhiều so với lớp lót đơn giản này.
vector
có số lượng lớn chi phí và sự phức tạp. Nếu yêu cầu của bạn là bạn có một mảng char có thể thay đổi , thì trên thực tế, một vectơ ký tự là khá nhiều trình bao bọc C ++ lý tưởng. Nếu yêu cầu của bạn thực sự chỉ cần gọi một con trỏ const-char, thì chỉ cần sử dụng c_str()
và bạn đã hoàn thành.
Nếu bạn chỉ muốn một chuỗi kiểu C đại diện cho cùng một nội dung:
char const* ca = str.c_str();
Nếu bạn muốn một chuỗi kiểu C có nội dung mới , một cách (cho rằng bạn không biết kích thước chuỗi tại thời gian biên dịch) là phân bổ động:
char* ca = new char[str.size()+1];
std::copy(str.begin(), str.end(), ca);
ca[str.size()] = '\0';
Đừng quên delete[]
nó sau.
Thay vào đó, nếu bạn muốn một mảng được phân bổ tĩnh, có độ dài giới hạn:
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
không hoàn toàn chuyển đổi sang các loại này vì lý do đơn giản là cần phải làm điều này thường là mùi thiết kế. Hãy chắc chắn rằng bạn thực sự cần nó.
Nếu bạn chắc chắn cần một char*
, cách tốt nhất có lẽ là:
vector<char> v(str.begin(), str.end());
char* ca = &v[0]; // pointer to start of vector
&str.front(), &str.back()
(không có trong C ++ 03) thay vì phổ biến hơn str.begin()
và str.end()
?
str.begin()
, hoặc thậm chí std::begin(str)
, giống như lặp? Tôi không tin string
có bất kỳ nghĩa vụ phải ở trong bộ nhớ tiếp giáp như thế vector
, hoặc có nó?
&back() + 1
chứ không phải&back()
Điều này sẽ tốt hơn khi nhận xét về câu trả lời của bobobobo, nhưng tôi không có đại diện cho điều đó. Nó hoàn thành điều tương tự nhưng với thực tiễn tốt hơn.
Mặc dù các câu trả lời khác là hữu ích, nhưng nếu bạn cần chuyển đổi std::string
thành char*
rõ ràng mà không cần const, const_cast
là bạn của bạn.
std::string str = "string";
char* chr = const_cast<char*>(str.c_str());
Lưu ý rằng điều này sẽ không cung cấp cho bạn một bản sao của dữ liệu; nó sẽ cung cấp cho bạn một con trỏ tới chuỗi. Do đó, nếu bạn sửa đổi một yếu tố chr
, bạn sẽ sửa đổi str
.
Giả sử bạn chỉ cần một chuỗi kiểu C để vượt qua làm đầu vào:
std::string str = "string";
const char* chr = str.c_str();
Để được mô tả nghiêm ngặt, bạn không thể "chuyển đổi chuỗi std :: thành kiểu dữ liệu char * hoặc char []."
Như các câu trả lời khác đã hiển thị, bạn có thể sao chép nội dung của chuỗi std :: sang một mảng char hoặc tạo một const char * vào nội dung của chuỗi std :: để bạn có thể truy cập nó theo kiểu "C" .
Nếu bạn đang cố gắng thay đổi nội dung của chuỗi std ::, kiểu chuỗi std :: có tất cả các phương thức để làm bất cứ điều gì bạn có thể cần làm với nó.
Nếu bạn đang cố gắng chuyển nó đến một số hàm có char *, thì có std :: string :: c_str ().
Vì sự trọn vẹn, đừng quên std::string::copy()
.
std::string str = "string";
const size_t MAX = 80;
char chrs[MAX];
str.copy(chrs, MAX);
std::string::copy()
NUL không chấm dứt. Nếu bạn cần đảm bảo bộ kết thúc NUL để sử dụng trong các hàm chuỗi C:
std::string str = "string";
const size_t MAX = 80;
char chrs[MAX];
memset(chrs, '\0', MAX);
str.copy(chrs, MAX-1);
Đây là một phiên bản mạnh mẽ hơn từ 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)
Chuyển đổi theo kiểu OOP
chuyển đổi.hpp
class StringConverter {
public: static char * strToChar(std::string str);
};
chuyển đổi.cpp
char * StringConverter::strToChar(std::string str)
{
return (char*)str.c_str();
}
sử dụng
StringConverter::strToChar("converted string")
char* result = strcpy((char*)malloc(str.length()+1), str.c_str());
Ngoài ra, bạn có thể sử dụng các vectơ để có được một char * có thể ghi * như được trình bày dưới đây;
//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
Phiên bản an toàn của câu trả lời char * của orlp bằng unique_ptr:
std::string str = "string";
auto cstr = std::make_unique<char[]>(str.length() + 1);
strcpy(cstr.get(), str.c_str());
Để có được một const char *
từ std::string
sử dụng c_str()
chức năng thành viên:
std::string str = "string";
const char* chr = str.c_str();
Để có được một non-const char *
từ một std::string
bạn có thể sử dụng data()
hàm thành viên trả về một con trỏ không const từ C ++ 17:
std::string str = "string";
char* chr = str.data();
Đối với các phiên bản cũ hơn của ngôn ngữ, bạn có thể sử dụng cấu trúc phạm vi để sao chép chuỗi vào một vectơ mà từ đó có thể lấy được một con trỏ không phải là con trỏ:
std::string str = "string";
std::vector<char> str_copy(str.c_str(), str.c_str() + str.size() + 1);
char* chr = str_copy.data();
Nhưng hãy cẩn thận rằng điều này sẽ không cho phép bạn sửa đổi chuỗi chứa trong đó str
, chỉ có thể thay đổi dữ liệu của bản sao theo cách này. Lưu ý rằng nó đặc biệt quan trọng trong các phiên bản cũ hơn của ngôn ngữ được sử dụng c_str()
ở đây vì trước đó std::string
không được đảm bảo sẽ bị hủy cho đến khi c_str()
được gọi.
Điều này cũng sẽ làm việc
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;
c_str
hoàn toàn sự điên rồ này .