Problema con Malloc y cadenas de tamaño variable.

Iniciado por samur88, 22 Noviembre 2010, 12:58 PM

0 Miembros y 1 Visitante están viendo este tema.

samur88

Hola. Saludos a todos.

Tengo un problema a la hora de entender malloc, el caso es que quiero un array que cada elemento almacene cadenas de dimension variable.
En principio tengo:


char nombre[2];
nombre[0] = (char *)malloc(sizeof(char));


Supuestamente esto me funciona, es decir, yo puedo usar scanf y almacenar una cadena del tamaño que yo quiera en nombre[0], pero el caso es que creo que la asignación de memoria esta mal, es decir, yo estoy reservando memoria para lo que ocupa un carácter, es decir un byte, por lo tanto no me tendría que dejar almacenar mas de un bye, al menos que este machando la memoria a partir de la posición de asignación de dicho byte, por eso quería saber si este código es correcto.
Es decir, si de esta forma yo estoy reservando memoria para una cadena de tamaño variable en nombre[0].

Un Saludo.

Akai

#1
Tal como asumes, esa asignación está mal. Estás asignando en un char un puntero a char. De hecho el compilador debería darte un error como mínimo.

Para lo que tu quieres hacer, primero necesitas un puntero a puntero a char, o también visto como un vector de cadenas.

char **nombre;
nombre= nombre=(char**)malloc(n*sizeof(char*)); //n=numero de cadenas
//luego, para cada cadena:
nombre[i]=(char*)malloc(n*sizeof(char)); // n= numero de caracteres en la cadena


o

char nombre[tam1][tam2] En esta opción el tamaño de la matriz de carácteres / vector de cadenas se define en tiempo de compilación.

En ambos casos, el uso sería el mismo, como si de una matriz se tratase

PD: Es posible que en el código usando malloc pueda haber alguna incorrección, hace tiempo que no lo uso.

Edit: gracias por la corrección, Eternal Idol.

samur88

Muchísimas gracias por la respuesta Akai pero tengo un problema, mi idea es que yo "n" no lo conozco hasta que no inserto la cadena, necesito que se asigne el tamaño en tiempo de ejecución del programa, así que si el usuario inserta 5 caracteres la cadena tenga un tamaño de 5 bytes en la memoria.

¿Como puedo hacer eso?
Un saludo y gracias de nuevo.

Eternal Idol

#3
Podes usar una variable temporal donde leer la cadena:


char tmp[80];
fgets(tmp, sizeof(tmp), stdin);


Despues solo tenes que usar strlen para saber el tamaño (no te olvides de reservar memoria para el 0 terminador de cadena) y copiar.


PD. Al reservar los punteros a cadena se tiene que usar el sizeof de char* y no de char para obtener el tamaño.
La economía nunca ha sido libre: o la controla el Estado en beneficio del Pueblo o lo hacen los grandes consorcios en perjuicio de éste.
Juan Domingo Perón

samur88

Gracias Eternal Idol pero mi problema sigue estando ahí, yo no quiero que la variable temporal sea de 80 caracteres como máximo, ya que no se cuanto se puede introducir, podrían ser mas o menos, me gustaría poder pasarle el valor de caracteres a la cadena en tiempo de ejecución.
Saludos.

Eternal Idol

No, no hay ningun problema, en todo caso se truncaria pero 80 es un tamaño mas que suficiente para practicamente cualquier cosa, si te parece insuficiente siempre podes reemplazar el 80 por 32768 por ejemplo.
La economía nunca ha sido libre: o la controla el Estado en beneficio del Pueblo o lo hacen los grandes consorcios en perjuicio de éste.
Juan Domingo Perón

samur88

Pero si lo reemplazo por eso, ¿no estaría desperdiciando memoria en el momento de capturar la cadena en tmp?

Sigo teniendo la curiosidad de hacer ese 80, ponerle en vez de un numero una variable y sacar cuando caracteres he introducido por teclado, eso lo puedo hacer, usando los flujos o algo así?
Un saludo y muchísimas gracias.

Eternal Idol

#7
Si pones el codigo en una funcion al salir de la misma todo esa memoria vuelve a estar disponible. ¿Estas tratando de entender malloc o tenes requisitos de un hardware con infima memoria?

No hay forma de saber el tamaño de la cadena ANTES de que el usuario la escriba, salvo que tambien tenga que escribir el tamaño de la misma ...
La economía nunca ha sido libre: o la controla el Estado en beneficio del Pueblo o lo hacen los grandes consorcios en perjuicio de éste.
Juan Domingo Perón

samur88

Muchas gracias Eternal Idol, en realidad no quiero decir antes, si no una vez que la ha ingresado, yo es que ahora mismo no estoy muy puesto en memoria dinamica, pero podría hacerse algo asi:

Sería coger y poner un tamaño mínimo de un byte, si la cadena no entra en ese tamaño entonces con realloc se asigna un nuevo de tamaño de los mismos byte que la cadena.

Un saludo.

Eternal Idol

¿Que la ha ingresado en donde? Para poder ingresarla se necesita minimo el tamaño exacto de la cadena ya reservado (incluyendo el 0 terminador). ¿Como sabes si la cadena no entra? Si es tratando de ingresar los datos en esa cadena para la que reservas un caracter (el 0 terminador en realidad) usando fgets correctamente no tendras nunca nada en la cadena, usando algun metodo inseguro accederas a memoria no reservada ...
La economía nunca ha sido libre: o la controla el Estado en beneficio del Pueblo o lo hacen los grandes consorcios en perjuicio de éste.
Juan Domingo Perón