str c_str array c++ string char

c++ - c_str - Copiar const char*



string to char c# (8)

¿Por qué lo tiene como const, si necesita cambiarlos en uno de los métodos de la clase.

De todos modos, los miembros de datos de referencia no estáticos y los miembros de datos de referencia no pueden tener valores asignados; debe usar la lista de inicialización con el constructor para inicializarlos.

MyClass::MyClass(const char *_filename) : filename( _filename ) { // filename = _filename; This isn''t going to work }

Un inicializador también puede llamar a una función de la siguiente manera

MyClass::MyClass(const char *_filename) : filename( getfilename() ) { // filename = _filename; This isn''t going to work }

No se verificó este caso particular, que es el más adecuado, pero la lista de inicialización es la forma de asignar valores a los miembros de datos de const no estáticos.

Recibo una cadena de caracteres como parámetro de una función, pero el argumento que recibo se destruirá más tarde. Entonces quiero hacer una copia.

Esto es lo que quiero decir:

class MyClass { private: const char *filename; public: void func (const char *_filename); } void MyClass::func (const char *_filename) { filename = _filename; //This isn''t going to work }

Lo que quiero lograr no es simplemente asignar una dirección de memoria a otra, sino copiar contenidos. Quiero tener un nombre de archivo como "const char *" y no como "char *".

Traté de usar strcpy pero requiere que la cadena de destino sea no const.

¿Hay una forma de evitarlo? Algo sin usar const_cast en el nombre de archivo?

Gracias.


Debe decidir si desea que su nombre de archivo sea const (para que no pueda modificarse) o no const (para que pueda cambiarse en MyClass :: func).


Estoy de acuerdo en que lo mejor (al menos sin saber nada más sobre su problema) es usar std::string . Pero si insiste en administrar la memoria usted mismo, debe gestionarla por completo. Entonces la forma C ++:

class MyClass { private: const char *filename; MyClass(const MyClass&); // no implementation MyClass operator=(const MyClass &); // no implementation public: MyClass() {filename = 0;} ~MyClass() {delete[] filename;} void func (const char *_filename); } void MyClass::func (const char *_filename) { const size_t len = strlen(_filename); char * tmp_filename = new char[len + 1]; strncpy(tmp_filename, _filename, len); tmp_filename[len] = ''/0''; // I''m paranoid, maybe someone has changed something in _filename :-) delete[] filename; filename = tmp_filename; }

y la forma C

class MyClass { private: const char *filename; MyClass(const MyClass&); // no implementation MyClass operator=(const MyClass &); // no implementation public: MyClass() {filename = 0;} ~MyClass() {free(filename);} void func (const char *_filename); } void MyClass::func (const char *_filename) { free(filename); filename = strdup(_filename); // easier than C++, isn''t it? }


Hay una función en la biblioteca Standard C (si desea ir a la ruta C) llamada _strdup. Utiliza malloc para hacer la asignación real, por lo que deberá llamar gratis cuando haya terminado con la cadena.

Así por ejemplo,

void MyClass::func (const char *_filename) { if (filename) { free(filename); } filename = _strdup(_filename); }

Por supuesto, no olvides liberar el nombre de archivo en tu destructor.


Si quieres mantenerte en C simple, usa strncpy. Pero estoy de acuerdo con Ilya, use std :: string ya que es C ++. Si es su aplicación la que está llamando a su método, incluso podría recibir una std :: cadena en primer lugar ya que el argumento original será destruido.


Use std::string para copiar el valor, ya que ya está usando C ++. Si necesita un const char* partir de eso, use c_str() .

class MyClass { private: std::string filename; public: void setFilename(const char *source) { filename = std::string(source); } const char *getRawFileName() const { return filename.c_str(); } }


char const* implica que la clase no posee la memoria asociada a ella. El propietario siempre necesita un puntero que no sea const porque de lo contrario la memoria no podría liberarse. Cuando tiene puntero no const, puede asignar la memoria para ello y luego usar strcpy (o memcpy ) para copiar la cadena. Sin embargo, en su situación, usar std::string es una opción mucho mejor.


[Suponiendo que continúa implementando las partes internas de su clase en el estilo C, lo que puede o no ser beneficioso en términos de desarrollo y velocidad de ejecución (dependiendo del diseño del proyecto completo) pero generalmente no se recomienda a favor de std::string y amigos.]

Torneado

const char *filename;

dentro

char *filename;

no te hará feliz con strcpy , ya que realmente necesitas memoria para una copia de tu cadena :)

Para la parte del código de administración de memoria manual, vea la respuesta de Tadeusz Kopec, que parece tener todo correcto.

Además, tenga en cuenta que hay una diferencia entre

const char *filename; // "filename" points to "const char" // and is not const itself char const *filename; // semantically the same as above

y

char * const filename; // "filename" is const and points to "char", // which is not const

En el primer caso, puede hacer que el filename apunte a cualquier otra cadena const char , en el segundo, solo puede cambiar esa cadena "in situ" (manteniendo el mismo valor de filename del filename , ya que apunta a la misma ubicación de memoria) . Por supuesto, uno puede combinar estos dos (o ninguno de ellos) si es necesario.

PD: si nombra el parámetro _filename la función miembro solo para evitar colisionar los nombres con el filename variable miembro, puede simplemente ponerle un prefijo (y deshacerse del guión bajo):

void MyClass::func (const char *filename) { ... this.filename = copy; }