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ć?

Jonathan Prior
źródło

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.

Jesse Beder
źródło
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);
Eugene
źródło
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
Atul
źródło
28

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

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

Paweł
źródło
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();
James Thompson
źródło
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;

źródło
6
char* data;
stringstream myStreamString;
myStreamString << data;
string myString = myStreamString.str();
cout << myString << endl;
Presen
źródło
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;
Erik van Velzen
źródło
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!

użytkownik1564286
źródło
0
char* data;
std::string myString(data);
Daniel A. White
źródło
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';
Vern Jensen
źródło
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