tochararray - string to char function c++




Como converter um std:: string para const char*ou char*? (6)

C ++ 17

O C ++ 17 (padrão futuro) altera a sinopse do modelo basic_string adicionando uma sobrecarga de data() não é const data() :

charT* data() noexcept;

Retorna: Um ponteiro p tal que p + i == & operador para cada i em [0, tamanho ()].

CharT const * from std::basic_string<CharT>

std::string const cstr = { "..." };
char const * p = cstr.data(); // or .c_str()

CharT * de std::basic_string<CharT>

std::string str = { "..." };
char * p = str.data();

C ++ 11

CharT const * from std::basic_string<CharT>

std::string str = { "..." };
str.c_str();

CharT * de std::basic_string<CharT>

Do C ++ 11 em diante, o padrão diz:

  1. Os objetos tipo char em um objeto basic_string devem ser armazenados contiguamente. Isto é, para qualquer objeto basic_string s , a identidade &*(s.begin() + n) == &*s.begin() + n deve ser válida para todos os valores de n tais que 0 <= n < s.size()
  1. const_reference operator[](size_type pos) const;
    reference operator[](size_type pos);

    Retorna: *(begin() + pos) se pos < size() , caso contrário, uma referência a um objeto do tipo CharT com o valor CharT() ; o valor referenciado não deve ser modificado.

  1. const charT* c_str() const noexcept;
    const charT* data() const noexcept;

    Retorna: Um ponteiro p tal que p + i == &operator[](i) para cada i em [0,size()] .

Existem maneiras possíveis separáveis ​​de obter um ponteiro de caractere não const.

1. Use o armazenamento contíguo do C ++ 11

std::string foo{"text"};
auto p = &*foo.begin();

Pró

  • Simples e curto
  • Rápido (único método sem cópia envolvida)

Contras

  • Final '\0' não deve ser alterado / não necessariamente parte da memória não-const.

2. Use std::vector<CharT>

std::string foo{"text"};
std::vector<char> fcv(foo.data(), foo.data()+foo.size()+1u);
auto p = fcv.data();

Pró

  • Simples
  • Manuseio automático de memória
  • Dinâmico

Contras

  • Requer cópia de string

3. Use std::array<CharT, N> se N for constante de tempo de compilação (e pequeno o suficiente)

std::string foo{"text"};
std::array<char, 5u> fca;
std::copy(foo.data(), foo.data()+foo.size()+1u, fca.begin());

Pró

  • Simples
  • Manipulação de memória de pilha

Contras

  • Estático
  • Requer cópia de string

4. Alocação de memória bruta com exclusão automática de armazenamento

std::string foo{ "text" };
auto p = std::make_unique<char[]>(foo.size()+1u);
std::copy(foo.data(), foo.data() + foo.size() + 1u, &p[0]);

Pró

  • Pegada de memória pequena
  • Exclusão automática
  • Simples

Contras

  • Requer cópia de string
  • Estático (uso dinâmico requer muito mais código)
  • Menos recursos que vetor ou matriz

5. Alocação de memória bruta com manuseio manual

std::string foo{ "text" };
char * p = nullptr;
try
{
  p = new char[foo.size() + 1u];
  std::copy(foo.data(), foo.data() + foo.size() + 1u, p);
  // handle stuff with p
  delete[] p;
}
catch (...)
{
  if (p) { delete[] p; }
  throw;
}

Pró

  • Máximo 'controle'

Vigarista

  • Requer cópia de string
  • Máxima responsabilidade / suscetibilidade por erros
  • Complexo

Como posso converter um std::string para um char* ou um const char* ?


Apenas veja isto:

string str1("");
const char * str2 = str1.c_str();

No entanto, observe que isso retornará um const char * .Para um char * , use o strcpy para copiá-lo em outro array char .


Eu estou trabalhando com uma API com um monte de funções obter como entrada um char* .

Eu criei uma pequena classe para enfrentar este tipo de problema, eu implementei o idioma RAII.

class DeepString
{
        DeepString(const DeepString& other);
        DeepString& operator=(const DeepString& other);
        char* internal_; 

    public:
        explicit DeepString( const string& toCopy): 
            internal_(new char[toCopy.size()+1]) 
        {
            strcpy(internal_,toCopy.c_str());
        }
        ~DeepString() { delete[] internal_; }
        char* str() const { return internal_; }
        const char* c_str()  const { return internal_; }
};

E você pode usá-lo como:

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

Eu chamei a classe DeepString porque ela está criando uma cópia profunda e única (o DeepString não é copiável) de uma string existente.


Se você quer apenas passar um std::string para uma função que precisa const char* você pode usar

std::string str;
const char * c = str.c_str();

Se você quiser obter uma cópia gravável, como char * , você pode fazer isso com isto:

std::string str;
char * writable = new char[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 it
delete[] writable;

Edit : Observe que o acima não é exceção segura. Se alguma coisa entre a new chamada e a chamada de delete emitida, você vazará memória, já que nada chamará delete automaticamente. Existem duas maneiras imediatas de resolver isso.

boost :: scoped_array

boost::scoped_array irá apagar a memória para você ao sair do escopo:

std::string str;
boost::scoped_array<char> writable(new char[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

Esta é 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()

Use o método .c_str() para const char * .

Você pode usar o &mystring[0] para obter um char * , mas há algumas pegadinhas: você não terá necessariamente uma cadeia terminada com zero e não poderá alterar o tamanho da string. Você especialmente tem que ter cuidado para não adicionar caracteres após o final da seqüência de caracteres ou você obterá uma sobrecarga de buffer (e provável acidente).

Não havia garantia de que todos os caracteres seriam parte do mesmo buffer contíguo até o C ++ 11, mas, na prática, todas as implementações conhecidas do std::string funcionavam dessa maneira; consulte “& s [0]” aponta para caracteres contíguos em um std :: string? .

Observe que muitas funções de membros de string realocarão o buffer interno e invalidarão todos os ponteiros que você possa ter salvo. Melhor usá-los imediatamente e depois descartar.


char* result = strcpy((char*)malloc(str.length()+1), str.c_str());




const