Autor Tema: Uso de punteros como array dinámico para novatos.  (Leído 11694 veces)

Drumpi

  • Hero Member
  • *****
  • Mensajes: 6289
  • Karma: 160
  • Odio el periodo "entre proyectos"
    • La web de Drumpi
Uso de punteros como array dinámico para novatos.
« en: Diciembre 02, 2009, 12:51:50 am »
Usar punteros como array dinámico es sencillo.
¿Que qué es esto? bueno, cuando declaramos un vector, este tiene un tamaño fijo, y más de uno se ha perguntado si no se pueden definir en base a una variable. Pues vamos a aprender cómo hacer uno de estos, y que se pueda cambiar de tamaño en plena ejecución del juego.

Primero debes declarar un puntero, para ello usamos la palabra POINTER seguido del nombre que queramos:

POINTER mi_puntero;

Pero seguramente quieras usar un tipo de datos en cada posición, quizás un BYTE porque no vas a usar más de 256 valores, quizás INT porque vayas a usar números negativos, o incluso un tipo que te hayas creado tu. Para indicárselo a Bennu, hay que añadírselo antes de la palabra POINTER:

int POINTER mi_puntero;

Un ejemplo creando un tipo nuevo llamado coordenadas:

TYPE coordenadas
 INT x,y,z;
END
coordenadas POINTER mi_puntero;

Bien ya tenemos un puntero, pero inicialmente está vacío, no se puede usar. Para ello primero hay que reservar espacio en memoria, cualquiera.

mi_puntero=alloc(5);

Con esto reservamos 5 bytes, lo cual no es correcto para usar INTs, pues cada INT requiere 4 bytes ¿cómo reservar espacio para 5 variables del tipo INT?

mi_puntero=alloc(5*sizeof(INT));

¿Y para 7 variables de tipo coordenadas?

mi_puntero=alloc(7*sizeof(coordenadas));

(Que alguien me corrija si me equivoco, pero creo que con Bennu ya no es necesario especificar el tamaño del tipo de variable ¿o sigue siendo así?)

Bien, ya tenemos un array de X posiciones. Lo bueno de este método es que ahora podemos trabajar con mi_puntero como si fuera un array normal:

INT variable
variable=mi_puntero[3];  //guardamos en "variable" el valor que hubiese en la cuarta posición

coordenadas variable;
variable=mi_puntero[5];  //guardamos en "variable" LOS VALORES de la estructura que hubiese en la sexta posición
mi_puntero[4].x=3; //guardamos 3 en el campo x de la quinta variable.

OJO: cuando trabajamos con punteros, la memoria que reservemos NO SE PONE A CERO, puede valer cualquier valor inicialmente, es importantísimo tenerlo en cuenta.
Supongamos que ahora queremos cambiar el tamaño, no hay problema, usamos REALLOC en lugar de ALLOC:

mi_puntero=REALLOC(mi_puntero, 1100*sizeof(INT));

Esta vez necesitamos indicarle a REALLOC qué puntero queremos redimensionar, y es importante volver a hacer la asignación, porque es muy probable que la zona de memoria haya cambiado de sitio.
Cuando acabemos, es IMPRESCINDIBLE liberar la memoria que no estemos usando, porque puede que esta quede en el sistema como ocupada, aun después de haber cerrado el programa, esto no es Java, amigos ;D Para ello, usamos la función FREE:

FREE(mi_puntero);

Y ya está ¿fácil? pues si, pero peligroso: ya he avisado del peligro de no usar FREE, pero tanto o más es acceder a una zona de memoria que no existe (por ejemplo, a mi_puntero[7000]), porque es muy probable que se nos salga del programa sin dar ningún aviso (quizás un segmentation fault) y la cosa se queda ahí, pero en raras ocasiones puede que no nos diga nada y nos metamos en zonas de memoria que no debemos tocar, CUIDADO.

Para más dudas, acceder a los lugares habituales (el manual de OSK ;D).
Hala, como con 1001 procesos sólo va a 9 FPS, vamos a meterle 32 veces más, a ver si revienta.
(Drumpi epic moment)

DjSonyk

  • Sr. Member
  • ****
  • Mensajes: 492
  • Karma: 24
Re: Uso de punteros como array dinámico para novatos.
« Respuesta #1 en: Diciembre 02, 2009, 12:56:18 am »
Vale,ya veo lo que hacia mal,muchas gracias Drumpi,ahi van 2 karmas uno por todas las molestias y otro por toda la ayuda ;P:

Windgate

  • Hero Member
  • *****
  • Mensajes: 2930
  • Karma: 124
    • TRINIT Asociación de Informáticos de Zaragoza
