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?

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.


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);

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

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()?


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();

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;

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

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;

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!


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

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';

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
En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.