815 votos

Convertir patraña const char * o char *

¿Cómo puedo convertir un std::string a un char* o un const char* ?

971voto

Johannes Schaub - litb Puntos 256113

Si sólo quieres pasar un std::string a una función que necesita const char* puede utilizar

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

Si desea obtener una copia modificable, como char *, usted puede hacer eso con esto:

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: Aviso que el de arriba no es la excepción seguro. Si nada entre la llamada nueva y la eliminación de la llamada lanza, que se fuga de memoria, ya que nada se llame a eliminar de forma automática. Hay dos formas inmediatamente para solucionar esto.

boost::scoped_array

boost::scoped_array borrará de la memoria para usted en el momento de salir de alcance:

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 es la manera estándar (no requiere de ninguna librería externa). Utilice std::vector, que gestiona la memoria para usted.

std::string str;
std::vector<char> writable(str.begin(), str.end());
writable.push_back('\0');

// get the char* using &writable[0] or &*writable.begin()

179voto

Tony D Puntos 43962

Dada decir...

std::string x = "hello";

Conseguir un `char *` o `const char*` de una `cadena`

Cómo obtener un puntero de carácter válida mientras x permanece en su alcance y no se modifica más

Uso:

  • x.c_str()
    • vuelve const char* a un ASCIIZ (NUL-terminada) de la representación del valor (es decir. ['h', 'e', 'l', 'l', 'o', '\0']).
    • x.size() + 1 de los personajes son seguros para leer.
    • garantizado de manera segura, incluso para las cadenas vacías (['\0']).
  • x.data()
    • vuelve const char* a la cadena del buffer que no la promesa de concluir con un NUL (es decir. ['h', 'e', 'l', 'l', 's']).
    • x.size() personajes son seguros para leer.
    • para las cadenas vacías, usted tiene la garantía de no-puntero NULL para que 0 puede ser de forma segura añadido, pero no se debe eliminar la referencia que el puntero.
  • &x[0]
    • como por x.data() , pero los rendimientos potencialmente no const char* puntero
    • x.size() personajes son seguros para leer, y escribir, si x no const
      • escribir un NUL no cambia el strings' size(); strings'pueden contener cualquier número de NULs - no tienen un tratamiento especial por std::string.
    • para las cadenas vacías, esto tiene un comportamiento indefinido(21.3.4)
      • por ejemplo. dada f(const char* p, size_t n) { if (n == 0) return; ...whatever... } no llame f(&x[0], x.size()); cuando x.empty() - sólo tiene que utilizar f(x.data(), ...).

Si usted llama a algunas string función miembro que modifica el string o reservas de más capacidad, cualquier puntero valores devueltos de antemano por cualquiera de los métodos anteriores son invalidadas. Usted puede utilizar estos métodos para conseguir otro puntero. (Las reglas son las mismas que para los iteradores en strings).

Cualquiera que sea su uso, usted no debe de memoria de acceso además a lo largo del puntero de los personajes garantizado presente en las descripciones anteriores. Los intentos de hacerlo tiene un comportamiento indefinido, con una muy real posibilidad de que la aplicación se bloquea, incluso para las lecturas, y, además, mayorista de datos, daños en la pila y/o vulnerabilidades de seguridad para los escribe.

Consejo: utilice .c_str() menos cierto que .data() es adecuado.

...pero no trate de entender el programa lo suficientemente data() cuando corresponda, o es probable que otros errores...

El ASCII NUL '\0' carácter garantizado por .c_str() es utilizado por muchas de las funciones como un centinela de valor que denota el final de pertinente y seguro para acceder a los datos. Esto se aplica tanto a de C++-sólo funciona como decimos fstream::fstream(const char* filename, ...) y compartida-con-las funciones de C como strchr()y printf().