Re: Uso de punteros como array dinámico para novatos.
« Respuesta #2 en: Diciembre 02, 2009, 02:11:13 am »
Toma tu karma, llevaba tiempo dando vueltas a este tema e incluso tengo por ahí código preparado con un #define para hacer un array dinámico con un tipo de dato "cualquiera" que puede definirse en la sentencia #define.

Me refiero a un módulo que tenga las operaciones básicas de vector:

Nuevo vector
Añadir elemento
Quitar elemento de la posición N
Elimintar vector

Espero que salga material interesante de este hilo, ya me he encontrado con varios casos prácticos que piden a gritos vectores dinámicos, especialmente en juegos de estrategia que es un tema que apenas hemos tocado en el foro :P

Besitos Drumpi :-* xD
Iván García Subero. Programador, profesor de informática, monitor de actividades culturales y presidente de TRINIT Asociación de Informáticos de Zaragoza. http://trinit.es

Windgate

  • Hero Member
  • *****
  • Mensajes: 2930
  • Karma: 124
    • TRINIT Asociación de Informáticos de Zaragoza
Re: Uso de punteros como array dinámico para novatos.
« Respuesta #3 en: Diciembre 02, 2009, 01:55:56 pm »
Bien, ahora he podido leer con más detenimiento, te voy a criticar hasta la humillación (Broma :P):

Citar
(Que alguien me corrija si me equivoco, pero creo que con Bennu ya no es necesario especificar el tamaño del tipo de variable ¿o sigue siendo así?)

sizeof funciona perfectamente, así debería hacerse.

Citar
INT variable
variable=mi_puntero[3];

mi_puntero almacena datos de tipo coordenada, y estás asignando al entero variable un dato de tipo coordenada... ¿No sería más limpio hacer que variable fuese de tipo coordenada también?

Me parece bien el mini-tutorial que has creado, pero definitivamente no me sirve, el coste de realloc a cada vez que el vector cambia de tamaño es muy elevado. Yo lo que busco es una lista enlazada, en la que los nuevos elementos añadidos crean nuevos nodos y los elementos borrados liberan nodos, volviendo a enlazar la lista donde se rompió.

Hace un tiempo empecé con algo así, pero como tantas otras cosas no lo terminé... Supongo que cuando realmente me haga falta retomaré el trabajo.
Iván García Subero. Programador, profesor de informática, monitor de actividades culturales y presidente de TRINIT Asociación de Informáticos de Zaragoza. http://trinit.es

DjSonyk

  • Sr. Member
  • ****
  • Mensajes: 492
  • Karma: 24
Re: Uso de punteros como array dinámico para novatos.
« Respuesta #4 en: Diciembre 02, 2009, 02:29:53 pm »
Wind creo entenderte que lo que quieres es una "Lista aninada",tambien estan las pilas(LIFO) y las colas (FIFO)....
Pero por tus explicaciones entiendo que lo que necesitas es una lista...No creo que sea muy dificil de imprementar yo tengo aun los libros del curso de JAVA que hice y vienen muy bien explicado,viene un ejercicio de prueba cuando tenga unos minutos le porto a Bennu...

Windgate

  • Hero Member
  • *****
  • Mensajes: 2930
  • Karma: 124
    • TRINIT Asociación de Informáticos de Zaragoza
Re: Uso de punteros como array dinámico para novatos.
« Respuesta #5 en: Diciembre 02, 2009, 07:32:58 pm »
Yo también tengo ejemplos por ahí, pero no lo completé en su día porque quería hacerlo con #define para que funcionase con cualquier tipo de dato, especificándolo en el define.

Si te me adelantas te doy mi karmín xD
Iván García Subero. Programador, profesor de informática, monitor de actividades culturales y presidente de TRINIT Asociación de Informáticos de Zaragoza. http://trinit.es

Drumpi

  • Hero Member
  • *****
  • Mensajes: 6289
  • Karma: 160
  • Odio el periodo "entre proyectos"
    • La web de Drumpi
Re: Uso de punteros como array dinámico para novatos.
« Respuesta #6 en: Diciembre 02, 2009, 07:39:23 pm »
Bien, ahora he podido leer con más detenimiento, te voy a criticar hasta la humillación (Broma :P):

Citar
(Que alguien me corrija si me equivoco, pero creo que con Bennu ya no es necesario especificar el tamaño del tipo de variable ¿o sigue siendo así?)

sizeof funciona perfectamente, así debería hacerse.

No, yo lo decía porque era posible que no se necesitase el sizeof, que al decirle "5", Bennu ya reservaba 5 posiciones del tamaño que sea el tipo al que apunta el puntero.

Citar
INT variable
variable=mi_puntero[3];

