konwertuj char * na std :: string


262

Potrzebuję użyć std::stringdo przechowywania danych pobranych przez fgets(). Aby to zrobić, muszę przekonwertować char*wartość zwracaną z fgets()na std::stringdo przechowywania w tablicy. Jak można to zrobić?

Odpowiedzi:


376

std::string ma do tego konstruktor:

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

Zauważ, że ta konstrukcja głęboko kopiuje listę znaków na si snie powinna być nullptr, w przeciwnym razie zachowanie jest niezdefiniowane.


6
co się stanie, jeśli tak jest?
Carson Myers

14
Standard mówi, że parametr konstruktora „nie powinien być zerowym wskaźnikiem” - nie określa, że ​​zgłaszane są wyjątki.

24
Czy jest to płytka czy głęboka kopia?

4
@pushkin No strto tylko nazwa zmiennej. To może być cokolwiek: S, abc, l, I, strHelloWorld. Oczywiście niektóre wybory są lepsze niż inne. Ale w tym przykładzie strjest całkiem do przyjęcia.
Rozczarowany

10
@Materiał jest to głęboka kopia. Przydział wskaźnika pozostanie, a ciąg stanie się nowym przydziałem.
moodboom

127

Jeśli znasz już rozmiar znaku *, użyj go zamiast tego

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

To nie używa strlen.

EDYCJA: Jeśli zmienna łańcuchowa już istnieje, użyj assign ():

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

1
To trochę poboczne pytanie, Eugene. Jeśli dane nie zostaną wypełnione do późniejszej rutyny, w jaki sposób zainicjujesz myString? Czy po prostu deklarujesz zmienną myString, gdy jest zapełniona?
IcedDante

2
int size = strlen (dane);
Vlad

@vlad: chodzi o to, że wiesz, że rozmiar z innego źródła i / lub danych nie jest ciągiem C (ma osadzone wartości null lub nie kończy się na null). Jeśli masz ciąg C, możesz po prostu zrobić myString = data; będzie działać dla ciebie strlen lub równoważny.
Eugene

1
@huseyintugrulbuyukisik Nadal musisz poprawnie pozbyć się oryginalnej pamięci - std :: string skopiuje bajty, nie przejmuje własności.
Eugene

2
@ZackLee przydzieli nową pamięć na bajty i skopiuje je wszystkie tak głęboko, jak to możliwe. Jeśli chcesz mieć potencjał do płytkiego kopiowania, musisz skopiować jeden std :: string do drugiego. Myślę, że niektóre implementacje mogłyby zrobić płytką kopię.
Eugene

30

Większość odpowiedzi mówi o konstruowaniu std::string .

Jeśli już został zbudowany, wystarczy użyć operatora przypisania .

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

Potrzebuję użyć std :: string do przechowywania danych pobranych przez fgets ().

fgets()Po co używać podczas programowania C ++? Dlaczego nie std::getline()?


18

Przekaż to przez konstruktor:

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

Możesz użyć funkcji string.c_str (), aby przejść w drugą stronę:

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

3
c_str()powracaconst char*
Steve Jessop

1
tak, nie możesz (nie powinieneś) modyfikować danych w std :: string za pomocą c_str (). Jeśli zamierzasz zmienić dane, to ciąg c z c_str () powinien być 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

Chciałbym wspomnieć o nowej metodzie, która używa literału zdefiniowanego przez użytkownika s. To nie jest nowe, ale będzie bardziej powszechne, ponieważ zostało dodane do biblioteki standardowej C ++ 14.

W dużej mierze zbędne w ogólnym przypadku:

string mystring = "your string here"s;

Ale pozwala korzystać z auto, również z szerokimi ciągami znaków:

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

I tutaj naprawdę świeci:

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

2

Właśnie walczyłem z MSVC2005, aby używać std::string(char*)konstruktora tak, jak najwyżej oceniana odpowiedź. Jak widzę ten wariant jest wymieniony jako nr 4 na zawsze zaufanym http://en.cppreference.com/w/cpp/string/basic_string/basic_string , wydaje mi się, że nawet stary kompilator to oferuje.

Tak długo zajęło mi zrozumienie, że ten konstruktor absolutnie nie zgadza się z (unsigned char*)argumentem! Otrzymałem te niezrozumiałe komunikaty o błędach dotyczące niezgodności z std::stringtypem argumentu, co zdecydowanie nie było moim celem. Właśnie rzucając kłótnię std::string((char*)ucharPtr)rozwiązałem mój problem ... duh!


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

9
Spowoduje to niezdefiniowane zachowanie.

1
Tylko z tymi dwiema liniami datapozostaje niezainicjowany (pusty).
heltonbiker

1
Bez podania prawdziwej „długości” wskaźnika, ten kod może powodować utratę danych, twój std :: string będzie „więcej krótszy” niż oryginalny znak *
Andiana

0

Nie jestem pewien, dlaczego nikt oprócz Erika o tym nie wspomniał, ale zgodnie z tą stroną operator przypisania działa dobrze. Nie trzeba używać konstruktora, .assign () ani .append ().

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

1
Wydaje się, że działa funkcjonalnie, ale kiedy to zrobiłem, zacząłem mieć problemy z raportami Valgrind dostępnymi blokami na końcu programu, pochodzącymi z „nowego” wnętrza =(i +=). Wydaje się, że tak się nie dzieje z takimi literałami, ale tylko z char*rzeczami. Kwestia, czy takie raporty są rzeczywiście przeciekami, jest omawiana tutaj . Ale jeśli zmieniłem przypisanie do destString = std::string(srcCharPtr);Valgrind, wyciek zniknął. YMMV.
HostileFork mówi: nie ufaj

Komentarz HostileFork może prowadzić do przekonania, że ​​skonstruowanie ciągu znaków z char * (jak z fgets) sprawi, że std :: string zarządza czasem życia tej pamięci. Jednak tak nie jest. Zobacz standard 21.4.2.7 i .9 Constructs an object of class basic_string and determines its initial string value from the array. Mówi wartość i nic o buforach lub własności wskaźnika.
Erik van Velzen
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.