Dada .c_str()'s de garantías acerca de la devolución de búfer es un super-conjunto de .data()'s, siempre se puede utilizar de forma segura .c_str(), pero la gente a veces no, porque:

  • hay una ligera posibilidad de que su string ejecución tendrá que hacer algo de memoria extra de asignación y/o la copia de datos a fin de preparar la NUL terminado de búfer (sugerencia: cuidado con los prematuro de optimización)
  • utilizando .data() se comunica a otros programadores que lean el código fuente que los datos no ASCIIZ (más bien, estás usando la cadena para almacenar un bloque de datos (que a veces ni siquiera es realmente textual)), o de que estamos pasando a otra función que la trata como un bloque de "binario" de datos. Esto puede ser una visión crucial en asegurar que otros programadores el código de los cambios continúan a manejar correctamente los datos.

Como otra sugerencia, si una función de los parámetros requieren de la (const) char* pero no insista en obtener x.size(), la función probablemente necesita .c_str() (la función de necesidades para saber donde esta el texto termina de alguna manera, así que si no es independiente del parámetro sólo puede ser una convención como un prefijo de longitud o de centinela, o algunos fijos espera de longitud).

Cómo obtener un puntero de carácter válido incluso después de x hojas ámbito o modificar aún más

Tendrás que copiar el contenido de la string x a una nueva área de memoria fuera x. Este externa de búfer que podría estar en muchos lugares como otra string o matriz de caracteres de la variable, que puede o no puede tener una duración diferente de x debido a que están en un ámbito diferente (por ej. espacio de nombres global, la estática, la pila, memoria compartida, archivo asignado en memoria).

Para copiar el texto de std::string x a un independiente matriz de caracteres:

 // EL USO DE OTRA CADENA - AUTO GESTIÓN DE LA MEMORIA, A EXCEPCIÓN SEGURO
 std::string old_x = x;
 // - old_x no se verán afectados por las modificaciones posteriores de x...
 // - se puede utilizar `&old_x[0]` para conseguir una escritura char* old_x del contenido textual
 // - se puede utilizar resize() para reducir/ampliar la cadena de
 // - cambio de tamaño no es posible desde dentro de una función pasa solamente a los char* dirección

 std::string old_x = x.c_str(); // old_x va a terminar antes de tiempo si x incrusta NUL
 // Copia ASCIIZ de datos, pero podría ser menos eficaz a medida que se necesita para escanear la memoria
 // encontrar el NULO terminador de lo que indica la longitud de la cadena antes de asignar esa cantidad
 // de memoria para copiar en, o más eficiente si termina por asignar, copiar un
 // mucho menos el contenido.
 // Por ejemplo, x == "ab\0cd" -> old_x == "ab".

 // UTILIZANDO UN VECTOR DE CHAR - AUTO, A EXCEPCIÓN DE CAJA FUERTE, LAS SUGERENCIAS AL CONTENIDO BINARIO, GARANTIZADO CONTIGUOS INCLUSO EN C++03
 std::vector old_x(x.data(), x.size()); // sin NUL
 std::vector old_x(x.c_str(), x.size() + 1); // con el NUL

 // USO de la PILA, DONDE el TAMAÑO MÁXIMO DE x ES CONOCIDO por SER CONSTANTE en TIEMPO de COMPILACIÓN "N"
 // (un poco peligroso, ya que "conoce" las cosas son a veces mal y a menudo se convierten mal)
 char s[N + 1];
 strcpy(s, x.c_str());

 // USO de la PILA DONDE INESPERADAMENTE LARGO x ES TRUNCADO (p. ej. Hola\0->Hel\0)
 char s[N + 1];
 strncpy(y, x.c_str(), N); // copiar en la mayoría de N, zero-padding si es más corta
 y[N] = '\0'; // asegurarse de NUL terminado

 // El USO de LA PILA PARA MANEJAR x DE DESCONOCIDO (PERO SANA) de LONGITUD
 char* y = ubica(x.size() + 1);
 strcpy(s, x.c_str());

 // El USO de LA PILA PARA MANEJAR x DE LONGITUD DESCONOCIDA (NO ESTÁNDAR GCC EXTENSIÓN)
 char s[x.size() + 1];
 strcpy(s, x.c_str());

 // El USO de las nuevas/borrar la MEMORIA HEAP, MANUAL de DEALLOC, NO INHERENTES a EXCEPCIÓN de SEGURIDAD
 char* s = new char[x.size() + 1];
 strcpy(s, x.c_str());
 // o como un one-liner: char* y = strcpy(new char[x.size() + 1], x.c_str());
 // uso y...
 delete[] y; // asegúrese de que no hay rotura, de retorno, de tiro o de ramificación omite este

 // El USO de las nuevas/borrar la MEMORIA HEAP, PUNTERO INTELIGENTE DESASIGNACIÓN, EXCEPCIÓN SEGURO
 ver impulsar shared_array uso en Johannes Schaub la respuesta

 // El USO de malloc/free MONTÓN de MEMORIA, MANUAL DEALLOC, NO INHERENTES a EXCEPCIÓN de SEGURIDAD
 char* y = strdup(x.c_str());
 // uso y...
