[C con Clase] problema con puntero

Steven Richard Davidson stevenrichard.davidson en gmail.com
Mar Ago 28 22:48:38 CEST 2007


Hola Duna,

On 8/28/07, duna.montero en ldasistencia.com <duna.montero en ldasistencia.com> wrote:
>
> Hola.
> Tengo un problema con un puntero.
> El programa acepta una cadena de caracteres que no sé en un principio el
> número que tiene.
> He programado esto, pero se queda basura después del ;, que debería ser el
> último caracter.
> Os pongo el código a ver si a alguien se le ocurre algo.
> Muchas gracias.
>

Veamos el código fuente.

>
> int main()
> {
>
>         //char consulta [256];
>         int a=0, numero, i;
>         char * caux, * consulta;
>
>
>
>   do
>   {
>
>                 printf ("\n\nEscriba la consulta \n\n");
>
>                         caux= (char *) malloc (sizeof (char));

Aquí, adjudicas memoria para un solo carácter. En la práctica, esto no
te dará buenos resultados.

>                         gets (caux);

Esto no es aconsejable. En primer lugar, 'gets()' no toma en cuenta la
cantidad máxima del array. Por esta razón, usa 'fgets()'. En segundo
lugar, 'caux' sólo contiene un carácter, que en la práctica no te
servirá para almacenar una cadena de caracteres.

>                         numero=strlen (caux);
>                         printf ("%d", numero);
>
>                         consulta = (char*) malloc (numero*(sizeof (char)));

No es necesario aaveriguar la cantidad de bytes que ocupa un 'char',
ya que siempre será 1 byte.

>
>                         for (i=0; i<numero; i++)
>                         {
>                                 consulta[i]=caux[i];
>                         }

Ten presente que 'strlen()' sólo cuenta los caracteres hasta el primer
carácter nulo, '\0'. Por lo tanto, en este algoritmo debes copiar el
carácter nulo también o al menos asignarlo después de la cadena. Por
ejemplo,

for( i=0; i<=numero; i++ )
  consulta[i] = caux[i];

O incluso,
for( i=0; i<numero; i++ )
  consulta[i] = caux[i];

consulta[numero] = 0;


Si sólo quieres copiar caracteres de una cadena a otra, entonces
sugiero usar 'strcpy()' o incluso 'strncpy()'.

>
>
>                         printf ("\n%s\n", consulta);
>
>                 a = siok (consulta);
>
>                 if (a==0)
>                 {
>                         printf ("\nLa consulta descrita no es correcta\n");
>                         getch();
>                 }
>                 free(consulta);
>                 free (caux);
>                 fflush (stdin);

Este comportamiento no es estándar. Es posible que lo anterior
funcione, pero depende de las bibliotecas que se usen.

>
>
>   }while (a==0);
>
>
> Meto esto y me da el resultado siguiente:
>
>
>
> Escriba la consulta
>
> select * from libros where cl = 123;
> 36
> select * from libros where cl = 123;½½½½½½½½¯■¯■
>

Esto tiene que ver con que el array 'consulta' no contiene el carácter
nulo al final de la información: la cadena en sí.


Viendo el programa que nos muestras, debo recomendarte repasar el tema
de cadenas de caracteres y arrays en general. Siempre debe haber un
carácter nulo al final de la información para describir una cadena de
caracteres.

Para hacer lo que pretendes, en C, tendrías que ir cambiando el tamaño
del array para ajustarse a los nuevos caracteres ingresados. Un
esquema de la lógica sería más o menos el siguiente,

1.  Mientras que no sea el final, hacer:
2.    Leer y extraer el siguiente carácter del canal de entrada (teclado).
3.    Redimensionar el array para aceptar un elemento más.
4.    Asignar el carácter leído al último índice del array.
5.  Terminar

Tenemos que asegurarnos que el último carácter de la cadena debe ser
el carácter nulo.

Incrementando el tamaño de la cadena uno a uno es algo costoso, pero
al menos es seguro y directo en su implementación. La lógica para
hacer esto es la siguiente:

1.  pNuevo <- Crear_Memoria( tamaño+1 )
2.  tamaño <- tamaño+1
3.  Copiar_Elementos( pNuevo, pOriginal )  // copiar de 'pOriginal' a 'pNuevo'
4.  Liberar_Memoria( pOriginal )
5.  pOriginal <- pNuevo   // el puntero 'pOriginal' apunta a 'pNuevo'
6.  Terminar.

Como puedes ver, hay que hacer varias operaciones para "redimensionar"
un array. Si además tenemos que hacer esto repetidamente, entonces
estamos haciendo muchas operaciones elevando el coste total del
algoritmo.


Espero haber aclarado las dudas.

Steven


Más información sobre la lista de distribución Cconclase