แปลงถ่าน * เป็นมาตรฐาน :: สตริง


262

ฉันจำเป็นต้องใช้ในการจัดเก็บข้อมูลที่ดึงมาจากstd::string fgets()ในการทำเช่นนี้ฉันต้องแปลงchar*ค่าส่งคืนจากfgets()เป็นstd::stringเก็บในอาร์เรย์ สิ่งนี้สามารถทำได้?

คำตอบ:


376

std::string มีตัวสร้างสำหรับสิ่งนี้:

const char *s = "Hello, World!";
std::string str(s);

โปรดทราบว่าสิ่งปลูกสร้างนี้จะคัดลอกรายชื่ออักขระที่sและsไม่ควรเป็นnullptrอย่างอื่นมิฉะนั้นพฤติกรรมจะไม่ได้กำหนด


6
จะเกิดอะไรขึ้นถ้ามันคืออะไร?
Carson Myers

14
มาตรฐานบอกว่าพารามิเตอร์คอนสตรัค "จะต้องไม่เป็นตัวชี้โมฆะ" - ไม่ได้ระบุว่ามีข้อยกเว้นใด ๆ

24
มันเป็นสำเนาตื้นหรือลึก?

4
@pushkin No strเป็นเพียงชื่อตัวแปร มันอาจจะเป็นอะไรที่: S, abc, l, ,I strHelloWorldเห็นได้ชัดว่าตัวเลือกบางอย่างดีกว่าตัวเลือกอื่น แต่สำหรับตัวอย่างstrนี้ค่อนข้างยอมรับได้
ไม่แยแส

10
@ แมทช์มันเป็นสำเนาลึก การจัดสรรตัวชี้จะยังคงอยู่และสตริงจะทำการจัดสรรใหม่เอง
moodboom

127

หากคุณรู้ขนาด char * แล้วให้ใช้สิ่งนี้แทน

char* data = ...;
int size = ...;
std::string myString(data, size);

สิ่งนี้ไม่ได้ใช้ strlen

แก้ไข: หากตัวแปรสตริงมีอยู่แล้วให้ใช้ assign ():

std::string myString;
char* data = ...;
int size = ...;
myString.assign(data, size);

1
คำถามด้านยูจีน หากข้อมูลไม่ได้บรรจุจนกระทั่งต่อมาในกิจวัตรประจำวันอย่างไรคุณเริ่มต้น myString แล้ว? คุณเพียงประกาศตัวแปร myString เมื่อมีการเติมข้อมูลหรือไม่
IcedDante

2
int size = strlen (ข้อมูล);
Vlad

@ vlad: แนวคิดคือคุณรู้ว่าขนาดจากแหล่งอื่น ๆ และ / หรือข้อมูลไม่ใช่ C-string (มีค่า Null ฝังอยู่หรือไม่สิ้นสุดในค่า Null) หากคุณมี C-string คุณสามารถทำ myString = data ได้ มันจะทำงาน strlen หรือเทียบเท่าสำหรับคุณ
ยูจีน

1
@huseyintugrulbuyukisik คุณยังคงต้องทิ้งหน่วยความจำดั้งเดิมอย่างถูกต้อง - std :: string จะคัดลอกไบต์มันไม่ได้เป็นเจ้าของ
Eugene

2
@ZackLee มันจะจัดสรรหน่วยความจำใหม่สำหรับไบต์และคัดลอกพวกมันทั้งหมดในนั้นดังนั้นลึกเท่าที่จะได้รับ หากคุณต้องการความเป็นไปได้ในการคัดลอกตื้นคุณจำเป็นต้องคัดลอกสตริง std :: หนึ่งไปยังอีกสตริงหนึ่ง จากนั้นการใช้งานบางอย่างสามารถทำสำเนาตื้น ๆ ฉันคิดว่า
ยูจีน

30

ส่วนใหญ่พูดถึงคำตอบเกี่ยวกับการก่อสร้าง std::string

ถ้าสร้างแล้วเพียงแค่ใช้ประกอบการที่ได้รับมอบหมาย

std::string oString;
char* pStr;

... // Here allocate and get character string (e.g. using fgets as you mentioned)

oString = pStr; // This is it! It copies contents from pStr to oString

28

ฉันต้องการใช้ std :: string เพื่อเก็บข้อมูลที่ถูกเรียกใช้โดย fgets ()

ทำไมต้องใช้fgets()เมื่อคุณเขียนโปรแกรม C ++ ทำไมstd::getline()ล่ะ


18

ส่งผ่านเข้าไปใน Constructor:

const char* dat = "my string!";
std::string my_string( dat );

คุณสามารถใช้ฟังก์ชั่น string.c_str () เพื่อไปทางอื่น:

std::string my_string("testing!");
const char* dat = my_string.c_str();

3
c_str()ผลตอบแทนconst char*
Steve Jessop

