Foro de elhacker.net

Programación => Programación C/C++ => Mensaje iniciado por: soyloqbuskas en 30 Enero 2012, 13:26 pm



Título: Array de punteros.
Publicado por: soyloqbuskas en 30 Enero 2012, 13:26 pm
¡Buenas a todos!
Necesito hacer la siguiente funcion:
Código:
char **parser_orden(const char *orden) {}


Esta funcion a la que se le pasa una cadena de caracteres, retorna un array de punteros el cual tiene en cada posicion del array un puntero a cada palabra de la cadena que se le pasa por referencia.

Para crear esta funcion me he hecho un programa a parte para ponerlo a prueba, y esto es lo que tengo escrito:

Código:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main (){
     
     char *orden;
     char **aux[10];
     char aux1[50];
     int i=0;  //indica la posicion de un caracter en la variable orden
     int j=0;  //indica la posicion en la cual hay un puntero a una palabra
     int k=0;  //indica la posicion de un caracter en la variable auxiliar aux1
     
     printf("Escribe una cadena de caracteres\n");
     gets(orden);     

     for(i=0;i<=strlen(orden);i++){
         aux1[k]=(char)orden[i];
         k++;
         if((orden[i]==' ')||(orden[i]=='\0')){
            aux[j]=(char **)aux1; //se que mi fallo esta aqui...
            printf("%i\n",j);         
            k=0;
            j++;       
         }
     }
     printf("1: %s\n",aux[0]);
     printf("2: %s\n",aux[1]);         
     system("pause");
     return 0;   
}

Teoricamente, si escribieramos 2 palabras ("hola mundo"), la salida deberia ser:
hola
mundo

Pero no es asi, porque aux[0] y aux[1], apunta al mismo valor.....

¿como puedo rellenar mi array char**aux[10] con punteros a cada una de las palabras de char*orden?

Gracias, un saludo.


Título: Re: Array de punteros.
Publicado por: soyloqbuskas en 30 Enero 2012, 15:17 pm
Bueno, ya se me a ocurrido como hacerlo....mas o menos....
La idea es usar malloc() y poner algo como....
Código:
aux[j]=malloc(strlen(aux1));

De esta menera rellena mi array con punteros a variables. Lo unico que me queda saber es....¿Como puedo copiar el valor al que apunta aux1, al valor que apunta aux[j]?
Es decir, dados 2 punteros que apuntan a distintas posiciones, ¿como puedo hacer que los valores a los que apuntan sean iguales sin cambiar las direcciones a las que apuntan?



