convertir un char * en std :: string

262

J'ai besoin d'utiliser un std::stringpour stocker les données récupérées par fgets(). Pour ce faire, je dois convertir la char*valeur de retour de fgets()en un std::stringpour stocker dans un tableau. Comment cela peut-il être fait?

Jonathan Prior
la source

Réponses:

376

std::string a un constructeur pour cela:

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

Notez que cette construction copie en profondeur la liste des caractères dans set sne devrait pas l'être nullptr, sinon le comportement n'est pas défini.

Jesse Beder
la source
6
que se passera-t-il si c'est le cas?
Carson Myers
14
Standard dit que le paramètre constructeur "ne doit pas être un pointeur nul" - il ne spécifie pas que des exceptions sont levées.
24
Est-ce une copie superficielle ou profonde?
4
@pushkin No strn'est qu'un nom de variable. Il pourrait être quelque chose: S, abc, l, I, strHelloWorld. Évidemment, certains choix sont meilleurs que d'autres. Mais pour cet exemple strest tout à fait acceptable.
Désillusionné
10
@Madhatter c'est une copie complète. L'allocation de pointeur restera et la chaîne se fera une nouvelle allocation.
moodboom
127

Si vous connaissez déjà la taille du caractère *, utilisez-le à la place

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

Cela n'utilise pas de strlen.

EDIT: Si la variable chaîne existe déjà, utilisez assign ():

std::string myString;
char* data = ...;
int size = ...;
myString.assign(data, size);
Eugène
la source
1
Une sorte de question secondaire, Eugene. Si les données ne sont remplies que plus tard dans la routine, comment initialisez-vous alors myString? Déclarez-vous simplement la variable myString lorsqu'elle est remplie?
IcedDante
2
int size = strlen (données);
Vlad
@vlad: l'idée est que vous savez que la taille d'une autre source et / ou de données n'est pas une chaîne C (a des valeurs nulles intégrées ou ne se termine pas par une valeur nulle). Si vous avez une chaîne C, vous pouvez simplement faire myString = data; il s'exécutera strlen ou équivalent pour vous.
Eugene
1
@huseyintugrulbuyukisik Vous devez encore disposer de la mémoire d'origine correctement - std :: string copiera les octets, il n'en prendra pas la propriété.
Eugene
2
@ZackLee allouera de la nouvelle mémoire pour les octets et les copiera tous là-dedans, aussi profondément que possible. Si vous voulez un potentiel de copie superficielle, vous devez copier une chaîne std :: dans une autre. Ensuite, certaines implémentations pourraient faire une copie superficielle, je pense.
Eugene
30

La plupart des réponses parlent de construction std::string .

S'il est déjà construit, utilisez simplement l'opérateur d'affectation .

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
la source
28

J'ai besoin d'utiliser std :: string pour stocker les données récupérées par fgets ().

Pourquoi utiliser fgets()lorsque vous programmez C ++? Pourquoi ne pas std::getline()?

Paul
la source
18

Passez-le via le constructeur:

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

Vous pouvez utiliser la fonction string.c_str () pour aller dans l'autre sens:

std::string my_string("testing!");
const char* dat = my_string.c_str();
James Thompson
la source
3
c_str()retoursconst char*
Steve Jessop
1
à droite, vous ne pouvez pas (ne devriez pas) modifier les données dans une chaîne std :: via c_str (). Si vous avez l'intention de modifier les données, la chaîne c de c_str () devrait être mémorisée
Carson Myers
11
const char* charPointer = "Hello, World!\n";
std::string strFromChar;
strFromChar.append(charPointer);
std::cout<<strFromChar<<std::endl;

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

Je voudrais mentionner une nouvelle méthode qui utilise le littéral défini par l'utilisateur s. Ce n'est pas nouveau, mais ce sera plus courant car il a été ajouté dans la bibliothèque standard C ++ 14.

Largement superflu dans le cas général:

string mystring = "your string here"s;

Mais cela vous permet d'utiliser auto, également avec des chaînes larges:

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

Et c'est là que ça brille vraiment:

string suffix;
cin >> suffix;
string mystring = "mystring"s + suffix;
Erik van Velzen
la source
2

Je viens de me battre avec MSVC2005 pour utiliser le std::string(char*)constructeur comme la réponse la mieux notée. Comme je vois cette variante répertoriée comme # 4 sur http://en.cppreference.com/w/cpp/string/basic_string/basic_string toujours fiable , je pense que même un ancien compilateur offre cela.

Il m'a fallu si longtemps pour réaliser que ce constructeur absolu refuse de correspondre avec (unsigned char*)comme argument! J'ai reçu ces messages d'erreur incompréhensibles sur l'échec de la correspondance avec le std::stringtype d'argument, ce qui n'était certainement pas ce que je visais. Le simple fait de lancer l'argument a std::string((char*)ucharPtr)résolu mon problème ... duh!

user1564286
la source
0
char* data;
std::string myString(data);
Daniel A. White
la source
9
Cela entraînera un comportement indéfini.
1
Avec seulement ces deux lignes, datareste non initialisé (vide).
heltonbiker du
1
Sans la vraie "longueur" du pointeur fourni, ce code peut entraîner la perte de données, votre chaîne std :: sera "plus courte" que le caractère d'origine *
Andiana
0

Je ne sais pas pourquoi personne à part Erik n'a mentionné cela, mais selon cette page , l'opérateur d'affectation fonctionne très bien. Pas besoin d'utiliser un constructeur, .assign () ou .append ().

std::string mystring;
mystring = "This is a test!";   // Assign C string to std:string directly
std::cout << mystring << '\n';
Vern Jensen
la source
1
Cela semble fonctionner de manière fonctionnelle, mais quand j'ai fait cela, j'ai commencé à avoir des problèmes avec Valgrind, signalant les blocs accessibles à la fin du programme, provenant d'un "nouveau" à l'intérieur de =(et +=). Cela ne semble pas se produire avec des littéraux comme celui-ci, mais seulement avec des char*choses. La question de savoir si de tels rapports sont réellement des fuites est discutée ici . Mais si je modifiais l'attribution aux destString = std::string(srcCharPtr);rapports de fuite de Valgrind, ils disparaissaient. YMMV.
HostileFork dit de ne pas faire confiance au SE
Le commentaire de HostileFork pourrait vous faire croire que la construction d'une chaîne à partir d'un char * (comme à partir de fgets) permettra à std :: string de gérer la durée de vie de cette mémoire. Cependant, ce n'est pas le cas. Voir les normes 21.4.2.7 et .9 Constructs an object of class basic_string and determines its initial string value from the array. Il indique la valeur et rien sur les tampons ou la propriété du pointeur.
Erik van Velzen