konvertiere ein char * in std :: string


262

Ich muss ein verwenden std::string, um Daten zu speichern, die von abgerufen wurden fgets(). Dazu muss ich den char*Rückgabewert von fgets()in in konvertieren std::string, um ihn in einem Array zu speichern. Wie kann das gemacht werden?

Antworten:


376

std::string hat einen Konstruktor dafür:

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

Beachten Sie, dass dieses Konstrukt die Zeichenliste tief kopiert sund snicht sein sollte nullptr, sonst ist das Verhalten undefiniert.


6
Was wird passieren, wenn es so ist?
Carson Myers

14
Standard sagt, dass der Konstruktorparameter "kein Nullzeiger sein soll" - er gibt nicht an, dass Ausnahmen ausgelöst werden.

24
Ist es eine flache oder tiefe Kopie?

4
@pushkin Nein strist nur ein Variablenname. Es könnte alles sein: S, abc, l, I, strHelloWorld. Offensichtlich sind einige Entscheidungen besser als andere. Aber für dieses Beispiel strist das durchaus akzeptabel.
Desillusioniert

10
@ Madhatter es ist eine tiefe Kopie. Die Zeigerzuordnung bleibt erhalten, und die Zeichenfolge wird selbst zu einer neuen Zuordnung.
Moodboom

127

Wenn Sie die Größe des Zeichens * bereits kennen, verwenden Sie diese stattdessen

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

Dies verwendet keine strlen.

BEARBEITEN: Wenn bereits eine Zeichenfolgenvariable vorhanden ist, verwenden Sie assign ():

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

1
Eine Art Nebenfrage, Eugene. Wie initialisieren Sie myString dann, wenn die Daten erst später in der Routine ausgefüllt werden? Deklarieren Sie einfach die Variable myString, wenn sie ausgefüllt ist?
IcedDante

2
int size = strlen (Daten);
Vlad

@vlad: Die Idee ist, dass Sie die Größe aus einer anderen Quelle kennen und / oder Daten keine C-Zeichenfolge sind (hat eingebettete Nullen oder endet nicht mit einer Null). Wenn Sie einen C-String haben, können Sie einfach myString = data ausführen. es wird strlen oder gleichwertig für Sie laufen.
Eugene

1
@huseyintugrulbuyukisik Sie müssen den ursprünglichen Speicher noch ordnungsgemäß entsorgen - std :: string kopiert Bytes und übernimmt keinen Besitz.
Eugene

2
@ZackLee reserviert neuen Speicher für die Bytes und kopiert sie alle dort, so tief es geht. Wenn Sie das Potenzial für eine flache Kopie haben möchten, müssen Sie einen std :: string in einen anderen kopieren. Dann könnten einige Implementierungen eine flache Kopie machen, denke ich.
Eugene

30

Die meisten Antworten sprechen vom Konstruieren std::string .

Wenn bereits erstellt, verwenden Sie einfach den Zuweisungsoperator .

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

Ich muss std :: string verwenden, um Daten zu speichern, die von fgets () abgerufen wurden.

Warum verwenden, fgets()wenn Sie C ++ programmieren? Warum nicht std::getline()?


18

Geben Sie es durch den Konstruktor weiter:

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

Sie können die Funktion string.c_str () verwenden, um in die andere Richtung zu gehen:

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

3
c_str()kehrt zurückconst char*
Steve Jessop

1
Richtig, Sie können (sollten) die Daten in einem std :: string nicht über c_str () ändern. Wenn Sie beabsichtigen, die Daten zu ändern, sollte der c-String von c_str () gespeichert werden
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

Ich möchte eine neue Methode erwähnen, die das benutzerdefinierte Literal verwendet s. Dies ist nicht neu, wird jedoch häufiger auftreten, da es in der C ++ 14-Standardbibliothek hinzugefügt wurde.

Im allgemeinen Fall weitgehend überflüssig:

string mystring = "your string here"s;

Sie können jedoch auch Auto verwenden, auch mit breiten Zeichenfolgen:

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

Und hier scheint es wirklich:

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

2

Ich habe gerade mit MSVC2005 gekämpft, um den std::string(char*)Konstruktor genau wie die am besten bewertete Antwort zu verwenden. Wie ich sehe, ist diese Variante unter http://en.cppreference.com/w/cpp/string/basic_string/basic_string als Nummer 4 aufgeführt ich, dass dies sogar ein alter Compiler anbietet.

Es hat so lange gedauert, bis mir klar wurde, dass dieser Konstruktor absolut nicht (unsigned char*)als Argument übereinstimmt ! Ich habe diese unverständlichen Fehlermeldungen über die Nichtübereinstimmung mit dem std::stringArgumenttyp erhalten, was definitiv nicht das war, was ich anstrebte. Nur das Argument mit zu werfen, std::string((char*)ucharPtr)löste mein Problem ... duh!


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

9
Dies führt zu undefiniertem Verhalten.

1
Mit nur diesen beiden Zeilen datableibt nicht initialisiert (leer).
Heltonbiker

1
Ohne die wahre "Länge" des Zeigers kann dieser Code zu Datenverlust führen. Ihr std :: string wird "kürzer" als das ursprüngliche
Zeichen

0

Ich bin mir nicht sicher, warum niemand außer Erik dies erwähnt hat, aber laut dieser Seite funktioniert der Zuweisungsoperator einwandfrei. Sie müssen keinen Konstruktor, .assign () oder .append () verwenden.

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

1
Es scheint funktionell zu funktionieren, aber als ich dies tat, bekam ich Probleme damit, dass Valgrind am Ende des Programms erreichbare Blöcke meldete, die aus einem "neuen" Inneren von =(und +=) stammten . Es scheint nicht mit solchen Literalen zu passieren, sondern nur mit char*Dingen. Die Frage, ob solche Berichte tatsächlich undicht sind , wird hier erörtert . Aber wenn ich die Zuordnung zum destString = std::string(srcCharPtr);Valgrind geändert habe, sind Leckberichte verschwunden. YMMV.
HostileFork sagt, vertraue SE

Der Kommentar von HostileFork könnte Sie zu der Annahme führen, dass durch das Erstellen einer Zeichenfolge aus einem Zeichen * (wie aus fgets) std :: string die Lebensdauer dieses Speichers verwaltet. Dies ist jedoch nicht der Fall. Siehe Standard 21.4.2.7 und .9 Constructs an object of class basic_string and determines its initial string value from the array. Es sagt Wert und nichts über Puffer oder Zeigerbesitz.
Erik van Velzen
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.