Voglio convertire una stringa std :: string in un tipo di dati char * o char [] .
std::string str = "string";
char* chr = str;
Risultati in: "errore: impossibile convertire" std :: string "in" char "..." .
Quali metodi sono disponibili per farlo?
Voglio convertire una stringa std :: string in un tipo di dati char * o char [] .
std::string str = "string";
char* chr = str;
Risultati in: "errore: impossibile convertire" std :: string "in" char "..." .
Quali metodi sono disponibili per farlo?
Risposte:
Non si convertirà automaticamente (grazie a dio). Dovrai utilizzare il metodo c_str()per ottenere la versione della stringa C.
std::string str = "string";
const char *cstr = str.c_str();
Si noti che restituisce a const char *; non ti è permesso cambiare la stringa di tipo C restituita da c_str(). Se vuoi elaborarlo, devi prima copiarlo:
std::string str = "string";
char *cstr = new char[str.length() + 1];
strcpy(cstr, str.c_str());
// do stuff
delete [] cstr;
O nel C ++ moderno:
std::vector<char> cstr(str.c_str(), str.c_str() + str.size() + 1);
vectorè stato inventato proprio come un wrapper per array dinamici, quindi non utilizzarlo sembra un'opportunità mancata nel migliore dei casi e in violazione dello spirito del C ++ nel peggiore dei casi.
std::stringsi convertirà automaticamente) e poi spiego cosa dovrebbe usare, con un esempio di codice breve. In prospettiva spiego anche alcuni effetti collaterali dell'uso di questa funzione, di cui uno è che non è possibile modificare la stringa restituita da c_str(). Vedi erroneamente i miei brevi esempi come un vero codice per la risoluzione dei problemi, che non lo è.
std::vector<char>).
Maggiori dettagli qui e qui ma è possibile utilizzare
string str = "some string" ;
char *cstr = &str[0];
Se avessi bisogno di una copia raw mutabile del contenuto della stringa di un c ++, allora farei questo:
std::string str = "string";
char* chr = strdup(str.c_str());
e più tardi:
free(chr);
Quindi perché non giocherellare con std :: vector o new [] come chiunque altro? Perché quando ho bisogno di una stringa char char * in stile C mutabile, allora perché voglio chiamare il codice C che cambia la stringa e il codice C dealloca le cose con free () e le alloca con malloc () (strdup usa malloc) . Quindi, se passo la mia stringa non elaborata a una funzione X scritta in C , potrebbe avere un vincolo sull'argomento che deve essere allocato sull'heap (ad esempio se la funzione potrebbe voler chiamare realloc sul parametro). Ma è altamente improbabile che si aspetti un argomento assegnato con (alcuni ridefiniti dall'utente) nuovo []!
strdupviene.
(Questa risposta si applica solo a C ++ 98).
Per favore, non usare un raw char*.
std::string str = "string";
std::vector<char> chars(str.c_str(), str.c_str() + str.size() + 1u);
// use &chars[0] as a char*
vector<char>(str.c_str(), str.c_str() + str.size() + 1), senza assegnare il puntatore al carattere a un temporaneo?
std::basic_string<>::c_str()è valido fino a quando non stringviene modificato o distrutto. Ciò implica anche che restituisce lo stesso valore nelle chiamate successive purché stringnon venga modificato.
vectorin questo modo non vi è alcun sovraccarico di velocità o spazio . E se si scrivesse un codice sicuro per le eccezioni senza un meccanismo RAII (ovvero usando puntatori non elaborati), la complessità del codice sarebbe molto più elevata di questo semplice one-liner.
vectorha un'enorme quantità di costi generali e complessità. Se il tuo requisito è che tu abbia un array di caratteri mutabile , in realtà un vettore di caratteri è praticamente il wrapper C ++ ideale. Se il tuo requisito in realtà richiede solo un puntatore const-char, allora basta usare c_str()e il gioco è fatto.
Se vuoi solo una stringa in stile C che rappresenti lo stesso contenuto:
char const* ca = str.c_str();Se si desidera una stringa in stile C con nuovi contenuti, un modo (dato che non si conosce la dimensione della stringa in fase di compilazione) è l'allocazione dinamica:
char* ca = new char[str.size()+1];
std::copy(str.begin(), str.end(), ca);
ca[str.size()] = '\0';
Non dimenticarlo delete[]più tardi.
Se si desidera invece un array di lunghezza limitata allocato staticamente:
size_t const MAX = 80; // maximum number of chars
char ca[MAX] = {};
std::copy(str.begin(), (str.size() >= MAX ? str.begin() + MAX : str.end()), ca);std::stringnon si converte implicitamente in questi tipi per la semplice ragione che la necessità di farlo è di solito un odore di design. Assicurati di averne davvero bisogno.
Se hai sicuramente bisogno di un char*, il modo migliore è probabilmente:
vector<char> v(str.begin(), str.end());
char* ca = &v[0]; // pointer to start of vector
&str.front(), &str.back()(che non sono presenti in C ++ 03) anziché i più comuni str.begin()e str.end()?
str.begin(), o addirittura std::begin(str), simile a un iteratore? Non credo stringabbia alcun obbligo di essere nella memoria contigua come vector, o no ?
&back() + 1, non&back()
Sarebbe meglio come un commento sulla risposta di bobobobo, ma non ho il rappresentante per questo. Compie la stessa cosa ma con pratiche migliori.
Anche se le altre risposte sono utili, se mai hai bisogno di convertire std::stringa char*esplicitamente, senza const, const_castè tuo amico.
std::string str = "string";
char* chr = const_cast<char*>(str.c_str());
Nota che questo non ti darà una copia dei dati; ti darà un puntatore alla stringa. Pertanto, se si modifica un elemento di chr, si modificherà str.
Per essere rigorosamente pedanti, non è possibile "convertire una stringa std :: string in un tipo di dati char * o char []".
Come hanno mostrato le altre risposte, è possibile copiare il contenuto di std :: string in un array di caratteri oppure creare un carattere const * nel contenuto di std :: string in modo che sia possibile accedervi in uno "stile C" .
Se stai provando a cambiare il contenuto dello std :: string, il tipo std :: string ha tutti i metodi per fare qualsiasi cosa tu possa aver bisogno di farci.
Se stai provando a passarlo a qualche funzione che richiede un carattere *, c'è std :: string :: c_str ().
Ecco un'altra versione robusta di Protocol Buffer
char* string_as_array(string* str)
{
return str->empty() ? NULL : &*str->begin();
}
// test codes
std::string mystr("you are here");
char* pstr = string_as_array(&mystr);
cout << pstr << endl; // you are here
if (str[str.length()-1] != 0) str.push_back(0)
Conversione in stile OOP
converter.hpp
class StringConverter {
public: static char * strToChar(std::string str);
};
converter.cpp
char * StringConverter::strToChar(std::string str)
{
return (char*)str.c_str();
}
uso
StringConverter::strToChar("converted string")
Per completezza, non dimenticare std::string::copy().
std::string str = "string";
const size_t MAX = 80;
char chrs[MAX];
str.copy(chrs, MAX);
std::string::copy()non termina NUL. Se è necessario garantire un terminatore NUL per l'uso nelle funzioni di stringa C:
std::string str = "string";
const size_t MAX = 80;
char chrs[MAX];
memset(chrs, '\0', MAX);
str.copy(chrs, MAX-1);
Per ottenere un const char *da un std::stringuso la c_str()funzione membro:
std::string str = "string";
const char* chr = str.c_str();
Per ottenere un non const char *da un std::stringè possibile utilizzare la data()funzione membro che restituisce un puntatore non const dal C ++ 17:
std::string str = "string";
char* chr = str.data();
Per le versioni precedenti della lingua, è possibile utilizzare la costruzione di intervalli per copiare la stringa in un vettore da cui è possibile ottenere un puntatore non const:
std::string str = "string";
std::vector<char> str_copy(str.c_str(), str.c_str() + str.size() + 1);
char* chr = str_copy.data();
Ma attenzione che questo non ti permetterà di modificare la stringa contenuta in str, solo i dati della copia possono essere modificati in questo modo. Si noti che è particolarmente importante nelle versioni precedenti del linguaggio utilizzare c_str()qui perché all'epoca std::stringnon era garantito che venisse annullato fino a quando non c_str()veniva chiamato.
char* result = strcpy((char*)malloc(str.length()+1), str.c_str());
In alternativa, è possibile utilizzare i vettori per ottenere un carattere scrivibile * come mostrato di seguito;
//this handles memory manipulations and is more convenient
string str;
vector <char> writable (str.begin (), str.end) ;
writable .push_back ('\0');
char* cstring = &writable[0] //or &*writable.begin ()
//Goodluck
Questo funzionerà anche
std::string s;
std::cout<<"Enter the String";
std::getline(std::cin, s);
char *a=new char[s.size()+1];
a[s.size()]=0;
memcpy(a,s.c_str(),s.size());
std::cout<<a;
c_strcompletamente questa follia.