str c_str array c++ string char

c++ - c_str - string to char c#



C++: ¿"my text" es std:: string, a*char o c-string? (8)

Acabo de hacer lo que parece ser un error común de principiante :

Primero leemos uno de muchos tutoriales que dice así:

#include <fstream> int main() { using namespace std; ifstream inf("file.txt"); // (...) }

En segundo lugar, tratamos de usar algo similar en nuestro código, que dice algo como esto:

#include <fstream> int main() { using namespace std; std::string file = "file.txt"; // Or get the name of the file // from a function that returns std::string. ifstream inf(file); // (...) }

En tercer lugar, el desarrollador novato está perplejo por algún mensaje de error del compilador críptico.

El problema es que ifstream toma const * char como un argumento constructor.

La solución es convertir std :: string en const * char .

Ahora, el verdadero problema es que, para un novato, "file.txt" o ejemplos similares dados en casi todos los tutoriales se parecen mucho a std :: string.

Entonces, ¿"my text" es std :: string, c-string o a * char, o depende del contexto?

¿Puedes dar ejemplos sobre cómo "mi texto" se interpretaría de manera diferente según el contexto?

[Editar: Pensé que el ejemplo anterior lo habría hecho obvio, pero debería haber sido más explícito, sin embargo: lo que quiero decir es el tipo de cadena entre dobles comillas, es decir, "myfilename.txt", no el significado de la palabra ''cuerda''.]

Gracias.


Ni C ni C ++ tienen un tipo de datos de cadena integrado.

Cuando el compilador encuentra, durante la compilación, se hace referencia implícita a las cadenas de comillas dobles (vea el código a continuación), la cadena misma se almacena en el código / texto del programa y genera código para crear una matriz de caracteres pares:

  • La matriz se crea en almacenamiento estático porque debe seguir siendo referida más tarde.
  • La matriz se hace constante porque siempre debe contener los datos originales (Hola).

Por lo tanto, al final, lo que tienes es const char * a esta matriz constante de caracteres estáticos.

const char* v() { char* text = “Hello”; return text; // Above code can be reduced to: // return “Hello”; }

Durante la ejecución del programa, cuando el control encuentra un corchete de apertura, crea "texto", el puntero char * en la pila y matriz constante de 6 elementos (incluido el terminador nulo ''/ 0'' al final) en el área de memoria estática. Cuando el control encuentra la siguiente línea (char * text = "Hello";), la dirección de inicio de la matriz de 6 elementos se asigna a "texto". En la siguiente línea (texto de retorno;), devuelve "texto". Con el corchete de cierre "texto" desaparecerá de la pila, pero la matriz todavía está en el área de memoria estática.

No necesita hacer const tipo de retorno. Pero si intentas cambiar el valor en la matriz estática usando char * no constante, igual te dará un error durante el tiempo de ejecución porque la matriz es constante. Por lo tanto, siempre es bueno hacer que el retorno sea constante para asegurarse de que no pueda ser referido por un puntero que no sea constante.

Pero si el compilador encuentra cadenas de comillas dobles explícitamente referidas como una matriz, el compilador supone que el programador las manejará (inteligentemente). Vea el siguiente ejemplo incorrecto:

const char* v() { char text[] = “Hello”; return text; }

Durante la compilación, el compilador comprueba el texto entre comillas y lo guarda como está en el código para completar el conjunto generado durante el tiempo de ejecución. Además, calcula el tamaño de la matriz, en este caso nuevamente como 6.

Durante la ejecución del programa, con el corchete abierto, la matriz "text []" con 6 elementos se crea en la pila. Pero no hay inicialización. Cuando el código encuentra (char texto [] = "Hola";), la matriz se inicializa (con el texto en código compilado). Entonces la matriz está ahora en la pila. Cuando el compilador encuentra (devolver texto;), devuelve la dirección de inicio de la matriz "texto". Cuando el compilador encuentra el corchete de cierre, la matriz desaparece de la pila. Así que no hay forma de referirlo por el puntero de retorno.

La mayoría de las funciones de biblioteca estándar aún toman solo los parámetros char * (o const char *).

La biblioteca estándar de C ++ tiene una poderosa clase llamada cadena para manipular texto. La estructura de datos interna para cadena es matrices de caracteres. La clase de cadena Standard C ++ está diseñada para encargarse (y ocultar) todas las manipulaciones de bajo nivel de las matrices de caracteres que anteriormente se requerían del programador C. Tenga en cuenta que std :: string es una clase:

  • Puede convertir implícitamente un char * en std :: string porque este último tiene un constructor para hacer eso.
  • Puede convertir explícitamente una std :: cadena en una const char * utilizando el método c_str ().

Entonces, ¿"string" es std::string , c-string o char* , o depende del contexto?

Depende completamente del contexto. :-) Bienvenido a C ++.

La cadena de CA es una cadena terminada en nulo, que casi siempre es lo mismo que un char* .

