Em vez de: char * writable = new char [str.size () + 1]; Você pode usar char writable [str.size () + 1]; Então você não precisa se preocupar em excluir o tratamento gravável ou de exceção.
7
Você não pode usar str.size (), a menos que o tamanho seja conhecido no momento da compilação, também pode sobrecarregar sua pilha se o valor do tamanho fixo for enorme.
@cegprakash strcpye mallocnão são realmente a maneira C ++.
boycy 25/09/14
4
Não, mas char* dest = new char[str.length() + 1]; std::copy(str.begin(), str.end(), dest)seria C ++ mais idiomático. strcpy()e malloc()não estão errados ou problemáticos, mas parece inconsistente usar uma cadeia de caracteres C ++ e recursos da biblioteca C com equivalentes C ++ no mesmo bloco de código.
boycy
Respostas:
1057
Se você apenas deseja passar a std::stringpara uma função que precisa, const char*pode usar
std::string str;constchar* c = str.c_str();
Se você deseja obter uma cópia gravável char *, pode fazer isso com isso:
std::string str;char* writable =newchar[str.size()+1];
std::copy(str.begin(), str.end(), writable);
writable[str.size()]='\0';// don't forget the terminating 0// don't forget to free the string after finished using itdelete[] writable;
Edit : Observe que o acima não é exceção segura. Se algo entre a newchamada e a deletechamada for lançada, você vazará memória, pois nada será chamado deleteautomaticamente. Existem duas maneiras imediatas de resolver isso.
std::string str;
boost::scoped_array<char> writable(newchar[str.size()+1]);
std::copy(str.begin(), str.end(), writable.get());
writable[str.size()]='\0';// don't forget the terminating 0// get the char* using writable.get()// memory is automatically freed if the smart pointer goes // out of scope
std :: vector
Essa é a maneira padrão (não requer nenhuma biblioteca externa). Você usa std::vector, que gerencia completamente a memória para você.
std::string str;
std::vector<char> writable(str.begin(), str.end());
writable.push_back('\0');// get the char* using &writable[0] or &*writable.begin()
você poderia, mas strdup não é ac ou c ++ função padrão, que é de posix :)
Johannes Schaub - litb
14
o que eu provavelmente preferiria geralmente é std :: vector <char> gravável (str.begin (), str.end ()); writable.push_back ('\ 0'); char * c = & gravável [0];
Johannes Schaub - litb 7/12/08
17
std :: copy é a maneira c ++ de fazer isso, sem a necessidade de obter o ponteiro da string. Eu tento evitar o uso de funções C, tanto quanto eu puder.
Johannes Schaub - litb
16
A partir do C ++ 17, std::string::data()agora retorna a em CharT*vez de a const CharT*. Pode ser uma boa idéia para atualizar esta resposta :)
Rakete1111
192
Dado dizer ...
std::string x ="hello";
Obtendo um `char *` ou `const char *` de uma `string`
Como obter um ponteiro de caractere válido enquanto xpermanece no escopo e não é mais modificado
C ++ 11 simplifica as coisas; todos os seguintes dão acesso ao mesmo buffer interno de cadeias de caracteres:
constchar* p_c_str = x.c_str();constchar* p_data = x.data();char* p_writable_data = x.data();// for non-const x from C++17 constchar* p_x0 =&x[0];char* p_x0_rw =&x[0];// compiles iff x is not const...
Todos os ponteiros acima conterão o mesmo valor - o endereço do primeiro caractere no buffer. Mesmo uma string vazia possui um "primeiro caractere no buffer", porque o C ++ 11 garante sempre manter um caractere terminador NUL / 0 extra após o conteúdo da string explicitamente designado (por exemplo, std::string("this\0that", 9)manterá o buffer "this\0that\0").
Dado qualquer um dos indicadores acima:
char c = p[n];// valid for n <= x.size()// i.e. you can safely read the NUL at p[x.size()]
Somente para o não constponteiro p_writable_datae de &x[0]:
p_writable_data[n]= c;
p_x0_rw[n]= c;// valid for n <= x.size() - 1// i.e. don't overwrite the implementation maintained NUL
Escrever um NUL em outro lugar da string não altera os string's size(); stringé permitido conter qualquer número de NULs - eles não recebem tratamento especial por std::string(o mesmo em C ++ 03).
No C ++ 03 , as coisas eram consideravelmente mais complicadas (principais diferenças destacadas ):
x.data()
retorna const char*ao buffer interno da string que não era exigido pelo Padrão para concluir com um NUL (ou seja, pode ser ['h', 'e', 'l', 'l', 'o']seguido por valores não inicializados ou de lixo, com acessos acidentais a ele com comportamento indefinido ).
x.size()caracteres são seguros de ler, ou seja, x[0]atravésx[x.size() - 1]
para cadeias vazias, você garante um ponteiro não NULL ao qual 0 pode ser adicionado com segurança (viva!), mas você não deve desreferenciar esse ponteiro.
&x[0]
para cadeias vazias, isso tem um comportamento indefinido (21.3.4)
por exemplo, dado que f(const char* p, size_t n) { if (n == 0) return; ...whatever... }você não deve ligar f(&x[0], x.size());quando x.empty()- apenas use f(x.data(), ...).
caso contrário, conforme por x.data()mas:
para não- constxisso produz um não- constchar*ponteiro; você pode substituir o conteúdo da string
x.c_str()
retorna const char*para uma representação ASCIIZ (terminada em NUL) do valor (ou seja, ['h', 'e', 'l', 'l', 'o', '\ 0']).
embora poucas implementações tenham optado por fazê-lo, o C ++ 03 Standard foi redigido para permitir à implementação da cadeia a liberdade de criar um buffer distinto terminado por NUL em tempo real , a partir do buffer potencialmente não terminado por NUL "exposto" por x.data()e&x[0]
x.size() É seguro ler + 1 caracteres.
seguro garantido, mesmo para cadeias vazias (['\ 0']).
Consequências do acesso a índices legais externos
Qualquer que seja a maneira como você obtém um ponteiro, não deve acessar a memória mais além do ponteiro do que os caracteres garantidos presentes nas descrições acima. As tentativas de fazer isso têm um comportamento indefinido , com uma chance muito real de travamentos de aplicativos e resultados de lixo, mesmo para leituras e dados adicionais adicionais, empilham corrupção e / ou vulnerabilidades de segurança para gravações.
Quando esses ponteiros são invalidados?
Se você chamar alguma stringfunção de membro que modifique stringou reserve mais capacidade, quaisquer valores de ponteiro retornados anteriormente por qualquer um dos métodos acima serão invalidados . Você pode usar esses métodos novamente para obter outro ponteiro. (As regras são as mesmas que para os iteradores em strings).
Consulte também Como obter um ponteiro de caractere válido mesmo depois que xsai do escopo ou é modificado mais abaixo ....
Então, qual é o melhor para usar?
No C ++ 11, use .c_str()para dados ASCIIZ e .data()para dados "binários" (explicados mais abaixo).
No C ++ 03, use a .c_str()menos que .data()seja adequado e prefira .data()o &x[0]contrário, pois é seguro para cadeias de caracteres vazias ....
... tente entender o programa o suficiente para usar data()quando apropriado, ou você provavelmente cometerá outros erros ...
O caractere ASCII NUL '\ 0' garantido por .c_str()é usado por muitas funções como um valor sentinela que indica o fim dos dados relevantes e de acesso seguro. Isso se aplica às funções C ++ - somente funções como say fstream::fstream(const char* filename, ...)e funções compartilhadas com C como strchr()e printf().
Dadas as .c_str()garantias de C ++ 03 sobre o buffer retornado, são um superconjunto de .data()'s, você sempre pode usar com segurança .c_str(), mas às vezes as pessoas não o fazem porque:
usando .data()comunica-se com outros programadores lendo o código fonte de que os dados não são ASCIIZ (em vez disso, você está usando a string para armazenar um bloco de dados (que às vezes nem é realmente textual)) ou que está passando esses dados para outra função que a trata como um bloco de dados "binários". Isso pode ser um insight crucial para garantir que as alterações no código de outros programadores continuem a manipular os dados corretamente.
Somente C ++ 03: há uma pequena chance de que sua stringimplementação precise fazer uma alocação de memória extra e / ou cópia de dados para preparar o buffer terminado por NUL
Como uma dica adicional, se os parâmetros de uma função exigirem o ( const), char*mas não insistirem em obter x.size(), a função provavelmente precisará de uma entrada ASCIIZ, portanto, .c_str()é uma boa opção (a função precisa saber onde o texto termina de alguma forma, por isso, se não estiver) um parâmetro separado, ele pode ser apenas uma convenção, como um prefixo de comprimento ou sentinela ou algum comprimento esperado fixo).
Como obter um ponteiro de caractere válido mesmo depois que xsai do escopo ou é modificado ainda mais
Você precisará copiar o conteúdo da página stringxpara uma nova área de memória externa x. Esse buffer externo pode estar em muitos locais, como outra stringvariável ou matriz de caracteres, pode ou não ter uma vida útil diferente da xdevida a estar em um escopo diferente (por exemplo, namespace, global, estático, heap, memória compartilhada, arquivo mapeado pela memória) .
Para copiar o texto de std::string xpara uma matriz de caracteres independente:
// USING ANOTHER STRING - AUTO MEMORY MANAGEMENT, EXCEPTION SAFE
std::string old_x = x;// - old_x will not be affected by subsequent modifications to x...// - you can use `&old_x[0]` to get a writable char* to old_x's textual content// - you can use resize() to reduce/expand the string// - resizing isn't possible from within a function passed only the char* address
std::string old_x = x.c_str();// old_x will terminate early if x embeds NUL// Copies ASCIIZ data but could be less efficient as it needs to scan memory to// find the NUL terminator indicating string length before allocating that amount// of memory to copy into, or more efficient if it ends up allocating/copying a// lot less content.// Example, x == "ab\0cd" -> old_x == "ab".// USING A VECTOR OF CHAR - AUTO, EXCEPTION SAFE, HINTS AT BINARY CONTENT, GUARANTEED CONTIGUOUS EVEN IN C++03
std::vector<char> old_x(x.data(), x.data()+ x.size());// without the NUL
std::vector<char> old_x(x.c_str(), x.c_str()+ x.size()+1);// with the NUL// USING STACK WHERE MAXIMUM SIZE OF x IS KNOWN TO BE COMPILE-TIME CONSTANT "N"// (a bit dangerous, as "known" things are sometimes wrong and often become wrong)char y[N +1];
strcpy(y, x.c_str());// USING STACK WHERE UNEXPECTEDLY LONG x IS TRUNCATED (e.g. Hello\0->Hel\0)char y[N +1];
strncpy(y, x.c_str(), N);// copy at most N, zero-padding if shorter
y[N]='\0';// ensure NUL terminated// USING THE STACK TO HANDLE x OF UNKNOWN (BUT SANE) LENGTHchar* y = alloca(x.size()+1);
strcpy(y, x.c_str());// USING THE STACK TO HANDLE x OF UNKNOWN LENGTH (NON-STANDARD GCC EXTENSION)char y[x.size()+1];
strcpy(y, x.c_str());// USING new/delete HEAP MEMORY, MANUAL DEALLOC, NO INHERENT EXCEPTION SAFETYchar* y =newchar[x.size()+1];
strcpy(y, x.c_str());// or as a one-liner: char* y = strcpy(new char[x.size() + 1], x.c_str());// use y...delete[] y;// make sure no break, return, throw or branching bypasses this// USING new/delete HEAP MEMORY, SMART POINTER DEALLOCATION, EXCEPTION SAFE// see boost shared_array usage in Johannes Schaub's answer// USING malloc/free HEAP MEMORY, MANUAL DEALLOC, NO INHERENT EXCEPTION SAFETYchar* y = strdup(x.c_str());// use y...
free(y);
Outras razões para querer um char*ou const char*gerado a partir de umstring
Então, acima, você viu como obter um ( const) char*e como fazer uma cópia do texto independente do original string, mas o que você pode fazer com ele? Um punhado aleatório de exemplos ...
conceda acesso ao código "C" ao stringtexto do C ++ , como emprintf("x is '%s'", x.c_str());
copiar xo texto para um buffer especificado pelo responsável pela chamada da função (por exemplo strncpy(callers_buffer, callers_buffer_size, x.c_str())) ou memória volátil usada para E / S do dispositivo (por exemplo for (const char* p = x.c_str(); *p; ++p) *p_device = *p;)
anexar xo texto a uma matriz de caracteres que já contenha algum texto ASCIIZ (por exemplo strcat(other_buffer, x.c_str())) - tome cuidado para não exceder o buffer (em muitas situações, você pode precisar usar strncat)
retornar uma const char*ou char*de uma função (talvez por razões históricas - o cliente está usando sua API existente - ou para compatibilidade com C, você não deseja retornar a std::string, mas deseja copiar stringos dados de algum lugar para o chamador)
tenha cuidado para não retornar um ponteiro que possa ser desreferenciado pelo chamador depois que uma stringvariável local para a qual esse ponteiro apontado deixou o escopo
alguns projetos com objetos compartilhados compilados / vinculados para diferentes std::stringimplementações (por exemplo, STLport e nativo do compilador) podem passar dados como ASCIIZ para evitar conflitos
Agradável. Outro motivo para querer um caractere * (não const) é operar com transmissão MPI. Parece melhor se você não precisar copiar para frente e para trás. Eu pessoalmente teria oferecido um caractere de caractere para string. Ponteiro Const, mas sequência editável. Embora possa ter mexido com a conversão implícita de const char * para string ...
bartgol
33
Use o .c_str()método para const char *.
Você pode usar &mystring[0]para obter um char *ponteiro, mas há algumas dicas: você não obterá necessariamente uma string terminada com zero e não poderá alterar o tamanho da string. Você precisa tomar cuidado especial para não adicionar caracteres após o final da string ou obter uma saturação de buffer (e provável falha).
Não havia garantia de que todos os caracteres fizessem parte do mesmo buffer contíguo até o C ++ 11, mas na prática todas as implementações conhecidas std::stringfuncionavam dessa maneira; consulte “& s [0]” aponta para caracteres contíguos em uma std :: string? .
Observe que muitas stringfunções de membro realocam o buffer interno e invalidam os ponteiros que você pode ter salvo. Melhor usá-los imediatamente e depois descartar.
você deve observar que data () retorna const char * :) o que você quer dizer é & str [0], que retorna uma string terminada nula contígua, mas não necessária.
Johannes Schaub - litb 7/12/08
1
@litb, Argh! É o que recebo por tentar responder rapidamente. Eu usei sua solução no passado, não sei por que não foi a primeira coisa que me veio à mente. Eu editei minha resposta.
Mark Ransom
2
Tecnicamente, o armazenamento std :: string será contíguo apenas no C ++ 0x.
MSalters
1
@MSalters, obrigado - eu não sabia disso. Seria difícil encontrar uma implementação em que esse não fosse o caso.
O C ++ 17 (próximo padrão) altera a sinopse do modelo, basic_stringadicionando uma sobrecarga não constante de data():
charT* data() noexcept;
Retorna: Um ponteiro p tal que p + i == & operador para cada i em [0, tamanho ()].
CharT const * de std::basic_string<CharT>
std::string const cstr ={"..."};charconst* p = cstr.data();// or .c_str()
CharT * de std::basic_string<CharT>
std::string str ={"..."};char* p = str.data();
C ++ 11
CharT const * de std::basic_string<CharT>
std::string str ={"..."};
str.c_str();
CharT * de std::basic_string<CharT>
A partir do C ++ 11, o padrão diz:
Os objetos do tipo char em um basic_stringobjeto devem ser armazenados contiguamente. Ou seja, para qualquer basic_stringobjeto s, a identidade vale &*(s.begin() + n) == &*s.begin() + npara todos os valores de ntal modo 0 <= n < s.size().
Retorna: *(begin() + pos)se pos < size(), caso contrário, uma referência a um objeto do tipo CharTcom valor CharT(); o valor referenciado não deve ser modificado.
void aFunctionAPI(char* input);// other stuff
aFunctionAPI("Foo");//this call is not safe. if the function modified the //literal string the program will crash
std::string myFoo("Foo");
aFunctionAPI(myFoo.c_str());//this is not compiling
aFunctionAPI(const_cast<char*>(myFoo.c_str()));//this is not safe std::string //implement reference counting and //it may change the value of other//strings as well.DeepString myDeepFoo(myFoo);
aFunctionAPI(myFoo.str());//this is fine
Chamei a classe DeepStringporque ela está criando uma cópia profunda e exclusiva ( DeepStringnão é copiável) de uma string existente.
Eu evitaria essa convenção de nomenclatura. c_str()tal como utilizado por stduma abreviatura de "C-cadeia" "const string" não e str()sempre retorna um std::basic_string, não char*(por exemplo std::stringstream::str())
bcrist
8
char* result = strcpy((char*)malloc(str.length()+1), str.c_str());
parece chique, mas realmente difícil de entender ... Simples é o melhor IMO #
Naeem A. Malik
4
strcpy (), malloc (), length () e c_str () são funções básicas e não há nada difícil nisso. Apenas alocando memória e cópia.
Cegprakash
5
sim as funções são básicos mas você torcido e dobrado-los a olhar como tigela de espaguete ou um forro monstro de Frankenstein :)
Naeem A. Malik
4
Sim, as funções são básicas, mas ... você se lembra quando começou a lidar com uma linguagem de programação? Algumas linhas mais para explicar e ele realmente vai ajudar um neófito para saber por que, por exemplo, é diferente ou melhor do que esta resposta :)
Hastur
2
@egegakash: Sempre que houver um malloc (), também deverá haver um free (). Caso contrário, o código vazará memória e a solução em sua resposta também. Alocar memória sem ao menos sugerir a desalocação necessária é uma prática recomendada para essas perguntas.
Olá, o que você postou já foi dito várias vezes, com mais detalhes, em outras respostas à pergunta de 5 anos. É bom responder a perguntas mais antigas, mas somente se você adicionar novas informações. Caso contrário, é apenas barulho.
strcpy
emalloc
não são realmente a maneira C ++.char* dest = new char[str.length() + 1]; std::copy(str.begin(), str.end(), dest)
seria C ++ mais idiomático.strcpy()
emalloc()
não estão errados ou problemáticos, mas parece inconsistente usar uma cadeia de caracteres C ++ e recursos da biblioteca C com equivalentes C ++ no mesmo bloco de código.Respostas:
Se você apenas deseja passar a
std::string
para uma função que precisa,const char*
pode usarSe você deseja obter uma cópia gravável
char *
, pode fazer isso com isso:Edit : Observe que o acima não é exceção segura. Se algo entre a
new
chamada e adelete
chamada for lançada, você vazará memória, pois nada será chamadodelete
automaticamente. Existem duas maneiras imediatas de resolver isso.boost :: scoped_array
boost::scoped_array
excluirá a memória para você ao sair do escopo:std :: vector
Essa é a maneira padrão (não requer nenhuma biblioteca externa). Você usa
std::vector
, que gerencia completamente a memória para você.fonte
std::string::data()
agora retorna a emCharT*
vez de aconst CharT*
. Pode ser uma boa idéia para atualizar esta resposta :)Dado dizer ...
Obtendo um `char *` ou `const char *` de uma `string`
Como obter um ponteiro de caractere válido enquanto
x
permanece no escopo e não é mais modificadoC ++ 11 simplifica as coisas; todos os seguintes dão acesso ao mesmo buffer interno de cadeias de caracteres:
Todos os ponteiros acima conterão o mesmo valor - o endereço do primeiro caractere no buffer. Mesmo uma string vazia possui um "primeiro caractere no buffer", porque o C ++ 11 garante sempre manter um caractere terminador NUL / 0 extra após o conteúdo da string explicitamente designado (por exemplo,
std::string("this\0that", 9)
manterá o buffer"this\0that\0"
).Dado qualquer um dos indicadores acima:
Somente para o não
const
ponteirop_writable_data
e de&x[0]
:Escrever um NUL em outro lugar da string não altera os
string
'ssize()
;string
é permitido conter qualquer número de NULs - eles não recebem tratamento especial porstd::string
(o mesmo em C ++ 03).No C ++ 03 , as coisas eram consideravelmente mais complicadas (principais diferenças destacadas ):
x.data()
const char*
ao buffer interno da string que não era exigido pelo Padrão para concluir com um NUL (ou seja, pode ser['h', 'e', 'l', 'l', 'o']
seguido por valores não inicializados ou de lixo, com acessos acidentais a ele com comportamento indefinido ).x.size()
caracteres são seguros de ler, ou seja,x[0]
atravésx[x.size() - 1]
&x[0]
f(const char* p, size_t n) { if (n == 0) return; ...whatever... }
você não deve ligarf(&x[0], x.size());
quandox.empty()
- apenas usef(x.data(), ...)
.x.data()
mas:const
x
isso produz um não-const
char*
ponteiro; você pode substituir o conteúdo da stringx.c_str()
const char*
para uma representação ASCIIZ (terminada em NUL) do valor (ou seja, ['h', 'e', 'l', 'l', 'o', '\ 0']).x.data()
e&x[0]
x.size()
É seguro ler + 1 caracteres.Consequências do acesso a índices legais externos
Qualquer que seja a maneira como você obtém um ponteiro, não deve acessar a memória mais além do ponteiro do que os caracteres garantidos presentes nas descrições acima. As tentativas de fazer isso têm um comportamento indefinido , com uma chance muito real de travamentos de aplicativos e resultados de lixo, mesmo para leituras e dados adicionais adicionais, empilham corrupção e / ou vulnerabilidades de segurança para gravações.
Quando esses ponteiros são invalidados?
Se você chamar alguma
string
função de membro que modifiquestring
ou reserve mais capacidade, quaisquer valores de ponteiro retornados anteriormente por qualquer um dos métodos acima serão invalidados . Você pode usar esses métodos novamente para obter outro ponteiro. (As regras são as mesmas que para os iteradores emstring
s).Consulte também Como obter um ponteiro de caractere válido mesmo depois que
x
sai do escopo ou é modificado mais abaixo ....Então, qual é o melhor para usar?
No C ++ 11, use
.c_str()
para dados ASCIIZ e.data()
para dados "binários" (explicados mais abaixo).No C ++ 03, use a
.c_str()
menos que.data()
seja adequado e prefira.data()
o&x[0]
contrário, pois é seguro para cadeias de caracteres vazias ....... tente entender o programa o suficiente para usar
data()
quando apropriado, ou você provavelmente cometerá outros erros ...O caractere ASCII NUL '\ 0' garantido por
.c_str()
é usado por muitas funções como um valor sentinela que indica o fim dos dados relevantes e de acesso seguro. Isso se aplica às funções C ++ - somente funções como sayfstream::fstream(const char* filename, ...)
e funções compartilhadas com C comostrchr()
eprintf()
.Dadas as
.c_str()
garantias de C ++ 03 sobre o buffer retornado, são um superconjunto de.data()
's, você sempre pode usar com segurança.c_str()
, mas às vezes as pessoas não o fazem porque:.data()
comunica-se com outros programadores lendo o código fonte de que os dados não são ASCIIZ (em vez disso, você está usando a string para armazenar um bloco de dados (que às vezes nem é realmente textual)) ou que está passando esses dados para outra função que a trata como um bloco de dados "binários". Isso pode ser um insight crucial para garantir que as alterações no código de outros programadores continuem a manipular os dados corretamente.string
implementação precise fazer uma alocação de memória extra e / ou cópia de dados para preparar o buffer terminado por NULComo uma dica adicional, se os parâmetros de uma função exigirem o (
const
),char*
mas não insistirem em obterx.size()
, a função provavelmente precisará de uma entrada ASCIIZ, portanto,.c_str()
é uma boa opção (a função precisa saber onde o texto termina de alguma forma, por isso, se não estiver) um parâmetro separado, ele pode ser apenas uma convenção, como um prefixo de comprimento ou sentinela ou algum comprimento esperado fixo).Como obter um ponteiro de caractere válido mesmo depois que
x
sai do escopo ou é modificado ainda maisVocê precisará copiar o conteúdo da página
string
x
para uma nova área de memória externax
. Esse buffer externo pode estar em muitos locais, como outrastring
variável ou matriz de caracteres, pode ou não ter uma vida útil diferente dax
devida a estar em um escopo diferente (por exemplo, namespace, global, estático, heap, memória compartilhada, arquivo mapeado pela memória) .Para copiar o texto de
std::string x
para uma matriz de caracteres independente:Outras razões para querer um
char*
ouconst char*
gerado a partir de umstring
Então, acima, você viu como obter um (
const
)char*
e como fazer uma cópia do texto independente do originalstring
, mas o que você pode fazer com ele? Um punhado aleatório de exemplos ...string
texto do C ++ , como emprintf("x is '%s'", x.c_str());
x
o texto para um buffer especificado pelo responsável pela chamada da função (por exemplostrncpy(callers_buffer, callers_buffer_size, x.c_str())
) ou memória volátil usada para E / S do dispositivo (por exemplofor (const char* p = x.c_str(); *p; ++p) *p_device = *p;
)x
o texto a uma matriz de caracteres que já contenha algum texto ASCIIZ (por exemplostrcat(other_buffer, x.c_str())
) - tome cuidado para não exceder o buffer (em muitas situações, você pode precisar usarstrncat
)const char*
ouchar*
de uma função (talvez por razões históricas - o cliente está usando sua API existente - ou para compatibilidade com C, você não deseja retornar astd::string
, mas deseja copiarstring
os dados de algum lugar para o chamador)string
variável local para a qual esse ponteiro apontado deixou o escopostd::string
implementações (por exemplo, STLport e nativo do compilador) podem passar dados como ASCIIZ para evitar conflitosfonte
Use o
.c_str()
método paraconst char *
.Você pode usar
&mystring[0]
para obter umchar *
ponteiro, mas há algumas dicas: você não obterá necessariamente uma string terminada com zero e não poderá alterar o tamanho da string. Você precisa tomar cuidado especial para não adicionar caracteres após o final da string ou obter uma saturação de buffer (e provável falha).Não havia garantia de que todos os caracteres fizessem parte do mesmo buffer contíguo até o C ++ 11, mas na prática todas as implementações conhecidas
std::string
funcionavam dessa maneira; consulte “& s [0]” aponta para caracteres contíguos em uma std :: string? .Observe que muitas
string
funções de membro realocam o buffer interno e invalidam os ponteiros que você pode ter salvo. Melhor usá-los imediatamente e depois descartar.fonte
C ++ 17
O C ++ 17 (próximo padrão) altera a sinopse do modelo,
basic_string
adicionando uma sobrecarga não constante dedata()
:CharT const *
destd::basic_string<CharT>
CharT *
destd::basic_string<CharT>
C ++ 11
CharT const *
destd::basic_string<CharT>
CharT *
destd::basic_string<CharT>
A partir do C ++ 11, o padrão diz:
Existem maneiras possíveis de separar um ponteiro de caracter não constante.
1. Use o armazenamento contíguo do C ++ 11
Pró
Contras
'\0'
não deve ser alterado / não necessariamente parte da memória não const.2. Use
std::vector<CharT>
Pró
Contras
3. Use
std::array<CharT, N>
se oN
tempo de compilação for constante (e pequeno o suficiente)Pró
Contras
4. Alocação de memória bruta com exclusão automática de armazenamento
Pró
Contras
5. Alocação de memória bruta com manipulação manual
Pró
Vigarista
fonte
Estou trabalhando com uma API com muitas funções, recebidas como entrada a
char*
.Criei uma classe pequena para enfrentar esse tipo de problema, implementei o idioma RAII.
E você pode usá-lo como:
Chamei a classe
DeepString
porque ela está criando uma cópia profunda e exclusiva (DeepString
não é copiável) de uma string existente.fonte
c_str()
tal como utilizado porstd
uma abreviatura de "C-cadeia" "const string" não estr()
sempre retorna umstd::basic_string
, nãochar*
(por exemplostd::stringstream::str()
)fonte
Basta ver isso:
No entanto, observe que isso retornará a
const char *
.Para a
char *
, usestrcpy
para copiá-lo para outrachar
matriz.fonte
Tente isto
fonte