Título: Re: Array de punteros.
Publicado por: rir3760 en 30 Enero 2012, 15:47 pm
Ese programa tiene varios errores. Lo primero es evitar el uso de la función "gets", mas información en el tema |Lo que no hay que hacer en C/C++. Nivel basico| (http://foro.elhacker.net/programacion_cc/lo_que_no_hay_que_hacer_en_cc_nivel_basico-t277729.0.html).

Si apenas empiezas con el tema de punteros deberías conseguir un buen libro sobre el tema, uno muy bueno pero en ingles y algo caro es:

Pointers on C, 1st edition
Kenneth Reek
Addison Wesley
ISBN: 0673999866

Es un libro enfocado en C estándar (C90) con especial énfasis en el tema de manejo de direcciones de memoria (punteros). Comparado con K&R2 lo bueno es que tiene explicaciones mas detalladas (incluyendo gráficas), lo malo es que su selección de ejemplos no es tan buena como el mencionado.

El primer error importante es utilizar la variable "orden" sin darle un valor antes. Debido a que su valor inicial (a falta de uno) es no definido o "basura" no lo puedes utilizar (debes utilizar antes malloc o bien cambiar su uso por un array).

También hay que utilizar nombres claros y descriptivos, por ejemplo para encontrar el uso (y diferencias) entre "aux" y "aux1" hay que revisar en detalle el programa. Mejor acostúmbrate desde ahora.

Tampoco puedes utilizar esto:
Código
  1. printf("1: %s\n", aux[0]);
  2. printf("2: %s\n", aux[1]);
Porque los objetos "aux[N]" son de tipo "char **" mientras que printf espera un "char *".

Si entiendo correctamente buscas obtener las direcciones de cada una de las palabras. Para ello hay varias formas como utilizar strcspn + strspn, sscanf, etc.

Un ejemplo utilizando el par strcspn + strspn:
Código
  1. #include <stdio.h>
  2. #include <stdlib.h>
  3. #include <string.h>
  4.  
  5. int main(void)
  6. {
  7.   char linea[] = "    Esta  es  la  cadena  de  prueba    ";
  8.   char *palabra[100]; /* O algun valor apropiado */
  9.   int longitud[100]; /* O algun valor apropiado */
  10.   int num_palabras;
  11.  
  12.   char *p;
  13.   int i;
  14.  
  15.   p = linea;
  16.   num_palabras = 0;
  17.   i = strspn(p, " ");
  18.   while (p[i] != '\0'){
  19.      /* Almacenamos la direccion de la palabra */
  20.      p += i;
  21.      palabra[num_palabras] = p;
  22.  
  23.      /* Obtenemos su longitud */
  24.      longitud[num_palabras] = strcspn(p, " ");
  25.  
  26.      /* Actualizamos los contadores */
  27.      p += longitud[num_palabras];
  28.      num_palabras++;
  29.  
  30.      /* Pasamos a la siguiente ... */
  31.      i = strspn(p, " ");
  32.   }
  33.  
  34.   for (i = 0; i < num_palabras; i++)
  35.      printf("palabra[%d] == \"%.*s\"\n", i, longitud[i], palabra[i]);
  36.  
  37.   return EXIT_SUCCESS;
  38. }

----

Edito:

Otra opción es mediante la función sscanf utilizando el especificador "%n" el cual nos da el numero de caracteres coincidentes hasta el momento:
Código
  1. #include <stdio.h>
  2. #include <stdlib.h>
  3.  
  4. int main(void)
  5. {
  6.   char linea[] = "    Esta  es  la  cadena  de  prueba    ";
  7.   char *palabra[100]; /* O algun valor apropiado */
  8.   int longitud[100]; /* O algun valor apropiado */
  9.   int num_palabras;
  10.   int i;
  11.  
  12.   char *p;
  13.   char aux[100];
  14.   int num_chars;
  15.   int num_spc;
  16.  
  17.   p = linea;
  18.   num_palabras = 0;
  19.   while (sscanf(p, " %n%s%n", &num_spc, aux, &num_chars) == 1){
  20.      /* Almacenamos la direccion de la palabra */
  21.      palabra[num_palabras] = p + num_spc;
  22.      longitud[num_palabras] = num_chars - num_spc;
  23.      num_palabras++;
  24.  
  25.      /* Pasamos a la siguiente ... */
  26.      p += num_chars;
  27.   }
  28.  
  29.   for (i = 0; i < num_palabras; i++)
  30.      printf("palabra[%d] == \"%.*s\"\n", i, longitud[i], palabra[i]);
  31.  
  32.   return EXIT_SUCCESS;
  33. }

Un detalle: funciona correctamente con GCC 3.x pero, por alguna extraña razón, no da los resultados correctos con Lcc-Win32 (debería darlos ya que hasta donde revise la documentación el comportamiento debe ser el esperado).

Un saludo


Título: Re: Array de punteros.
Publicado por: soyloqbuskas en 30 Enero 2012, 20:28 pm
¡Muchas gracias rir3760!

Citar
El primer error importante es utilizar la variable "orden" sin darle un valor antes. Debido a que su valor inicial (a falta de uno) es no definido o "basura" no lo puedes utilizar (debes utilizar antes malloc o bien cambiar su uso por un array).

También hay que utilizar nombres claros y descriptivos, por ejemplo para encontrar el uso (y diferencias) entre "aux" y "aux1" hay que revisar en detalle el programa. Mejor acostúmbrate desde ahora.

http://foro.elhacker.net/programacion_cc/array_de_punteros-t352112.0.html#ixzz1kyGoKDyW


Como ya dije al principio solo un programa de prueba, no le di mucha importacia a los nombres de las variables y demas...

Citar
Para crear esta funcion me he hecho un programa a parte para ponerlo a prueba, y esto es lo que tengo escrito:

Yo es que vengo de programar en lenguajes bastantes mas estrictos que C, y por eso me hago un lio con los punteros y punteros dobles, etc.

Asi que muchas gracias por tu ayuda, un saludo.