Quiero convertir un std :: string en un tipo de datos char * o char [] .
std::string str = "string";
char* chr = str;
Resulta en: "error: no se puede convertir 'std :: string' a 'char' ..." .
¿Qué métodos hay disponibles para hacer esto?
Quiero convertir un std :: string en un tipo de datos char * o char [] .
std::string str = "string";
char* chr = str;
Resulta en: "error: no se puede convertir 'std :: string' a 'char' ..." .
¿Qué métodos hay disponibles para hacer esto?
Respuestas:
No se convertirá automáticamente (gracias a Dios). Tendrá que usar el método c_str()
para obtener la versión de cadena C.
std::string str = "string";
const char *cstr = str.c_str();
Tenga en cuenta que devuelve a const char *
; no puede cambiar la cadena de estilo C devuelta por c_str()
. Si desea procesarlo, primero deberá copiarlo:
std::string str = "string";
char *cstr = new char[str.length() + 1];
strcpy(cstr, str.c_str());
// do stuff
delete [] cstr;
O en C ++ moderno:
std::vector<char> cstr(str.c_str(), str.c_str() + str.size() + 1);
vector
fue inventado precisamente como un contenedor para matrices dinámicas, por lo que no usarlo parece una oportunidad perdida en el mejor de los casos, y en el peor de los casos, viola el espíritu de C ++.
std::string
se convertiría automáticamente) y luego explico lo que debería usar, con un ejemplo de código corto. Mirando hacia el futuro, también explico algunos efectos secundarios del uso de esta función, de los cuales uno no puede editar la cadena devuelta por c_str()
. Usted ve erróneamente mis ejemplos breves como un código de resolución de problemas real, que no lo es.
std::vector<char>
).
Más detalles aquí , y aquí, pero puedes usar
string str = "some string" ;
char *cstr = &str[0];
Si necesitara una copia cruda mutable del contenido de la cadena de c ++, entonces haría esto:
std::string str = "string";
char* chr = strdup(str.c_str());
y después:
free(chr);
Entonces, ¿por qué no juego con std :: vector o new [] como cualquier otra persona? Porque cuando necesito una cadena char * sin procesar de estilo C mutable, entonces porque quiero llamar al código C que cambia la cadena y el código C desasigna cosas con free () y asigna malloc () (strdup usa malloc) . Entonces, si paso mi cadena sin procesar a alguna función X escrita en C , podría tener una restricción en su argumento de que tiene que asignarse en el montón (por ejemplo, si la función podría llamar a realloc en el parámetro). ¡Pero es muy poco probable que espere un argumento asignado con (algunos redefinidos por el usuario) nuevo []!
strdup
es.
(Esta respuesta se aplica solo a C ++ 98).
Por favor, no uses un crudo 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)
, sin asignar el puntero a un carácter temporal?
std::basic_string<>::c_str()
es válido hasta que string
se cambie o se destruya. Esto también implica que devuelve el mismo valor en llamadas posteriores siempre que string
no se modifique.
vector
de esta manera. Y si uno escribiera código seguro de excepción sin un mecanismo RAII (es decir, utilizando punteros sin formato), la complejidad del código sería mucho mayor que esta simple línea.
vector
tiene una gran cantidad de gastos generales y complejidad. Si su requisito es que tenga una matriz de caracteres mutable , entonces, de hecho, un vector de caracteres es prácticamente el contenedor ideal de C ++. Si su requerimiento realmente solo requiere un puntero const-char, entonces simplemente use c_str()
y ya está.
Si solo desea una cadena de estilo C que represente el mismo contenido:
char const* ca = str.c_str();
Si desea una cadena de estilo C con nuevos contenidos, una forma (dado que no conoce el tamaño de la cadena en tiempo de compilación) es la asignación dinámica:
char* ca = new char[str.size()+1];
std::copy(str.begin(), str.end(), ca);
ca[str.size()] = '\0';
No lo olvides delete[]
más tarde.
Si desea una matriz de longitud limitada estáticamente asignada:
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::string
no se convierte implícitamente a estos tipos por la simple razón de que la necesidad de hacer esto suele ser un olor a diseño. Asegúrate de que realmente necesitas.
Si definitivamente necesita un char*
, la mejor manera es probablemente:
vector<char> v(str.begin(), str.end());
char* ca = &v[0]; // pointer to start of vector
&str.front(), &str.back()
(que no están presentes en C ++ 03) en lugar de los más comunes str.begin()
y str.end()
?
str.begin()
, o incluso std::begin(str)
, como un iterador? No creo que string
tenga ninguna obligación de estar en memoria contigua vector
, ¿o sí?
&back() + 1
, no&back()
Esto sería mejor como un comentario sobre la respuesta de bobobobo, pero no tengo el representante para eso. Logra lo mismo pero con mejores prácticas.
A pesar de las otras respuestas son útiles, si alguna vez necesita para convertir std::string
a char*
forma explícita y sin const, const_cast
es su amigo.
std::string str = "string";
char* chr = const_cast<char*>(str.c_str());
Tenga en cuenta que esto no le dará una copia de los datos; le dará un puntero a la cadena. Por lo tanto, si modifica un elemento de chr
, lo modificará str
.
Para ser estrictamente pedante, no puede "convertir una cadena std :: en un tipo de datos char * o char []".
Como han mostrado las otras respuestas, puede copiar el contenido de std :: string a una matriz de caracteres, o hacer un const char * al contenido de std :: string para que pueda acceder a él en un "estilo C" .
Si está intentando cambiar el contenido de std :: string, el tipo std :: string tiene todos los métodos para hacer cualquier cosa que pueda necesitar.
Si está tratando de pasarlo a alguna función que toma un char *, hay std :: string :: c_str ().
Aquí hay una versión más robusta de 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)
Conversión en estilo 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")
Por completo, no lo olvides std::string::copy()
.
std::string str = "string";
const size_t MAX = 80;
char chrs[MAX];
str.copy(chrs, MAX);
std::string::copy()
no termina NUL. Si necesita asegurar un terminador NUL para usar en funciones de cadena C:
std::string str = "string";
const size_t MAX = 80;
char chrs[MAX];
memset(chrs, '\0', MAX);
str.copy(chrs, MAX-1);
Para obtener un const char *
de un std::string
uso de la c_str()
función miembro:
std::string str = "string";
const char* chr = str.c_str();
Para obtener un no constante char *
de un std::string
puede usar la data()
función miembro que devuelve un puntero no constante desde C ++ 17:
std::string str = "string";
char* chr = str.data();
Para versiones anteriores del lenguaje, puede usar la construcción de rango para copiar la cadena en un vector del que se puede obtener un puntero sin constante:
std::string str = "string";
std::vector<char> str_copy(str.c_str(), str.c_str() + str.size() + 1);
char* chr = str_copy.data();
Pero tenga en cuenta que esto no le permitirá modificar la cadena contenida str
, solo los datos de la copia se pueden cambiar de esta manera. Tenga en cuenta que es especialmente importante en versiones anteriores del lenguaje usar c_str()
aquí porque en aquel entonces std::string
no se garantizaba que se anulara hasta que c_str()
se llamara.
char* result = strcpy((char*)malloc(str.length()+1), str.c_str());
Alternativamente, puede usar vectores para obtener un carácter de escritura * como se muestra a continuación;
//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
Esto también funcionará
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_str
locura por completo.