mi_puntero almacena datos de tipo coordenada, y estás asignando al entero variable un dato de tipo coordenada... ¿No sería más limpio hacer que variable fuese de tipo coordenada también?

No, en ese ejemplo no he dicho el tipo de datos que almacena mi_puntero, quizás debí haber explicado mejor que en este caso hacía referencia al primer ejemplo de todos los que hay en el mini-tuto, o haber usado nombres distintos.
Pero al menos veo que habeis cogido la idea :D

Me parece bien el mini-tutorial que has creado, pero definitivamente no me sirve, el coste de realloc a cada vez que el vector cambia de tamaño es muy elevado. Yo lo que busco es una lista enlazada, en la que los nuevos elementos añadidos crean nuevos nodos y los elementos borrados liberan nodos, volviendo a enlazar la lista donde se rompió.

Hace un tiempo empecé con algo así, pero como tantas otras cosas no lo terminé... Supongo que cuando realmente me haga falta retomaré el trabajo.

El tuto es por una duda que me planteó DjSonyk. Obviamente el uso de realloc se come las últimas posiciones, si lo que quieres es reorganizarlo internamente, te toca crear una lista enlazada. No es complicado, pero si laborioso (menos mal que los tipos definidos pueden ahorrar mucho trabajo de adaptación a otros tipos de nodos si se hace bien).
Si lo veis necesario, y la guia de Osk no os parece suficiente, puedo probar a hacer otro mini-tuto al respecto (y luego, s alguien quiere, pues que los ponga en la wiki, que no me aclaro con su "código").
Hala, como con 1001 procesos sólo va a 9 FPS, vamos a meterle 32 veces más, a ver si revienta.
(Drumpi epic moment)

DjSonyk

  • Sr. Member
  • ****
  • Mensajes: 492
  • Karma: 24
Re: Uso de punteros como array dinámico para novatos.
« Respuesta #7 en: Diciembre 02, 2009, 08:26:49 pm »
Si la duda era mia que no sabia como declarar los punteros,hasta tal punto que escribia aberraciones..... con lo simple que.... ^^

Nada ahora estoy pegandome como pasar los datos de la memoria dinamica a un fichero xD,por ahora tengo una chapuza pero no me gusta...en fins llevo un par de dias que madre de dios hermoso....

Windgate

  • Hero Member
  • *****
  • Mensajes: 2930
  • Karma: 124
    • TRINIT Asociación de Informáticos de Zaragoza
Re: Uso de punteros como array dinámico para novatos.
« Respuesta #8 en: Diciembre 02, 2009, 10:13:30 pm »
DjSonik, ¿No debería valer con un fwrite y el nombre del vector?

Hace poco se dijo en un hilo, que Bennu escribe los datos del vector, sea de 1, 10 o 1000 "celdas" el jodido...
Iván García Subero. Programador, profesor de informática, monitor de actividades culturales y presidente de TRINIT Asociación de Informáticos de Zaragoza. http://trinit.es

DjSonyk

  • Sr. Member
  • ****
  • Mensajes: 492
  • Karma: 24
Re: Uso de punteros como array dinámico para novatos.
« Respuesta #9 en: Diciembre 02, 2009, 10:15:25 pm »
¿No me fastidies que es tan facil?voy aprobar


EDIT : nonono, no lo guarda ,vamos al menos que un array de 64*64*3 ocupe 4 bytes XD,creo que guarda el puntero....Lo que quiero es volcar los datos de la memoria donde tengo guardado los valores a un archivo....Aun asi me gusta muy poco tener Type con 3 valores,estaba mejor como lo tenia antes aunque no se pudiera modificar en ejecucucción, era una strucutura filay y filax ,y ya me guardaba el codido,ahora es &celda[0].x; &celda[0].y; &celda[0].id;
pufff!!!
EDIT 2: Para guardalo uso GuardaX=&celda[n].X;GuardaY=&Celda[n].y;Guardaid=&Celda[n].id;con un bucle y tres fwrite ().....
« última modificación: Diciembre 02, 2009, 10:26:00 pm por DjSonyk »

Drumpi

  • Hero Member
  • *****
  • Mensajes: 6289
  • Karma: 160
  • Odio el periodo "entre proyectos"
    • La web de Drumpi
Re: Uso de punteros como array dinámico para novatos.
« Respuesta #10 en: Diciembre 02, 2009, 11:08:09 pm »
Lo habría escrito hace un par de horas, pero el servidor se puso en modo mantenimiento y me dejó con la palabra en la boca (o con el texto en el portapapeles, más bien ;D)

id_fich=FOPEN("datos.bin",O_WRITE);
FOR (n=0;n<=max_datos;n++)
 FWRITE(id_fich, mi_puntero[n]);