1
ขวาคุณไม่สามารถ (ไม่ควร) แก้ไขข้อมูลใน std :: string ผ่าน c_str () หากคุณตั้งใจจะเปลี่ยนแปลงข้อมูลดังนั้นสตริง c จาก c_str () ควรเป็น memcpy'd
Carson Myers

11
const char* charPointer = "Hello, World!\n";
std::string strFromChar;
strFromChar.append(charPointer);
std::cout<<strFromChar<<std::endl;


5

ฉันต้องการจะพูดถึงวิธีการใหม่ที่ใช้ตัวอักษรที่กำหนดโดยผู้ใช้ sผมอยากจะพูดถึงวิธีการใหม่ซึ่งใช้ตัวอักษรที่ผู้ใช้กำหนดนี่ไม่ใช่เรื่องใหม่ แต่มันจะเป็นเรื่องธรรมดามากกว่าเพราะมันถูกเพิ่มเข้าไปใน C ++ 14 Standard Library

ฟุ่มเฟือยส่วนใหญ่ในกรณีทั่วไป:

string mystring = "your string here"s;

แต่มันช่วยให้คุณใช้ auto ได้เช่นกัน

auto mystring = U"your UTF-32 string here"s;

และนี่คือที่ที่มันส่องแสง:

string suffix;
cin >> suffix;
string mystring = "mystring"s + suffix;

2

ฉันเพิ่งดิ้นรนกับ MSVC2005 เพื่อใช้ตัวstd::string(char*)สร้างเช่นเดียวกับคำตอบที่ติดอันดับยอดนิยม เมื่อฉันเห็นตัวแปรนี้อยู่ในรายการ # 4 บนhttp://en.cppreference.com/w/cpp/string/basic_string/basic_stringฉันเชื่อถือได้เสมอฉันคิดว่าคอมไพเลอร์เก่ามีสิ่งนี้

ฉันใช้เวลานานมากที่จะตระหนักว่าตัวสร้างนี้ปฏิเสธที่จะจับคู่กับ(unsigned char*)การโต้แย้ง! ฉันได้รับข้อความแสดงข้อผิดพลาดที่เข้าใจไม่ได้เกี่ยวกับความล้มเหลวในการจับคู่กับstd::stringประเภทอาร์กิวเมนต์ซึ่งไม่ใช่สิ่งที่ฉันต้องการ เพียงแค่ทำการโต้แย้งด้วยการstd::string((char*)ucharPtr)แก้ไขปัญหาของฉัน ... duh!


0
char* data;
std::string myString(data);

9
สิ่งนี้จะส่งผลให้พฤติกรรมที่ไม่ได้กำหนด

1
มีเพียงสองบรรทัดเท่านั้นที่dataยังคงค่าเริ่มต้น (ว่าง)
heltonbiker

1
หากไม่มีตัวชี้ "ความยาว" ที่แท้จริงรหัสนี้อาจทำให้ข้อมูลสูญหาย std :: string ของคุณจะ "สั้นลง" กว่า char ดั้งเดิม *
Andiana

0

ไม่แน่ใจว่าทำไมไม่มีใครนอกจากเอริคพูดถึงเรื่องนี้ แต่ตามหน้านี้ผู้ประกอบการที่ได้รับมอบหมายทำงานได้ดี ไม่จำเป็นต้องใช้ Constructor, .assign () หรือ. append ()

std::string mystring;
mystring = "This is a test!";   // Assign C string to std:string directly
std::cout << mystring << '\n';

1
ดูเหมือนว่าจะใช้งานได้จริง แต่เมื่อฉันทำสิ่งนี้ฉันเริ่มได้รับปัญหาเกี่ยวกับการรายงานบล็อกที่เข้าถึงได้ของ Valgrind ในตอนท้ายของโปรแกรมโดยเริ่มจาก "ใหม่" ภายในจาก=(และ+=) ดูเหมือนจะไม่เกิดขึ้นกับตัวอักษรแบบนี้ แต่มี แต่char*สิ่งต่าง ๆ ปัญหาที่ว่ารายงานดังกล่าวนั้นรั่วไหลจริง ๆจะกล่าวถึงที่นี่หรือไม่ แต่ถ้าฉันเปลี่ยนการมอบหมายให้destString = std::string(srcCharPtr);กับรายงานการรั่วไหลของ valgrind ก็หายไป YMMV
HostileFork บอกว่าอย่าไว้ใจ SE

ความคิดเห็นของ HostileFork อาจทำให้คุณเชื่อว่าการสร้างสตริงจาก char * (เช่นจาก fgets) จะทำให้ std :: string จัดการอายุการใช้งานของหน่วยความจำนี้ อย่างไรก็ตามนี่ไม่ใช่กรณี ดูมาตรฐาน 21.4.2.7 และ Constructs an object of class basic_string and determines its initial string value from the array0.9 มันบอกว่ามีคุณค่าและไม่มีอะไรเกี่ยวกับบัฟเฟอร์หรือความเป็นเจ้าของตัวชี้
Erik van Velzen
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.