[C con Clase] Array de cadenas de caracteres y p aso de paráme tros en C.
srd4121 en njit.edu
srd4121 en njit.edu
Dom Dic 14 12:23:00 CET 2008
Hola Carlos,
Mensaje citado por: gmh2000 <helder1986 en gmail.com>:
> Steven, yo no entiendo que Rolando quiera decir que su código es
> incorrecto, sino que se le olvidó reservar memoria para la nueva cadena.
Lo siento, pero el mismo Rolando lo dijo, y cito textualmente:
"Lo único que le veo mal es que estas volviendo a declarar el arreglo PCHAR11*
file_names.string_pointers ahí el PCHAR11* es innecesario."
Ahora bien, releyendo lo que dije, veo que sí puedes pensar que yo estaba
diciendo que el código de Rolando estaba mal, pero no era eso lo que quería
decir. Simplemente, dije lo mismo que Rolando, pero me expresé de otra manera,
acerca de la declaración del campo 'string_pointers' que tú hiciste. Es decir,
deberías haber hecho esto:
PCHAR11 string_pointers;
que viene a ser lo mismo que hacer esto,
char (*string_pointers)[11];
Si declaras 'string_pointers' como un puntero a 'PCHAR11', entonces tienes que
crear memoria para 'string_pointers' al igual que memoria para la lista de
punteros a 'char[11]'. Es decir, tienes un doble puntero a un array
que viene a ser lo siguiente.
PCHAR11 *string_pointers;
es equivalente a:
char (**string_pointers)[11];
Por esta razón, Rolando te dice que es innecesario, porque tienes otro nivel
de indirección que no te sirva para nada excepto "amargarte la vida".
> Si está mal corrígenos, pues yo también lo veo bien para mi caso, en el
> que casi todas las cadenas son de 10 caracteres (más el /0), y ninguna
Si sabes que 11 es la longitud máxima, entonces adelante con esta idea de
crear un array dinámico a un array "estático". La otra posibilidad que te di
era para que tuvieras mayor control acerca de las cantidadesde cada cadena.
> mide más de 10. A partir de ahí reescribo el código comentándolo según
> lo aprendido. Por favor, si tengo algún concepto incorrecto díganmelo.
> Ahí va:
>
>
> typedef char (*PCHAR11)[11];
>
> struct string_list
> {
> PCHAR11* string_pointers;
Como hemos dicho, deberías declarar este campo así:
PCHAR11 string_pointers;
> unsigned int number_of_strings;
> } file_names;
>
>
> ... add_cadena()
> {
>
> /* Ahora necesitamos un "índice" más a la cadena que vamos a añadir.
> Incrementamos memoria para poder almacenar este puntero a cadena de 11
> */
>
> file_names.string_pointers = (PCHAR11*)
> realloc(file_names.string_pointers, ++file_names.number_of_strings *
> sizeof(PCHAR11) );
>
Esto no es correcto. Estamos creando memoria para una lista (como un array) de
cadenas. Esto es,
file_names.string_pointers = (PCHAR11) realloc(file_names.string_pointers,
++file_names.number_of_strings * sizeof(CHAR11) );
He aquí la razón de definir 'CHAR11'.
Si no se trata de un array tan grande, entonces puedes usar esta solución. Eso
sí, ten presente que estás creando un solo bloque de múltiplos de 11 bytes. Es
decir, cada vez que agregas una cadena, el sistema operativo tiene que
encontrar un solo bloque contiguo de 11 bytes más que la cantidad original. Si
quieres expresar lo que ocurre algebraicamente, tenemos esta cantidad total:
11*n, donde 'n' es la cantidad de cadenas
Sé que hoy en día los SS.OO. disponen de mucha memoria, pero intenta tener las
cantidades presentes. La otra ventaja de la solución que te di es que puedes
reducir la cantidad de bloques al crear la memoria dinámicamente, ya que cada
petición de memoria es independiente a las otras. Es más fácil encontrar
bloques de memoria de cantidades pequeñas de cantidades más grandes.
>
> /* Reservamos memoria para la nueva cadena de caracteres, esto es,
> desreferenciamos la antigua dirección de memoria a un espacio que esté
> vacío (lo gestiona el sistema operativo). */
> file_names.string_pointers[file_names.number_of_strings - 1] = (char *)
> malloc(11 * sizeof(char));
>
Esto sería correcto, para la solución que yo te di, pero como estás usando un
puntero a un array, esta sentencia ya no es necesaria.
> /* Nota: no hago tu strlen(szNombre)+1 porque no me vale la pena el
> conste computacional de calcular la longitud vs memoria desperdiciada
> */
>
> /* Ahora sólo quedaría copiar la nueva cadena */
> strcpy(file_names.string_pointers[file_names.number_of_strings - 1],
> "nueva_cadena");
Aconsejo usar 'strncpy()' para no sobrepasar los límites del array de 11
caracteres. Incluso podrías usar 'memcpy()' para copiar 10 caracteres y luego
agregar el carácter nulo al final explícitamente.
>
> }
>
>
> __________
> Haber si eso ya está bien. No lo puedo probar yo mismo en mi compilador
> porque los fines de semana voy para mi pueblo y aquí no tengo el
> tinglado necesario.
>
¿No tenéis ordeñador en el pueblo? :P Lo siento, no pude resistir la
tentación de escribir este chiste tan malo :)
Bueno, espero que lo anterior aclare un poco las cosas.
Steven
Más información sobre la lista de distribución Cconclase