END
FCLOSE(id_fich);

Esto es lo más simple, ahora tu le vas añadiendo toda la complicación que te de la gana ^^U

PD: a tu método creo que le sobra el & de delante, tanto a la hora de escribir le array, como a usar &celda[0].x, el [] ya indica que nos referimos al contenido (como poner * al principio).
« última modificación: Diciembre 02, 2009, 11:11:22 pm por Drumpi »
Hala, como con 1001 procesos sólo va a 9 FPS, vamos a meterle 32 veces más, a ver si revienta.
(Drumpi epic moment)

DjSonyk

  • Sr. Member
  • ****
  • Mensajes: 492
  • Karma: 24
Re: Uso de punteros como array dinámico para novatos.
« Respuesta #11 en: Diciembre 02, 2009, 11:18:40 pm »
 :o
toda la tarde bucando la solución y aparece drumpi.........
aun asi tengo problemas con la carga,asi que no se si de todas formas lo estaba haciendo mal o lo cargo mal....... dios que asquito esto de la memoria dinamica.....y veo que aun sigo sin cojerlo,cuando mas creo a ver entendido como funciona mas cuenta me doy que no se como funciona...menos mal que por ejemplo tenemos el garbage collection y lo hace solito al menos enque maneja la memoria dinamica auto....gracias de nuevo

Drumpi

  • Hero Member
  • *****
  • Mensajes: 6289
  • Karma: 160
  • Odio el periodo "entre proyectos"
    • La web de Drumpi
Re: Uso de punteros como array dinámico para novatos.
« Respuesta #12 en: Diciembre 03, 2009, 12:15:44 am »
Llevo años tras el título de "Master de los Ficheros", pero con todos los cambios que ha habido en Bennu he pasado de experto a simple "aficionado" ;D
Tu di que problemas tienes con la carga y trataremos de ayudar, pero para el tema de leer/escribir en ficheros suelo usar tres variables auxiliares con FREAD/FWRITE:
BYTE dato_b;
WORD dato_w;
INT dato_i;
Se que no es eficiente ni recomendable, pero así evitas cualquier problema ligado al mal reconocimiento de los tipos. Mas adelante ya te atreves a más.

¿Garbage collection? ¿Eso existe?
Hala, como con 1001 procesos sólo va a 9 FPS, vamos a meterle 32 veces más, a ver si revienta.
(Drumpi epic moment)

DjSonyk

  • Sr. Member
  • ****
  • Mensajes: 492
  • Karma: 24
Re: Uso de punteros como array dinámico para novatos.
« Respuesta #13 en: Diciembre 03, 2009, 12:22:41 am »
Garbage collection o Colector de Basura ,existe o se llama asi en JAVA se puede usar con System.gc(),lo he recordado viendo lo de las listas aninadas a ver como le hacia un ejemplo a Wind y estaba ahi escrito...

A ver lo e gradado como me as dicho pero al leer me sale por say(),numero muy grandes,apenas uso del 1 al 10 para colocar los procesos,lo que me e fijado que salen con una distancia de 12 osea por ejemplo, 3000,3012,3024,ect,creo que se refiere a la direcion de memoria,te adjunto el codigo que creo que sera por eso no me va...
declaracion de datos:
TYPE Celda
   INT X,Y,Grafico;
END
Celda POINTER Celdas;
abrir fichero

Celdas=Alloc(3072*sizeof(Celdas));
id_fich=FOPEN("dat.dat",O_READ);
FOR (contador10=0;contador10<=3072;contador10++)
   Fread(id_fich, Celdas[contador10]);      
END
FCLOSE(id_fich);

Drumpi

  • Hero Member
  • *****
  • Mensajes: 6289
  • Karma: 160
  • Odio el periodo "entre proyectos"
    • La web de Drumpi
Re: Uso de punteros como array dinámico para novatos.
« Respuesta #14 en: Diciembre 03, 2009, 12:30:11 am »
Supongo que el SAY lo haces así:
FOR (contador10=0;contador10<3072;contador10++)  //<- OJO, la posición 3072 no existe ¿o si?
 SAY(itoa(celdas[contador10].X));
 SAY(itoa(celdas[contador10].Y));
 SAY(itoa(celdas[contador10].Grafico));
END

Si no, prueba primero a grabar un "dat.dat" con valores que conozcas (por ejemplo, del 0 al 9) a ver si lo lee bien (o usa un lector hexadecimal para comprobarlo, son muy socorridos).
Hala, como con 1001 procesos sólo va a 9 FPS, vamos a meterle 32 veces más, a ver si revienta.
(Drumpi epic moment)