gratis(y);

Otras razones para querer un `char*` o `const char*` generado a partir de una `cadena`

Así que, anteriormente hemos visto cómo conseguir un (const) char*, y de cómo realizar una copia de los de texto independiente de la original string, pero ¿qué se puede hacer con ella? Un azar puñado de ejemplos...

  • dar "C" de acceso a código C++ string's de texto, como en printf("x is '%s'", x.c_str());
  • copia x's de texto en un buffer especificado por la función de llamada (por ej. strncpy(callers_buffer, callers_buffer_size, x.c_str())), o memoria volátil utilizado para e/S de dispositivo (p. ej. for (const char* p = x.c_str(); *p; ++p) *p_device = *p;)
  • anexar x's de texto a una matriz de caracteres ya que contiene algunos ASCIIZ de texto (por ej. strcat(other_buffer, x.c_str())) - tener cuidado de no desbordar el búfer (en muchas situaciones en las que usted puede necesitar usar strncat)
  • devolución de un const char* o char* de una función (tal vez por razones históricas - del cliente utilizando la API - o para C compatibilidad usted no quiere devolver un std::string, pero no queremos copiar su string's de datos en algún lugar de la llamada)
    • tenga cuidado de no devolver un puntero que puede anular la referencia por el autor de la llamada después de un local string variable a la que que el puntero apunta ha dejado alcance
    • algunos de los proyectos con objetos compartidos compilado/vinculado para diferentes std::string implementaciones (por ej. STLport y compilador nativo) pueden pasar datos ASCIIZ para evitar conflictos

33voto

Mark Ransom Puntos 132545

El uso de la .c_str() método para const char *.

Usted puede utilizar &mystring[0] para obtener un char * puntero, pero hay un par de gotcha: no necesariamente tener una cadena terminada en cero, y usted no será capaz de cambiar la cadena del tamaño. Especialmente ha de tener cuidado de no añadir caracteres al final de la cadena o te convertirás en un desbordamiento de búfer (y probable caída).

No había ninguna garantía de que todos los personajes podrían ser parte de la misma contiguos de búfer hasta que C++11, pero en la práctica todos los conocidos de las implementaciones de std::string trabajado de esa manera, de todas maneras, a ver que Hace "&s[0]" punto de caracteres contiguos en un std::string?.

Tenga en cuenta que muchas string funciones de miembro de reasigne el buffer interno y anular cualquier punteros que podría haber salvado. Mejor manera de utilizarlos de inmediato y luego descartar.

9voto

Alessandro Teruzzi Puntos 1860

Estoy trabajando con una API con un montón de funciones get como entrada un char *.

He creado una pequeña clase para enfrentar este tipo de problema, he implementado el 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_; }
};

Y se puede utilizar 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

He llamado a la clase DeepString porque está creando una copia profunda y única (el DeepString no es copiables) de una cadena existente.

7voto

DamnDev Puntos 161

Ver esto:

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

Sin embargo, tenga en cuenta que esto volverá a const char * .Para un ' char *', utilice strcpy para copiarlo en otra matriz char.

Iteramos.com

Iteramos es una comunidad de desarrolladores que busca expandir el conocimiento de la programación mas allá del inglés.
Tenemos una gran cantidad de contenido, y también puedes hacer tus propias preguntas o resolver las de los demás.

Powered by: