Foro de elhacker.net

Programación => Programación C/C++ => Mensaje iniciado por: 1t4h1s4 en 11 Febrero 2013, 00:20 am



Título: Problema con asignación de memoria en puntero de caracteres.
Publicado por: 1t4h1s4 en 11 Febrero 2013, 00:20 am
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  :-[.


Título: Re: Problema con asignación de memoria en puntero de caracteres.
Publicado por: DickGumshoe en 11 Febrero 2013, 01:47 am
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
  1. #include <string.h>
  2. #include <iostream>
  3.  
  4. using namespace std;
  5.  
  6. int main()
  7. {
  8.    char* a = new char[20];
  9.    cout << strlen(a);
  10.  
  11. }
  12.  

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
  1. #include <string.h>
  2. #include <iostream>
  3.  
  4. using namespace std;
  5.  
  6. int main()
  7. {
  8.    char* a = new char[20];
  9.    cout << strlen(a);
  10.    cin >> a;
  11.    cout << strlen(a);
  12. }
  13.  

Un saludo.


Título: Re: Problema con asignación de memoria en puntero de caracteres.
Publicado por: 1t4h1s4 en 11 Febrero 2013, 01:50 am
Gracias, muchas gracias, de verás.  ;) No entendía porque a veces funcionaba y a veces no.


Título: Re: Problema con asignación de memoria en puntero de caracteres.
Publicado por: DickGumshoe en 11 Febrero 2013, 01:52 am
De nada. Por cierto, mientras lo leías edité el mensaje con una explicación de por qué pasa eso, por si quieres saberlo.  ;)


Título: Re: Problema con asignación de memoria en puntero de caracteres.
Publicado por: 1t4h1s4 en 11 Febrero 2013, 02:31 am
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:

Código:
char *a = "hola", *b;

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

Código:
int i = 0;
while (a[i] != NULL)
   i++;

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

Código:
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:

Código:
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:

Código:
b[i+1] = '\0'

pero me falla en ejecución.




Título: Re: Problema con asignación de memoria en puntero de caracteres.
Publicado por: DickGumshoe en 11 Febrero 2013, 02:46 am
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
  1. for (int j = 0; j < i+1; j++)
  2.         b[j] = a[j];

Así quedaría completo:

Código
  1. #include <string.h>
  2. #include <iostream>
  3.  
  4. using namespace std;
  5.  
  6. int main()
  7. {
  8.    char* a = new char[20];
  9.    char *b;
  10.    int i = 0;
  11.    cin >> a;
  12.  
  13.    while (a[i] != '\0')
  14.    i++;
  15.  
  16.    b = new char[i+1];
  17.  
  18.    for (int j = 0; j < i+1; j++)
  19.         b[j] = a[j];
  20.   cout << b;
  21.  
  22. }
  23.  


Título: Re: Problema con asignación de memoria en puntero de caracteres.
Publicado por: 1t4h1s4 en 11 Febrero 2013, 03:13 am
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  ;)


Título: Re: Problema con asignación de memoria en puntero de caracteres.
Publicado por: 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:

Código
  1. string Texto = "Hola mundo";
  2. cout<<Texto<<endl<<Texto.size()<<endl;
  3. Texto = "Reducido"; // Los strings se ajustan automaticamente
  4. 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/


Título: Re: Problema con asignación de memoria en puntero de caracteres.
Publicado por: 0xDani en 11 Febrero 2013, 16:56 pm
@amchacon, estes en C o C++ para aprender nunca viene mal trabajar con arrays.


Título: Re: Problema con asignación de memoria en puntero de caracteres.
Publicado por: 1t4h1s4 en 13 Febrero 2013, 02:58 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í.