converter um char * em std :: string

262

Eu preciso usar um std::stringpara armazenar dados recuperados por fgets(). Para fazer isso, preciso converter o char*valor de retorno defgets() em std::stringpara armazenar em uma matriz. Como isso pode ser feito?

Jonathan Prior
fonte

Respostas:

376

std::string tem um construtor para isso:

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

Observe que essa construção copia profundamente a lista de caracteres em se snão deve ser nullptr, ou o comportamento é indefinido.

Jesse Beder
fonte
6
o que acontecerá se for?
Carson Myers
14
O padrão diz que o parâmetro do construtor "não deve ser um ponteiro nulo" - não especifica que nenhuma exceção seja lançada.
24
É uma cópia superficial ou profunda?
4
@pushkin Não stré apenas um nome de variável. Poderia ser qualquer coisa: S, abc, l, I, strHelloWorld. Obviamente, algumas opções são melhores que outras. Mas para este exemplo stré bastante aceitável.
desiludido em
10
@ Madhatter é uma cópia profunda. A alocação do ponteiro permanecerá e a sequência se tornará uma nova alocação.
Moodboom
127

Se você já sabe o tamanho do caractere *, use-o

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

Isso não usa strlen.

EDIT: Se a variável de string já existir, use assign ():

std::string myString;
char* data = ...;
int size = ...;
myString.assign(data, size);
Eugene
fonte
1
Uma espécie de pergunta paralela, Eugene. Se os dados não forem preenchidos até mais tarde na rotina, como você inicializa o myString? Você simplesmente declara a variável myString quando é preenchida?
IcedDante
2
int tamanho = strlen (dados);
Vlad
@ Vlad: a idéia é que você saiba que o tamanho de alguma outra fonte e / ou dados não é uma string C (possui nulos incorporados ou não termina em nulo). Se você tem uma string C, pode simplesmente fazer myString = data; será executado strlen ou equivalente para você.
Eugene
1
@huseyintugrulbuyukisik Você ainda precisa descartar a memória original corretamente - std :: string copiará bytes, não é de propriedade.
Eugene
2
@ZackLee, ele alocará nova memória para os bytes e os copiará todos lá, tão profundamente quanto possível. Se você deseja uma cópia superficial, é necessário copiar uma std :: string para outra. Então algumas implementações poderiam fazer uma cópia superficial, eu acho.
Eugene
30

A maioria das respostas fala sobre a construção std::string .

Se já estiver construído, basta usar o operador de atribuição .

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
fonte
28

Eu preciso usar std :: string para armazenar dados recuperados por fgets ().

Por que usar fgets()quando você está programando C ++? Por que não std::getline()?

Paulo
fonte
18

Passe-o pelo construtor:

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

Você pode usar a função string.c_str () para o contrário:

std::string my_string("testing!");
const char* dat = my_string.c_str();
James Thompson
fonte
3
c_str()retornaconst char*
Steve Jessop
1
certo, você não pode (não deveria) modificar os dados em uma std :: string via c_str (). Se você pretende alterar os dados, então a string c de c_str () deve ser gravada com erro
Carson Myers
11
const char* charPointer = "Hello, World!\n";
std::string strFromChar;
strFromChar.append(charPointer);
std::cout<<strFromChar<<std::endl;

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

Gostaria de mencionar um novo método que usa o literal definido pelo usuário s. Isso não é novo, mas será mais comum porque foi adicionado na Biblioteca Padrão C ++ 14.

Em grande parte supérfluo no caso geral:

string mystring = "your string here"s;

Mas permite que você use auto, também com amplas strings:

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

E aqui é onde realmente brilha:

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

Acabei de lutar com o MSVC2005 para usar o std::string(char*)construtor exatamente como a resposta mais bem avaliada. Como vejo essa variante listada como nº 4 em http://en.cppreference.com/w/cpp/string/basic_string/basic_string sempre confiável , acho que até um compilador antigo oferece isso.

Levei tanto tempo para perceber que esse construtor se recusa a combinar (unsigned char*)como argumento! Recebi essas mensagens de erro incompreensíveis sobre falha na correspondência com o std::stringtipo de argumento, o que definitivamente não era o que eu pretendia. Acabar de lançar o argumento std::string((char*)ucharPtr)resolveu meu problema ... duh!

user1564286
fonte
0
char* data;
std::string myString(data);
Daniel A. White
fonte
9
Isso resultará em um comportamento indefinido.
1
Com apenas essas duas linhas, datapermanece não inicializado (vazio).
Heltonbiker
1
Sem o "comprimento" verdadeiro do ponteiro fornecido, esse código pode causar a perda de dados, sua std :: string será "mais curta" do que o caractere original *
Andiana
0

Não sei por que ninguém além de Erik mencionou isso, mas de acordo com esta página , o operador de atribuição funciona bem. Não há necessidade de usar um construtor, .assign () ou .append ().

std::string mystring;
mystring = "This is a test!";   // Assign C string to std:string directly
std::cout << mystring << '\n';
Vern Jensen
fonte
1
Parece que funciona funcionalmente, mas quando fiz isso, comecei a ter problemas com o Valgrind relatando blocos acessíveis no final do programa, originados de um "novo" dentro de =(e +=). Não parece acontecer com literais como este, mas apenas com as char*coisas. A questão de saber se esses relatórios são realmente vazamentos é discutida aqui . Mas se eu alterasse a atribuição para destString = std::string(srcCharPtr);os relatórios de vazamento da valgrind, eles desapareceriam. YMMV.
HostileFork diz que não confia em SE
O comentário do HostileFork pode levar você a acreditar que a construção de uma string a partir de um caractere * (como no fgets) fará com que std :: string gerencie o tempo de vida dessa memória. No entanto, este não é o caso. Veja o padrão 21.4.2.7 e .9 Constructs an object of class basic_string and determines its initial string value from the array. Diz valor e nada sobre buffers ou propriedade do ponteiro.
Erik van Velzen