chuyển đổi một char * thành std :: chuỗi


262

Tôi cần phải sử dụng một std::stringđể lưu trữ dữ liệu lấy fgets(). Để làm điều này, tôi cần chuyển đổi char*giá trị trả về từ fgets()thành một std::stringđể lưu trữ trong một mảng. Điều này có thể giải quyết như thế nào?

Câu trả lời:


376

std::string có một hàm tạo cho cái này:

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

Lưu ý rằng cấu trúc này sao chép sâu danh sách ký tự tại sskhông nên nullptr, hoặc hành vi khác không được xác định.


6
Điều gì sẽ xảy ra nếu nó là?
Carson Myers

14
Standard nói rằng tham số constructor "sẽ không phải là con trỏ null" - nó không xác định rằng bất kỳ ngoại lệ nào được đưa ra.

24
Là bản sao nông hay sâu?

4
@pushkin Không strchỉ là một tên biến. Nó có thể là bất cứ điều gì: S, abc, l, I, strHelloWorld. Rõ ràng một số lựa chọn là tốt hơn so với những người khác. Nhưng đối với ví dụ strnày là khá chấp nhận được.
vỡ mộng

10
@Madhatter nó là một bản sao sâu sắc. Phân bổ con trỏ sẽ vẫn còn và chuỗi sẽ tự tạo một phân bổ mới.
psychboom

127

Nếu bạn đã biết kích thước của char *, hãy sử dụng thay thế

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

Điều này không sử dụng strlen.

EDIT: Nếu biến chuỗi đã tồn tại, hãy sử dụng gán ():

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

1
Một loại câu hỏi phụ, Eugene. Nếu dữ liệu không được điền cho đến sau trong thói quen, làm thế nào để bạn khởi tạo myString? Bạn có đơn giản khai báo biến myString khi nó được điền không?
IcedDante

2
int size = strlen (dữ liệu);
Vlad

@vlad: ý tưởng là bạn biết kích thước từ một số nguồn khác và / hoặc dữ liệu không phải là chuỗi C (đã nhúng null hoặc không kết thúc bằng null). Nếu bạn có chuỗi C, bạn chỉ cần thực hiện myString = data; Nó sẽ chạy strlen hoặc tương đương với bạn.
Eugene

1
@huseyintugrulbuyukisik Bạn vẫn cần xử lý bộ nhớ gốc đúng cách - std :: chuỗi sẽ sao chép byte, nó không có quyền sở hữu.
Eugene

2
@ZackLee nó sẽ phân bổ bộ nhớ mới cho các byte và sao chép tất cả chúng trong đó, càng sâu càng tốt. Nếu bạn muốn tiềm năng cho bản sao nông, bạn cần sao chép một chuỗi std :: sang chuỗi khác. Sau đó, một số triển khai có thể làm một bản sao nông tôi nghĩ.
Eugene

30

Hầu hết các câu trả lời nói về xây dựng std::string .

Nếu đã được xây dựng, chỉ cần sử dụng toán tử gán .

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

Tôi cần sử dụng std :: string để lưu trữ dữ liệu được lấy bởi fgets ().

Tại sao sử dụng fgets()khi bạn đang lập trình C ++? Tại sao không std::getline()?


18

Truyền nó qua hàm tạo:

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

Bạn có thể sử dụng hàm string.c_str () để đi theo cách khác:

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

3
c_str()trở vềconst char*
Steve Jessop

1
đúng, bạn không thể (không nên) sửa đổi dữ liệu trong chuỗi std :: thông qua c_str (). Nếu bạn có ý định thay đổi dữ liệu, thì chuỗi c từ c_str () sẽ là memcpy'd
Carson Myers

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

6
char* data;
stringstream myStreamString;
myStreamString << data;
string myString = myStreamString.str();
cout << myString << endl;

5

Tôi muốn đề cập đến một phương pháp mới sử dụng nghĩa đen do người dùng định nghĩa s. Điều này không mới, nhưng nó sẽ phổ biến hơn vì nó đã được thêm vào Thư viện chuẩn C ++ 14.

Phần lớn là thừa trong trường hợp chung:

string mystring = "your string here"s;

Nhưng nó cho phép bạn sử dụng tự động, cũng với chuỗi rộng:

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

Và đây là nơi nó thực sự tỏa sáng:

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

2

Tôi vừa mới vật lộn với MSVC2005 để sử dụng hàm std::string(char*)tạo giống như câu trả lời được xếp hạng cao nhất. Như tôi thấy biến thể này được liệt kê là số 4 trên http://en.cppreference.com/w/cpp/opes/basic_opes/basic_opes , tôi thậm chí còn nghĩ rằng một trình biên dịch cũ cung cấp điều này.

Tôi đã mất rất lâu để nhận ra rằng nhà xây dựng này tuyệt đối từ chối khớp với (unsigned char*)như một đối số! Tôi đã nhận được các thông báo lỗi không thể hiểu này về việc không khớp với std::stringloại đối số, đây chắc chắn không phải là điều tôi đang hướng tới. Chỉ cần đưa ra lập luận với std::string((char*)ucharPtr)giải quyết vấn đề của tôi ... duh!


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

9
Điều này sẽ dẫn đến hành vi không xác định.

1
Chỉ với hai dòng này, datavẫn chưa được khởi tạo (trống).
heltonbiker

1
Nếu không có "độ dài" đúng của con trỏ được cung cấp, mã này có thể khiến dữ liệu bị mất, chuỗi std :: của bạn sẽ "ngắn hơn" so với char ban đầu *
Andiana

0

Không chắc chắn tại sao không có ai ngoài Erik đề cập đến điều này, nhưng theo trang này , toán tử gán chỉ hoạt động tốt. Không cần sử dụng hàm tạo, .assign () hoặc .append ().

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

1
Nó dường như hoạt động chức năng, nhưng khi tôi làm điều này, tôi bắt đầu gặp vấn đề với Valgrind báo cáo các khối có thể truy cập vào cuối chương trình, bắt nguồn từ một "mới" bên trong =(và +=). Nó dường như không xảy ra với những người như thế này, nhưng chỉ với char*mọi thứ. Vấn đề liệu các báo cáo như vậy có thực sự bị rò rỉ hay không được thảo luận ở đây . Nhưng nếu tôi thay đổi gán cho destString = std::string(srcCharPtr);các báo cáo rò rỉ valgrind đã biến mất. YMMV.
HostileFork nói không tin tưởng SE

Nhận xét của HostileFork có thể khiến bạn tin rằng việc xây dựng một chuỗi từ char * (như từ fgets) sẽ khiến std :: string quản lý vòng đời của bộ nhớ này. Tuy nhiên, đây không phải là trường hợp. Xem tiêu chuẩn 21.4.2.7 và .9 Constructs an object of class basic_string and determines its initial string value from the array. Nó nói giá trị và không có gì về bộ đệm hoặc quyền sở hữu con trỏ.
Erik van Velzen
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.