Dependiendo de las plataformas y los marcos que esté utilizando, puede haber aún más significados de la palabra "cadena" (por ejemplo, también se utiliza para referirse a QString en Qt o CString en MFC).


Entonces, ¿"string" es std :: string, c-string o a * char, o depende del contexto?

  • Ni C ni C ++ tienen un tipo de datos de cadena integrado, por lo que cualquier cadena de comillas dobles en su código es esencialmente const char * (o const char [] para ser exactos). "Cadena C" generalmente se refiere a esto, específicamente una matriz de caracteres con un terminador nulo.
  • En C ++, std::string es una clase de conveniencia que envuelve una cadena sin formato en un objeto. Al usar esto, puede evitar tener que hacer (desordenado) operaciones aritméticas de punteros y de memoria por su cuenta.
  • La mayoría de las funciones de biblioteca estándar aún toman solo los parámetros char * (o const char * ).
  • Puede convertir implícitamente un char * en std::string porque este último tiene un constructor para hacer eso.
  • Debe convertir explícitamente una std::string en un const char * utilizando el método c_str() .

Gracias a Clark Gaebel por señalar constness, y a jalf y a GMan por mencionar que en realidad es una matriz.


Con la mayor frecuencia posible, esto debería significar std::string (o una alternativa como wxString , QString , etc., si está utilizando un marco que lo proporciona. A veces no tiene otra opción que utilizar una secuencia de bytes terminada en NUL) , pero generalmente quiere evitarlo cuando sea posible.

En última instancia, simplemente no hay una terminología clara e inequívoca. Así es la vida.


La biblioteca estándar de C ++ proporciona una clase std :: string para administrar y representar secuencias de caracteres. Encapsula la administración de memoria y la mayoría de las veces se implementa como una cadena C; pero ese es un detalle de implementación. También proporciona rutinas de manipulación para tareas comunes.

El tipo std :: string siempre será ese (no tiene un operador de conversión a char * por ejemplo, es por eso que tiene el método c_str ()), pero puede inicializarse o asignarse mediante una C-string ( carbonizarse*).

Por otro lado, si tiene una función que toma std :: string o const std :: string & como parámetro, puede pasar un c-string (char *) a esa función y el compilador construirá un std: : cadena en el lugar para ti. Esa sería una interpretación diferente según el contexto como lo pones.


Para usar la redacción correcta (como se encuentra en el estándar de lenguaje C ++) string es una de las variedades de std :: basic_string (incluyendo std :: string) del capítulo 21.3 "Clases de cadenas" (como en C ++ 0x N3092), mientras que el argumento del constructor de ifstream es NTBS (secuencia de bytes terminada en cero)

Para citar, C ++ 0x N3092 27.9.1.4/2.

basic_filebuf * open (const char * s, ios_base :: openmode mode);

...

abre un archivo, si es posible, cuyo nombre es NTBS s


"myString" es un literal de cadena, y tiene el tipo const char[9] , una matriz de 9 caracteres constantes. Tenga en cuenta que tiene suficiente espacio para el terminador nulo. Así que "Hi" es un const char[3] , y así sucesivamente.

Esto es casi siempre cierto, sin ambigüedad. Sin embargo, siempre que sea necesario, un const char[9] decaerá en un const char* que apunta a su primer elemento. Y std::string tiene un constructor implícito que acepta un const char* . Entonces, si bien siempre comienza como una matriz de caracteres, puede convertirse en los otros tipos si lo necesita.

Tenga en cuenta que los literales de cadena tienen la propiedad única de que const char[N] también puede degradarse en char* , pero este comportamiento está en desuso. Si intenta modificar la cadena subyacente de esta manera, terminará con un comportamiento indefinido. Simplemente no es una buena idea.


std::string file = "file.txt";

El lado derecho de = contiene un literal de cadena (sin procesar) (es decir, una cadena de bytes con terminación nula). Su tipo efectivo es una array of const char .

The = es un pony complicado aquí: no ocurre ninguna asignación. La clase std::string tiene un constructor que toma un puntero a char como argumento y esto se llama para crear una std::string temporal y esto se usa para copiar-construir (usando el ctor de copia de std::string ) file de objeto de tipo std::string .

Sin embargo, el compilador puede eludir el copiador y directamente crear una instancia del archivo.

Sin embargo, tenga en cuenta que std:string no es lo mismo que una cadena terminada en nulo estilo C. Ni siquiera se requiere que sea terminado en nulo.

ifstream inf("file.txt");

La clase std::ifstream tiene un ctor que toma un const char * y el literal de cadena que se le pasa se desintegra a un puntero al primer elemento de la cadena.

Lo que hay que recordar es esto: std::string proporciona una conversión (casi sin interrupciones) de las cadenas estilo C. Debe buscar la firma de la función para ver si está pasando un const char * o std::string (este último debido a las conversiones implícitas).