ฉันต้องการแปลงstd :: stringเป็นchar *หรือchar []ชนิดข้อมูล
std::string str = "string";
char* chr = str;
ผลการค้นหาใน: “ข้อผิดพลาด: ไม่สามารถแปลง 'มาตรฐาน :: สตริง' เป็น 'ถ่าน' ...”
มีวิธีการอะไรให้ทำเช่นนี้?
ฉันต้องการแปลงstd :: stringเป็นchar *หรือchar []ชนิดข้อมูล
std::string str = "string";
char* chr = str;
ผลการค้นหาใน: “ข้อผิดพลาด: ไม่สามารถแปลง 'มาตรฐาน :: สตริง' เป็น 'ถ่าน' ...”
มีวิธีการอะไรให้ทำเช่นนี้?
คำตอบ:
มันจะไม่แปลงโดยอัตโนมัติ (ขอบคุณพระเจ้า) คุณจะต้องใช้วิธี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);
vector
ได้รับการคิดค้นอย่างแม่นยำในฐานะเสื้อคลุมสำหรับอาเรย์แบบไดนามิกดังนั้นจึงไม่ได้ใช้มันดูเหมือนเป็นโอกาสที่ไม่ได้รับอย่างดีที่สุดและเป็นการละเมิดจิตวิญญาณของซีพลัสพลัสที่แย่ที่สุด
std::string
จะแปลงโดยอัตโนมัติ) จากนั้นฉันอธิบายสิ่งที่เขาควรใช้พร้อมตัวอย่างโค้ดสั้น ๆ c_str()
คิดไปข้างหน้าฉันยังอธิบายผลข้างเคียงบางส่วนของการใช้งานของฟังก์ชั่นนี้ที่หนึ่งคือการที่คุณไม่สามารถแก้ไขสตริงส่งกลับโดย คุณเห็นตัวอย่างสั้น ๆ ของฉันผิดว่าเป็นรหัสแก้ปัญหาที่แท้จริงซึ่งไม่ใช่
std::vector<char>
)
รายละเอียดเพิ่มเติมที่นี่และที่นี่แต่คุณสามารถใช้
string str = "some string" ;
char *cstr = &str[0];
หากฉันต้องการสำเนาดิบของเนื้อหาสตริงของ c ++ ที่ผันแปรไม่ได้ฉันจะทำดังนี้:
std::string str = "string";
char* chr = strdup(str.c_str());
และหลังจากนั้น:
free(chr);
แล้วทำไมฉันถึงไม่เล่นกับ std :: vector หรือ new [] เหมือนใคร? เพราะเมื่อฉันต้องไม่แน่นอนแบบ C ถ่านดิบ * สตริงแล้วเพราะผมต้องการที่จะเรียกรหัส C ซึ่งการเปลี่ยนแปลงสตริงและรหัส C deallocates สิ่งที่มีฟรี () และจัดสรรกับ malloc () (ใช้ strdup malloc) ดังนั้นถ้าฉันส่งสตริงดิบของฉันไปยังฟังก์ชั่น X ที่เขียนใน Cมันอาจมีข้อ จำกัด ในการโต้แย้งว่ามันต้องจัดสรรบนฮีป (ตัวอย่างเช่นถ้าฟังก์ชันอาจต้องการเรียก realloc บนพารามิเตอร์) แต่ไม่น่าเป็นไปได้สูงที่จะคาดว่าจะมีการจัดสรรอาร์กิวเมนต์ด้วย (บางส่วนที่ผู้ใช้กำหนดใหม่) ใหม่ []!
strdup
มาจากไหน
(คำตอบนี้ใช้กับ 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)
หรือไม่โดยไม่ได้กำหนดตัวชี้ถ่านให้เป็นแบบชั่วคราว?
std::basic_string<>::c_str()
ถูกต้องจนกว่าstring
จะมีการเปลี่ยนแปลงหรือถูกทำลาย นี่ก็หมายความว่ามันจะส่งกลับค่าเดียวกันในการโทรครั้งต่อไปตราบใดที่string
ไม่ได้แก้ไข
vector
ในการใช้วิธีนี้ และถ้ามีใครที่จะเขียนโค้ดที่มีข้อยกเว้นที่ปลอดภัยโดยไม่มีกลไก RAII (เช่นการใช้ตัวชี้แบบดิบ) ความซับซ้อนของรหัสจะสูงกว่าการซับแบบง่าย ๆ แบบนี้มาก
vector
มีค่าใช้จ่ายและความซับซ้อนจำนวนมาก หากความต้องการของคุณคือคุณมีอาร์เรย์ char ที่ไม่แน่นอนในความเป็นจริงแล้วเวกเตอร์ของตัวอักษรนั้นเป็นตัวห่อหุ้ม C ++ ในอุดมคติ หากความต้องการของคุณเพียงแค่เรียกตัวชี้ const-char จากนั้นก็ใช้c_str()
และคุณทำเสร็จแล้ว
หากคุณต้องการสตริง C-style ที่แสดงเนื้อหาเดียวกัน:
char const* ca = str.c_str();
หากคุณต้องการสตริง C-style ที่มีเนื้อหาใหม่วิธีหนึ่ง (เนื่องจากคุณไม่ทราบขนาดสตริงในเวลาคอมไพล์) คือการจัดสรรแบบไดนามิก:
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)
, iterator เหมือน? ฉันไม่เชื่อว่าstring
มีข้อผูกพันใด ๆ ที่จะต้องอยู่ในความทรงจำที่ต่อเนื่องกันเช่นvector
นี้หรือไม่?
&back() + 1
ไม่ใช่&back()
นี่จะดีกว่าเป็นความคิดเห็นในคำตอบของ bobobobo แต่ฉันไม่มีตัวแทนสำหรับสิ่งนั้น มันประสบความสำเร็จในสิ่งเดียวกัน แต่มีแนวทางปฏิบัติที่ดีกว่า
แม้ว่าคำตอบอื่น ๆ นั้นมีประโยชน์หากคุณจำเป็นต้องแปลงstd::string
เป็นchar*
อย่างชัดเจนโดยไม่มี const แต่const_cast
เป็นเพื่อนของคุณ
std::string str = "string";
char* chr = const_cast<char*>(str.c_str());
โปรดทราบว่าสิ่งนี้จะไม่ให้สำเนาของข้อมูลแก่คุณ มันจะให้ตัวชี้ไปยังสตริง ดังนั้นหากคุณปรับเปลี่ยนองค์ประกอบของคุณจะปรับเปลี่ยนchr
str
สมมติว่าคุณต้องการสตริง C-style เพื่อส่งผ่านเป็นอินพุต:
std::string str = "string";
const char* chr = str.c_str();
หากต้องการพูดจาหยาบคายอย่างเคร่งครัดคุณไม่สามารถ "แปลง std :: string เป็น char * หรือ char [] ชนิดข้อมูล"
ดังที่คำตอบอื่น ๆ ได้แสดงขึ้นคุณสามารถคัดลอกเนื้อหาของสตริง std :: ไปยังอาร์เรย์ char หรือสร้าง const char * ไปยังเนื้อหาของสตริง std :: เพื่อให้คุณสามารถเข้าถึงได้ใน "C style" .
หากคุณกำลังพยายามเปลี่ยนเนื้อหาของสตริง std :: std :: string type มีวิธีการทั้งหมดที่จะทำทุกอย่างที่คุณอาจจำเป็นต้องทำ
หากคุณพยายามส่งผ่านไปยังฟังก์ชั่นบางตัวที่ใช้ถ่าน * มี std :: string :: c_str ()
นี่คืออีกหนึ่งเวอร์ชันที่แข็งแกร่งกว่าจาก 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)
การแปลงในรูปแบบ 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::copy()
เพื่อประโยชน์ครบถ้วนไม่ลืม
std::string str = "string";
const size_t MAX = 80;
char chrs[MAX];
str.copy(chrs, MAX);
std::string::copy()
NUL ไม่สิ้นสุด หากคุณต้องการตรวจสอบให้แน่ใจว่า NUL terminator สำหรับใช้ในฟังก์ชันสตริง C:
std::string str = "string";
const size_t MAX = 80;
char chrs[MAX];
memset(chrs, '\0', MAX);
str.copy(chrs, MAX-1);
คุณสามารถทำได้โดยใช้ตัววนซ้ำ
std::string str = "string";
std::string::iterator p=str.begin();
char* chr = &(*p);
โชคดี.
char * รุ่นที่ปลอดภัยของคำตอบ orlp โดยใช้ unique_ptr:
std::string str = "string";
auto cstr = std::make_unique<char[]>(str.length() + 1);
strcpy(cstr.get(), str.c_str());
วิธีขอรับ a const char *
จากการstd::string
ใช้c_str()
ฟังก์ชันสมาชิก:
std::string str = "string";
const char* chr = str.c_str();
เพื่อรับ non-const char *
จากstd::string
คุณสามารถใช้data()
ฟังก์ชั่นสมาชิกซึ่งส่งกลับตัวชี้ที่ไม่ใช่ const ตั้งแต่ 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()
มีการเรียกใช้
char* result = strcpy((char*)malloc(str.length()+1), str.c_str());
หรือคุณสามารถใช้เวคเตอร์เพื่อรับถ่านแบบเขียนได้ * ดังที่แสดงด้านล่าง
//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 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
ความบ้าคลั่งนี้อย่างสมบูรณ์