Problema con asignación de memoria en puntero de caracteres.

Iniciado por 1t4h1s4, 11 Febrero 2013, 00:20 AM

0 Miembros y 3 Visitantes están viendo este tema.

1t4h1s4

Esto nunca me había pasado, y creo que me va a explotar la cabeza, porque he hecho esto otras veces y funcionaba perfectamente. Verán quiero hacer algo tan simple y sencillo como:

char* a = new char[20];

Es decir, crear una cadena para almacenar 20 caracteres.

Pues bien, cuando devuelvo el tamaño de mi variable a:

cout << strlen(a);

Me muestra 32!!!! es decir, que no me está creando una cadena de caracteres de la longitud que yo deseo.

¿Cómo es posible? Estoy desesperando, por favor, ayuda  :-[.

DickGumshoe

#1
Hola.

Si reservas memoria pero no pides datos, el programa fallará. Es decir, strlen() no dice el número de caracteres reservados, sino el de caracteres ocupados. Esto es porque strlen() cuenta caracteres hasta que encuentre un '\0'. En tu caso, te dio 32, porque 32 posiciones en memoria más allá de a[0] se encontraba '\0'. A mí me dio en este programa 3 por lo mismo:

Código (cpp) [Seleccionar]

#include <string.h>
#include <iostream>

using namespace std;

int main()
{
   char* a = new char[20];
   cout << strlen(a);
 
}


Depende de lo que se encuentre en memoria en cada ordenador en un momento determinado.

Sin embargo, cuando asignes algo a esa cadena, sí te dará la longitud, porque encontrará el '\0' que has asignado tú, y no lo que haya encontrado el ordenador por casualidad. Así sale bien:

Código (cpp) [Seleccionar]

#include <string.h>
#include <iostream>

using namespace std;

int main()
{
   char* a = new char[20];
   cout << strlen(a);
   cin >> a;
   cout << strlen(a);
}


Un saludo.

1t4h1s4

Gracias, muchas gracias, de verás.  ;) No entendía porque a veces funcionaba y a veces no.

DickGumshoe

De nada. Por cierto, mientras lo leías edité el mensaje con una explicación de por qué pasa eso, por si quieres saberlo.  ;)

1t4h1s4

Ok, muchas gracias  ;)

Aunque una última cosita, si quisiera hacerlo sin la librería string.h y sus métodos, sino crear yo mis propios métodos:

por ejemplo:

char *a = "hola", *b;

para saber la longitud de a se que me vale con lo siguiente:


int i = 0;
while (a[i] != NULL)
   i++;


luego para asignar esa misma longitud a b haría lo siguiente:


b = new char[i+1];
for (int j = 0; j < i; j++)
   b[j] = a[j];


Pero el problema es que si imprimiera b con cout:


cout << b


me aparecería:

holaxxxxxxxxxxx

siendo x basura.

¿Cómo lo solucionaría? ¿No se supone que ya he igualado una cadena a otra?

Sé que con strcpy funciona perfectamente, pero me gustaría saber hacerlo a mi manera.

Intenté esto, marcarle yo el final:


b[i+1] = '\0'


pero me falla en ejecución.



DickGumshoe

El bucle for que has creado debería tener como condición que j < i+1. La variable i representa la posición del último carácter "real" de la cadena, ahí no incluye el '\0'. Si le añades ese 1 también copia el '\0':

Código (cpp) [Seleccionar]
for (int j = 0; j < i+1; j++)
         b[j] = a[j];


Así quedaría completo:

Código (cpp) [Seleccionar]
#include <string.h>
#include <iostream>

using namespace std;

int main()
{
    char* a = new char[20];
    char *b;
    int i = 0;
    cin >> a;
   
    while (a[i] != '\0')
    i++;

    b = new char[i+1];
   
    for (int j = 0; j < i+1; j++)
         b[j] = a[j];
   cout << b;

}

1t4h1s4

#6
Gracias, me has solucionado mis dudas a la perfección  ;-)
Sé que son muy básicas, pero así voy aprendiendo  :-[ así que gracias por tu atención, respuestas y útil solución.
Eternamente agradecida  ;)

amchacon

A todo esto, en C++ ya no se usan los char*. Es mucho más sencillo usar los strings:

Código (cpp) [Seleccionar]
string Texto = "Hola mundo";
cout<<Texto<<endl<<Texto.size()<<endl;
Texto = "Reducido"; // Los strings se ajustan automaticamente
cout<<Texto<<end<<Texto.size();


Te olvidas de reservar memoria con new/delete, el solito se agranda y se reduce conforme lo vayas necesitando... También hay muchas funciones internas para tratar con ellos (buscar, concatenar...)
http://www.cplusplus.com/reference/string/string/
Por favor, no me manden MP con dudas. Usen el foro, gracias.

¡Visita mi programa estrella!

Rar File Missing: Esteganografía en un Rar

0xDani

@amchacon, estes en C o C++ para aprender nunca viene mal trabajar con arrays.
I keep searching for something that I never seem to find, but maybe I won't, because I left it all behind!

I code for $$$
Hago trabajos en C/C++
Contactar por PM

1t4h1s4

Cita de: amchacon en 11 Febrero 2013, 08:27 AM
A todo esto, en C++ ya no se usan los char*. Es mucho más sencillo usar los strings

En este ejercicio concretamente, me pedían que utilizara el char*, no sé por qué, pero bueno, nunca está demás aprender como hacerlo así.