Archive for the 'Programación' Category

Utilizando libparted para obtener información de nuestros discos

Pese a que en este blog normalmente solo escribe Jose Carlos (vosotros le llamáis rooibo), a partir de ahora yo también iré escribiendo de vez en cuando, a ver si así esto coge un poco mas de vida, ya que Jose Carlos no siempre tiene tiempo. Me llamo Noemi y a pesar de que es la primera vez que escribo en un blog como este (bueno, mas bien es la primera vez que escribo en un blog que no se hable solo de curiosidades tonterías) espero estar a la altura.

Libparted es una librería desarrollada en C por el proyecto GNU, la cual estoy utilizando casi a diario en el nuevo proyecto que estamos llevando a cabo Jose Carlos y yo.

Se trata de una librería que nos permite desde listar hasta crear, borrar y modificar particiones. Fue desarrollada para el programa parted, cuya versión gráfica y más conocida es gparted

Para instalar libparted en sistemas basados en debian (como ubuntu):

apt-get install libparted1.8-dev

Una vez instalada, podemos empezar a utilizarla desde nuestros programas, pero antes de entrar en detalle, mejor empezar con un ejemplo:

#include <stdio.h>
#include <parted/parted.h>
#define MEGABYTE 1048576

int main (void)
{
PedDevice* device = NULL;
PedDisk* disk = NULL;
PedPartition* part = NULL;
PedGeometry geom;

unsigned long size;
double length;
PedSector p_size;
char *fsname;

ped_device_probe_all ();

while ((device = ped_device_get_next(device))) {
disk = ped_disk_new(device);
p_size = device->length;
size = p_size/MEGABYTE;
size = size * device->sector_size;
printf(“%s name: %s size: %uMB\n”,device->path,device->model,size);

for (part = ped_disk_next_partition (disk, NULL); part;
part = ped_disk_next_partition (disk, part)) {
geom = part->geom;
length = (double)geom.length/MEGABYTE*device->sector_size;
if(part->fs_type) {
fsname = (char*)part->fs_type->name;
} else {
fsname = “Uknown”;
}

//if(part->num > 0) {
printf(“\t%s%d %10.2fMB %s\n”,device->path, part->num,length,fsname);
//}
}

}
return 0;
}

para compilarlo es suficiente poner

gcc -lparted test.c -o test

Al ejecutarlo nos muestra una lista con nuestros discos y sus particiones (debemos ejecutarlo como root ya que libparted utiliza instrucciones a bajo nivel que requieren privilegios de administrador para funcionar)

andr0med:/home/ap0# ./test
/dev/sda name: ATA Hitachi HTS54161 size: 152576MB
/dev/sda1  146389.14MB ext3
/dev/sda2    6236.17MB Uknown
/dev/sda5    6236.14MB linux-swap
andr0med:/home/ap0#

Si miramos el código, vemos que hay dos bucles anidados (uno dentro de otro), el primero es el que lee los discos mientras que el que está dentro se encarga de iterar sobre las particiones de cada disco leído.

Lo primero que tenemos que hacer es incluir la librería

#include <parted/parted.h>

Libparted necesita escanear el sistema busca de dispositivos de almacenamiento, para ello llamamos a ped_device_probe_all:

ped_device_probe_all ();

A continuación, creamos un bucle que itera sobre ped_device_get_next, obteniendo el siguiente dispositivo cada vez que es llamada la función. Cuando no queden mas dispositivos, la función devuelve NULL y el bucle finaliza:

while ((device = ped_device_get_next(device)))

con ped_disk_new(device) a partir de un dispositivo creamos un disco para poder tratarlo como tal

disk = ped_disk_new(device);

con esto obtenemos el tamaño del disco en megabytes

p_size = device->length;
size = p_size/MEGABYTE;
size = size * device->sector_size;

de esta forma ya podemos printear nuestro disco por pantalla con su ruta en el sistema(device->path), modelo(device->model) y su tamaño en MB (size)

printf(“%s name: %s size: %uMB\n”,device->path,device->model,size);

terminado esto, entramos en el segundo bucle el cual hace lo mismo que el primero pero en este caso llamando a las diferentes particiones de nuestro disco

for (part = ped_disk_next_partition (disk, NULL); part;
part = ped_disk_next_partition (disk, part))

Como veis, es un bucle exactamente igual, pero esta vez llamando a ped_disk_next_partition. Calculamos el tamaño de cada partición encontrada en el disco, de la misma forma que hacemos para calcular el tamaño de cada disco:

length = (double)geom.length/MEGABYTE*device->sector_size;

A continuación, comprobamos si la partición tiene un sistema de archivos conocido, en caso contrario lo llamamos Uknown

if(part->fs_type) {
fsname = (char*)part->fs_type->name;
} else {
fsname = “Uknown”;
}

finalmente, printeamos nuestras particiones filtrándolas

if(part->num > 0) {
printf(“\t%s%d %10.2fMB %s\n”,device->path, part->num,length,fsname);
}

Esta condición que comprueba si el número de partición es mayor que 0, es necesaria para impedir que se muestren por pantalla particiones inexistentes por pantalla, ya que ninguna partición está identificada por un número negativo, veamos que pasa si quitamos el condicional:

andr0med:/home/ap0# ./test
/dev/sda name: ATA Hitachi HTS54161 size: 152576MB
/dev/sda-1       0.03MB Uknown
/dev/sda1  146389.14MB ext3
/dev/sda2    6236.17MB Uknown
/dev/sda-1       0.03MB Uknown
/dev/sda5    6236.14MB linux-swap
/dev/sda-1       2.49MB Uknown
andr0med:/home/ap0#

Esto es solo una pequeña parte de lo que se puede hacer con libparted, en un futuro ya volveré a hablar de ella.

Convierte imagenes JPEG en XHTML

Si, se que el título es un poco raro, pero es la forma mas rápida de describir el último lío en el que me he metido.

La historia comienza hace un año mas o menos, cuando alguien me propuso como se podría crear un captcha en PHP sin usar GD ni Imagemagick o similares, y como por aquel entonces yo ya estaba trabajando en eyeOS, tenía muy presente el tema del DHTML, y de jugar con elementos DIV con posición absoluta por todas partes, etc, por lo que pensé, que si una imagen es un conjunto de pixels, se podría pintar una imagen, con un conjunto de divs con width:1px y height:1px, y posicionándolos todos con position absolute, en su sitio.

Me di cuenta enseguida de que era viable, pero nunca me puse a hacerlo (tenía demasiado trabajo en eyeOS por aquel entonces), el caso es que hace 2 días, tras el artículo que hice sobre un programa que habíamos hecho mi novia y yo, para romper el viejo captcha de meneame, y como tenía tan reciente el uso de libjpeg, decidí empezar un nuevo mini-proyecto con ella…y ahí nació img2xhtml.

La idea es sencilla, img2xhtml es un programa que usando libjpeg, lee una imagen jpeg linea a linea, y genera un archivo xhtml de salida, que pinta exactamente la misma imagen, pero utilizando anchors (<a>) de un pixel de alto por un pixel de ancho, con el mismo background-color que tenía el pixel en la imagen original, y position absolute en el sitio que le pertoca.

Dicho así, suena muy simple, pero ya me imaginaba que no iba a ser tan fácil, nunca lo es.

En primer lugar, hay una linea que se va a repetir dentro del xhtml muchísimas veces: el pixel, por lo que si podemos reducir esa linea en 1 caracter, reduciremos considerablemente el peso total del archivo html resultante, por ello se usan anchors (<a>) en lugar de div (<div>) por que los primeros se escriben con 2 letras menos. Veamos un pixel:

<a class=w style=top:74px;left:62px;background:rgb(52,52,52) />

Un pixel como vemos, es un anchor (<a>) un poco guarro para pesar lo mínimo, que omite las comillas en los atributos html por que no contienen espacios, etc.

w es una clase css, tal como:

.w{position:absolute;height:1px;width:1px;}

De esta forma, todo lo que no es variable en un pixel, está en la clase CSS, lo que nos ahorra tamaño por pixel.

Vale, con todo esto en mente, hicimos el programa, el cual funciona bastante bien, por ejemplo, esta imagen:

Se puede ver pasada a xhtml aquí.

Lo cual, al menos en mi Firefox3, se renderiza así:

El resultado es bastante bueno, sin embargo, uno enseguida se da cuenta de que esta imagen debe tener MUCHOS elementos xhtml para pintarse así, pesa 277k, frente al original, que pesa 2,8k, además, dentro tiene:

jcarlosn@linux-wnp3:~/img2xhtml> cat tux.html | sed “s/<a/\n/g” | wc -l
4343
jcarlosn@linux-wnp3:~/img2xhtml>

4343 anchors (<a>).

Además, el problema que surge es que la CPU se dispara al abrir imágenes medianamente grandes.

Con el problema de la cpu y del tamaño en mente, estaba claro que teníamos que empezar a trabajar en ideas para reducir los elementos xhtml, le conté la idea a SirKeldon,y me picó un poco para que siguiese reduciendo el tamaño de los pixeles al mínimo, pero eso no servia para intentar reducir el número de elementos xhtml que disparan la cpu.

El segundo paso fue un poco mas complejo, hablando con mi novia, enseguida nos dimos cuenta de que había una manera fácil de reducir el número de <a> en pantalla: uniendo horizontalmente los pixels contiguos del mismo color, en un mismo elemento xhtml, alargado.

Tras hacerlo, obtuvimos una mejora considerable, sin embargo, no era suficiente para imágenes grandes, por lo que decidimos agregar un nuevo concepto: tolerancia.

La tolerancia es el tope de diferencia entre dos colores RGB, para considerarlos “iguales” y unirlos bajo un mismo elemento xhtml, de esta forma, cuanta mas tolerancia, menor calidad y mayor velocidad. Vamos a hacer una prueba con tolerancia 15: (R+-15, G+-15, B+-15):

img2xhtml -f tux.jpg -t 15 > tux_15.html

Lo cual genera esto.

Como vemos, la calidad ha bajado un poco, en mi firefox3 se renderiza así:

Vale, no es perfecto, pero, ahora el tamaño es de 89k, y la cantidad de elementos xhtml es de:

jcarlosn@linux-wnp3:~/img2xhtml> cat tux_15.html | sed “s/<a/\n/g” | wc -l
1313
jcarlosn@linux-wnp3:~/img2xhtml>

Con solo 1313 elementos xhtml, se dibuja esa imagen, si la analizamos un poco, veremos que está hecha con elementos xhtml alargados, no con pixels sueltos.

Lo mejor, es que lo probéis vosotros mismos, y jugueis un poco, no os recomiendo probar con imagenes mayores de 250×250. El programa lo podéis bajar de aquí:

Descargar img2xhtml

Compilarlo e instalarlo es como siempre, primero lo extraemos y ejecutamos ./configure:

jcarlosn@linux-wnp3:~/downloads> tar -xzf img2xhtml-1.0.tar.gz
jcarlosn@linux-wnp3:~/downloads> cd img2xhtml-1.0/
jcarlosn@linux-wnp3:~/downloads/img2xhtml-1.0> ./configure
checking for a BSD-compatible install… /usr/bin/install -c
checking whether build environment is sane… yes
checking for a thread-safe mkdir -p… /bin/mkdir -p
checking for gawk… gawk
checking whether make sets $(MAKE)… yes
checking for gcc… gcc
checking for C compiler default output file name… a.out
checking whether the C compiler works… yes
checking whether we are cross compiling… no
checking for suffix of executables…
checking for suffix of object files… o
checking whether we are using the GNU C compiler… yes
checking whether gcc accepts -g… yes
checking for gcc option to accept ISO C89… none needed
checking for style of include used by make… GNU
checking dependency style of gcc… gcc3
checking for a BSD-compatible install… /usr/bin/install -c
configure: creating ./config.status
config.status: creating Makefile
config.status: creating config.h
config.status: config.h is unchanged
config.status: executing depfiles commands
checking for jpeg_start_compress in -ljpeg… yes
checking for zlibVersion in -lz… yes

Y luego lo compilamos:

jcarlosn@linux-wnp3:~/downloads/img2xhtml-1.0> make
make all-am
make[1]: se ingresa al directorio `/home/jcarlosn/downloads/img2xhtml-1.0′
gcc -DHAVE_CONFIG_H -I. -g -O2 -MT main.o -MD -MP -MF .deps/main.Tpo -c -o main.o main.c
mv -f .deps/main.Tpo .deps/main.Po
gcc -DHAVE_CONFIG_H -I. -g -O2 -MT libjpg.o -MD -MP -MF .deps/libjpg.Tpo -c -o libjpg.o libjpg.c
mv -f .deps/libjpg.Tpo .deps/libjpg.Po
gcc -DHAVE_CONFIG_H -I. -g -O2 -MT libhtml.o -MD -MP -MF .deps/libhtml.Tpo -c -o libhtml.o libhtml.c
mv -f .deps/libhtml.Tpo .deps/libhtml.Po
gcc -g -O2 -o img2xhtml main.o libjpg.o libhtml.o -ljpeg
make[1]: se sale del directorio `/home/jcarlosn/downloads/img2xhtml-1.0′

Finalmente lo instalamos con:

sudo make install

Ahora para ver la ayuda del programa:

jcarlosn@linux-wnp3:~> img2xhtml -h
img2xhtml -f file [-m maxLine] [-t color tolerance]
Convert images to xhtml files

-f FILENAME Filename to convert to xhtml
-m MAXLINE Maximum number of pixels to join with tolerance
-t TOLERANCE Color tolerance to join two pixels with similar colors
into a single xhtml element (between 0-127)

img2xhtml Copyright (C) 2008 Noemi Blazquez & Jose Carlos Norte
This program comes with ABSOLUTELY NO WARRANTY.
This is free software, and you are welcome to redistribute it
under certain conditions.

Please send bugs to jose@eyeos.org

El parametro -m (maxline) especifica el máximo largo que puede tomar un pixel estirado tragandose a su pixel de al lado, sirve para jugar con tolerancias altas sin obtener imagenes que parecen códigos de barras.

Si alguien me pregunta para que sirve todo esto, la verdad es que no lo tengo muy claro, pero…¿y lo bien que se lo pasa uno haciendo el friki y programando en C estas extravagancias?

La dirección del proyecto en sourceforge es:

http://sourceforge.net/projects/img2xhtml/

Pero aún no nos ha dado tiempo de subir los paquetes y todo eso.

Rompiendo el antiguo captcha de meneame!

Hoy para variar, hago un post un poco mas práctico que los anteriores.

El caso es que estoy ayudando a mi novia a entender C/C++, sistemas y todo eso, así que decidí que hoy programaría algo con ella (algo simple,para empezar) y como no se me ocurría nada mas ameno, pensé en programar un programa en C, que usando libjpeg, fuese capaz de leer una imagen del viejo captcha clásico de meneame (como el que usan en enchilame para el registro) y sacar los números que hay en la imagen.

Nada mas empezar, nos dimos cuenta de que los números de ese captcha, siempre salen en la misma posición, tamaño y medida, además del mismo color y misma fuente, solo varía un poco el fondo, pero poco.

Para localizar los pixeles que pertenecen a un dígito y no al fondo, basta con comprobar si su nivel de azul (colores RGB) es mayor que 100.

El programa básicamente lo que hace es leer la imagen, linea a linea (linea de pixeles) y comprobar que pixeles están con azul mayor que 100, en la linea 20, lo cual es suficiente para distinguir todo los números.

El programa junto con una imagen de ejemplo, lo podéis bajar de aquí:

Enlace

Se compila con:

gcc -ljpeg image.c -o image

Y tiene como dependencia libjpeg (y libjpeg-dev para sistemas basados en debian)

Al ejecutarlo, lee el archivo image.jpeg de su mismo directorio, y muestra por la salida estandar, los números contenidos dentro de la imagen.

Con este pequeño programa y un script en bash bastante sencillo, uno puede dar de alta cuantas cuentas como quiera, de forma automatizada en páginas que usen las versión de meneame sin recaptcha.

Prueba con el programa compilado y la imagen que viene el .tar.gz:

jcarlosn@linux-wnp3:~/captcha> ./image
724160
jcarlosn@linux-wnp3:~/captcha>

Tiene en principio, un 100% de efectividad.

Como leer un feed RSS desde C

Esta semana estoy muy liado en el trabajo, no tengo mucho tiempo para mantener la calidad del blog, así que tendré que meter algún artículo de relleno, lo siento :D

Bromas aparte, en realidad este es un artículo que quería escribir hace días, pero no encontraba el momento.

Para entrar al tema y no dar los rodeos que acostumbro a dar, existe una librería para C, llamada libmrss, la cual proporciona un conjunto de funciones y estructuras de datos para leer de un feeds rss.

Dicha librería, utiliza libcurl para obtener los feeds y nxml para parsearlos, son sus únicas dependencias.

Para instalar la librería en ubuntu/debian basta con hacer:

apt-get install libmrss0-dev libmrss0

El paquete -dev es el que proporciona los .h para utilizarlos desde nuestro programa, el paquete normal, proporciona los .so, de la librería.

Una vez con la librería instalada, los pasos son sencillos, en primer lugar, incluimos mrss.h desde nuestro código:

#include <mrss.h>

Esto nos define las estructuras de datos y las funciones de la librería, para que las usemos en nuestro programa, en realidad, solo usaremos una función y 2 structs, la función es:

mrss_parse_url

Y las estructuras son el struct mrss_t y mrss_item_t, el primero representa a la información de un feed, y el segundo a los elementos del feed.

Lo interesante de esta librería, es lo sencilla que es de usar, vamos a ver un ejemplo:

#include <mrss.h>
#include <stdio.h>

int main() {
mrss_t *data=NULL;
mrss_error_t ret;
mrss_item_t *item;
ret=mrss_parse_url(“http://rooibo.wordpress.com/feed/&#8221;, &data);
if(ret != MRSS_OK || data == NULL) {
return 0;
}
item=data->item;
while (item) {
printf(“%s\n——————————-\n”,item->title);
item = item->next;
}
return 0;
}

Este miniejemplo hecho en un segundo,  lee las entradas del rss de este blog, y las printea por pantalla, se puede compilar así:

gcc -lmrss ejemplo.c -o ejemplo

Y se ejecuta sin argumentos. Como veis, es muy sencillo utilizar libmrss, la función mrss_parse_url rellena un puntero de tipo data, que dentro contiene un puntero a un struct de tipo mrss_item_t, en el cual tenemos el titulo de la noticia, descripción, etc y un puntero al siguiente elemento de tipo mrss_item_t, con los datos de la siguiente entrada del feed.

Para ver que contiene mrss_item_t aparte de title, podemos consultar la web de mrss, aqui.

Leer feds desde C sirve para muchas cosas, desde extender tu aplicación con soporte para algún tipo de feed, como para hacerse programas que hagan acciones con RSS en dispositivos empotrados, como la fonera.

Lo único negativo de esta librería es que no existe documentación alguna para ella, yo aprendí a usarla leyendo el mrss.h.

Librería en C para usar la API de meneame, y meneame-utils

Hoy es sábado, y como informático que soy, los sábados no salgo por ahí, no voy a bares ni discotecas, ni me paseo por ningún sitio…Me quedo en casa programando, igual que el resto de la semana, pero programando lo que yo quiero, es decir, como hobby.

Este sábado he decidido programar algo un poco rebuscado…empezaré por el principio.

Como todos sabéis, meneame es una página web, donde los usuarios envían noticias, las cuales los usuarios votan, y las que mas votos reciben, llegan a portada, y son vistas por miles de personas. Es una especie digg en español, pero que además, es software libre.

El caso es que meneame tiene una API pública, que cualquiera puede utilizar, para interactuar con meneame, desde cualquier programa, mediante el protocolo http, por ejemplo, si queremos comprobar si una url existe en meneame, ha sido enviada antes:

http://meneame.net/api/url.php?url=http://www.google.com

Y nos devuelve OK seguido de los enlaces a las veces que ha sido enviada y los votos que recibió, si no ha sido envíada:

http://meneame.net/api/url.php?url=http://www.example.com

Nos devuelve “KO” y la url desde la que podemos enviarla.

Utilizando esta API, podemos hacer un programa, que tenga la opción de comprobar si una url, existe en meneame, y con eso, todo tipo de viguerías.

Otra API muy interesante de el meneame, es la de enviar notas al notame. El notame es una especie de twitter, pero integrado en la página de meneame.

Para enviar notas al notame, existe otra API que podemos utilizar:

http://meneame.net/api/newpost.php?user=NOMBREUSUARIO&key=CLAVEAPI&text=TEXTOAQUI

Donde la clave API, es nuestra clave API, que podemos consultar en nuestro perfil de meneame, habiendo iniciado sesión.

Bien, además de todo esto, las notas del notame se pueden leer vía rss, entre otras cosas.

No voy a continuar, por que no pretendo documentar aquí toda la API de meneame, era solo para hacer una idea de lo que es, y como funciona, para introduciros en lo que he programado hoy.

El caso, es que imaginaros que queréis hacer un programa que utilice una de esas API, necesitaréis hacer peticiones HTTP desde vuestro programa, en algunos casos parsear la respuesta…si queréis leer las notas del notame, necesitaréis leer del feed…todo esto, es demasiado trabajo para un simple programa que interactúa con meneame, por ello, he creado un conjunto de librerías en C, que disponen de una serie de funciones para interactuar con el meneame desde tu programa, sin preocuparte de nada.

Para ejemplificar como funcionan, he creado también 3 programas que utilizan las librerías, para que podáis ver en directo, como funciona todo esto.

Antes de entrar en materia de código, voy a enseñar un poco los 3 programas (en C, para consola) de los que hablo.

jcarlosn@thanatos:~$ mnmuserinfo -h
mnmuserinfo [-xkrwndz] [-i id] [-u usuario]
Consulta información sobre un usuario de meneame

-x    Muestra solo el username
-k    Muestra solo el karma
-r    Muestra solo la posicion en el ranking
-w    Muestra solo la web
-n    Muestra solo el nombre
-d    Muestra solo la fecha de registro
-z    Muestra solo el id

-i id    Consulta la informacion para el usuario con ese id
-u usuario    Consulta la informacion mediante el nombre de usuario

Ejemplos:

Consultar informacion de jcarlosn usando su id: mnmuserinfo -i 23321
Consultar informacion de jcarlosn usando su nombre: mnuserinfo -u jcarlosn

Para notificar bugs: jose@eyeos.org
jcarlosn@thanatos:~$

El primero, permite obtener información de un usuario de meneame, vamos a verlo:

jcarlosn@thanatos:~$ mnmuserinfo -u Carme
Id: 2682
Nombre de usuario: Carme
Web:
Nomre: Carmen
Karma: 15.220000
Ranking: 70
Fecha de registro: 2006-03-04
jcarlosn@thanatos:~$

Podemos pedirle información del usuario pasando su id, o su nombre de usuario, si queremos ver solo un campo, podemos hacerlo, por ejemplo, la web:

jcarlosn@thanatos:~$ mnmuserinfo -u jonarano -w

http://www.jonarano.es

jcarlosn@thanatos:~$

Vale, el siguiente comando de ejemplo, creado con las librerías es mnmchecklink, permite consultar una url, para saber si ya existe en meneame, y si existe, muestra su enlace a meneame, y sus votos:

jcarlosn@thanatos:~$ mnmchecklink http://www.google.com
http://meneame.net/story.php?id=41836  votes: 4
http://meneame.net/story.php?id=20861  votes: 3
jcarlosn@thanatos:~$

Y si no existe:

jcarlosn@thanatos:~$ mnmchecklink http://www.meloinvento.com
El link proporcionado no existe en meneame
jcarlosn@thanatos:~$

Y el tercer y último comando, el mas elaborado, permite enviar y leer notas del notame, vamos a verlo:

jcarlosn@thanatos:~$ cnotame -h
cnotame [-l] [-n usuario] [-v] [-k apikey] [-m mensaje]
Publica notas en el notame, usando la API de meneame

-v    modo verbose (salida con detalle)
-h    muestra la ayuda
-k CLAVE    la clave API que se utilizara para agregar las notas
-m MENSAJE    el texto de la nota a enviar
-u USUARIO    el usuario asociado a la clave API porporcionada

-n USUARIO    lista las ultimas notas de USUARIO
-l    lista las ultimas notas de el notame

Ejemplos:

Listar las ultimas notas: cnotame -l
Listar las ultimas notas del usuario jcarlosn: cnotame -n jcarlosn
Enviar una nota al notame: cnotame -k XXXXXXXXXX -m “hola meneantes” -u youuser

Para notificar bugs: jose@eyeos.org
jcarlosn@thanatos:~$

Por ejemplo, para ver las últimas 20 lineas del notame:

jcarlosn@thanatos:~$ cnotame -l | tail -n 20
#15   Abel.Florez

No creo que seas de Segovia. Si es así, te mando a “los Miami”.
autor: jmt
———————
Entro a tuenti.

Me encuentro con una foto de la Euskal Encounter, que salgo dormido como un angelito!!! Con una toalla al cuello (porque tenía frio). No conocía la existencia de tal foto

Eso si, la que la ha subido, ya tiene la respuesta en “modo foto”
autor: jonarano
———————
Odio cuando algunos videojuegos llegan a un punto de dificultad en el cual pasarte una pantalla significa “pulsar exactamente los mismos botones en los mismos instantes (durante un buen rato) porque no hay otra manera, llegar a un punto ligeramente más avanzado que la vez anterior, morir, repetir”.
autor: trollinator
———————
@trollinator Por curiosidad. Qué juego te atormenta?
autor: Cesc
———————
jcarlosn@thanatos:~$

Si no lo limitamos con tail ,la salida será un poco extensa.

Ahora para ver todas las notas de un usuario concreto:

jcarlosn@thanatos:~$ cnotame -n jcarlosn
No es lo mismo @PEP0M0LT0, no
autor: jcarlosn
———————
me aburro
autor: jcarlosn
———————
no es lo mismo ganar karma para votar, que votar para ganar karma (karmwhore)
autor: jcarlosn
———————
@Ancalagon: no, no lo merece
autor: jcarlosn
———————
las 3 y media y aun sin sueño, que dura la vida del informatico
autor: jcarlosn
———————
jcarlosn@thanatos:~$

Para enviar una nota al notame:

cnotame -m “introduce aqui tu nota” -k tuclaveapiaqui -u tuusuarioaqui

Estos programas, son ejemplos del uso de esta librería, podéis crear vuestros propios programas con ella, vamos a verla un poco por encima:

En la parte de notame, tenemos libnotame.h/libnotame.c que disponen de:

int sendNote(char *msg, char *key, char *user);
struct note *listNotes(char *author);

La primera envía una nota dado su texto, la clave API y el usuario, la segunda devuelve una lista enlazada con el contenido de las notas, si no queremos especificar autor, y queremos leer todas las notas del notame, basta con pasarle NULL, para iterar sobre la lista de notas, tenéis un ejemplo en cnotame.c:

result=listNotes(vuser);
if(result == NULL) {
fprintf(stderr, “Error obteniendo las notas de notame\n”);
}
while(result != NULL) {
ptr=result;
printf(“%s\n———————\n”,ptr->text);
result=ptr->next;
free(ptr->text);
free(ptr);
}

En el apartado de la API de consultar la información de un usuario, tenemos libuserinfo.c/libuserinfo.h, que disponen de:

int getUserInfo(int id, struct userInfo *uinfo);
int getIdByUser(char *user);

La primera, rellena el struct de tipo userInfo que le pases en el segundo argumento, con la información obtenida del usuario con id, recibido por el primer argumento, el struct userInfo es:

struct userInfo {
char username[60];
char name[512];
char web[1024];
int id;
float karma;
int ranking;
char regdate[11];
};

La segunda, devuelve el id de un usuario, dado su nombre de usuario.

Y en el apartado de links, tenemos liblink.h/liblink.c que dispone de:

struct link *linkExists(char *link);

La cual comprueba si el link dado existe ya en meneame, y si existe, devuelve una lista enlazada de structs del tipo:

struct link {
char url[42];
int votes;
struct link *next;
};

Con todos los enlaces de las veces que fue enviado a meneame, y los votos que obtuvo, para iterar sobre ella, hay un ejemplo en mnmchecklink.c:

stack = linkExists(argv[1]);

if(stack == NULL) {
printf(“El link proporcionado no existe en meneame\n”);
} else {
while(stack != NULL) {
printf(“%s votes: %d\n”,stack->url,stack->votes);
myLink=stack;
stack=stack->next;
free(myLink);
}
}

Bueno, tiene muchísimos detalles ocultos esta librería, y no voy a entrar demasiado en detalles por que me estoy extendiendo demasiado, si tenéis alguna duda sobre la librería, podéis escribirme, mi correo está en los headers de todos los archivos.

Para poder compilar los ejemplo, se requiere libmrss y libcurl, para instalarlos en sistemas basados en debian, como ubuntu:

sudo apt-get install libcurl4-openssl-dev libmrss0-dev libmrss0

Luego estando en el directorio donde lo habéis extraído, ejecutáis make y si queréis que se copien a /usr/local/bin, sudo make install.

El makefile es muy cutre, por que solo son ejemplos de lo que se puede hacer con la librería, nada mas.

Todo el código es software libre y está liberado bajo GPL3, como dice en los headers.

Podéis descargar la librería de aquí.

Aviso: no es una librería propiamente dicha, en el sentido de librería de linux :) recordad que es un trabajo de fin de semana por hobby, es simplemente archivos .h con su .c, que proporcionan funciones para interactuar con meneame, y programas de ejemplo que los utilizan.

Por cierto, me olvidaba, segun comentaban aquí:

[*] Crea un API para bobos y los frikis harán virguerías, además dejarán de darte la lata pidiendo cosas complicadas. Pero no serán capaces de hacer que esos programas lean las notas vía RSS

así que los frikis no eramos capaces de leer las notas vía RSS :p

Estructuras de datos y todo eso

Acabo de empezar a escribir este blog, en el que me he propuesto escribir solo lo que me apetezca…  y el caso es que varios conocidos mios, están cursando la carrera de ingeniería informática, y estos últimos días me han pedido ayuda con la asignatura que ellos llaman FP2, y me ha parecido interesante escribir un poco, precisamente sobre eso, sobre algunos fundamentos de programación (en C/C++).

Voy a hablar de las estructuras de datos básicas que podríamos decir que son la Pila, lista y cola.

Una estructura de datos, es en programación, una forma de organizar y acceder a conjuntos de datos, de forma que podríamos decir, que las estructuras de datos, son distintos modelos de organizar conjuntos de información.

Como eso no suena muy claro, voy a enfocarlo de otra manera menos ortodoxa (espero que esto no lo lea nunca ningún experto :D)

Imagina que estás en tu casa, y de pronto el lavavajillas termina su trabajo, y los platos están listos para que los saques y los metas en el armario, bien, como la distancia entre el armario de los platos, y el lavavajillas, es un poco grande, os cansáis de tanto ir arriba y abajo, y le pedís a vuestra esposa/madre, que  se ponga al lado del armario, y vosotros le iréis pasando los platos.

Entonces empiezas a sacar platos del lavavajillas, y los vas dejando encima de la mesa, y de ahí, los va cogiendo ella, y los va metiendo en el armario.

En este ejemplo, los platos son los datos unitarios, y la mesa, es la memoria, en donde se almacenan los datos, el cómo nosotros pongamos los platos en la mesa, y en como ella los saque de la mesa, constituirán una estructura de datos.

Vamos a poner el ejemplo mas típico de todos, si vas dejando los platos encima de la mesa, cada uno encima del otro, estarás utilizando una estructura de datos llamada pila, y su particularidad es que el último plato que metas, será el primero en salir, esto se conoce como LIFO (Last Input, First Output).

Vale, con nuestro ejemplo de los platos, hemos descubierto ya la primera estructura de datos, la pila, la cual ya sabemos que es de tipo LIFO. En la pila, existe un concepto de siguiente, el siguiente plato es el que hay debajo de el que quitas, como siempre podemos ir agregando platos a la pila (en una habitación que no tuviese techo) la pila permite apilar tantos datos como quieras, sin afectar a los platos que yo había, ni cambiarlos de lugar o reestructurarlos.

Como vemos, el esfuerzo necesario para agregar un plato a la pila es mínimo y solo implica a ese plato.

Sin embargo, imagina que le dices a tu querida ayudante: saca primero el plato séptimo empezando por abajo, ella tendrá que primero contar los platos, recorriendo todos los platos hasta llegar al 7, levantar los de encima, coger el 7, y dejar otra vez los otros encima.

Como veis, el esfuerzo de acceder a un plato concreto, y no siempre el de encima, es muy grande.

Para solventar eso, podríamos cambiar el modo en el que apilamos los platos, podríamos colocar unas cajas numeradas encima de la mesa, en las que cada una cupiese un plato, al hacer esto, en la mesa cabrían como máximo unas 20 cajas, tu irías metiendo empezando por la caja 1, y acabando en la 20.

Al hacer esto, estaríamos usando un vector (array).

Tu ayudante, podría ir sacando platos de las cajas (posiciones del array), y metiéndolos en el armario. Si ahora le pidieses el plato número siete, solo tendría que ir y coger el plato de la caja (posición) 7, sin necesidad de mover nada, ni contar nada. El esfuerzo ha sido mucho menor, sin embargo, este método tiene también sus contras…

- Solo caben 20 platos, y si queremos meter mas, hay que hacer cosas muy costosas, como poner otra mesa y llenarla de cajas.
- Aunque tengas solo 3 platos, las cajas te ocupan gran parte de la mesa (que hemos dicho que es la memoria)

Como es lógico, todo el mundo, sin saber programar usa una pila para este problema, en el mundo real. La gente simplemente va apilando platos en lugar de utilizar cajas, por que? Por que en el problema planteado, no existe normalmente la necesidad de coger un plato arbitrario, sino que solo hay que ir apilando y desapilando.

Esta demostración sirve para ilustrar un par de cosas, la primera, es que distintas formas de organizar datos, proporcionan distintas ventajas y desventajas, y que en cada problema, hay que utilizar la adecuada.

Para extenderme un poco mas, seguramente alguien habrá pensado que el caso de la pila tiene otra desventaja, que es que los platos salen de la pila de platos, en un orden invertido al que entraron, por lo cual, el primer plato que apilaste, permanece en la pila mucho tiempo, y el último plato apilado, permanece en la pila un instante.

En el caso de los platos, esto no importa, pero, y si importase? Habría que utilizar una cola.

Una cola funciona exactamente igual que una pila, con la diferencia, que los platos se meten por arriba, y se sacan por abajo (imaginaros una mesa con una trampilla que tiene platos encima, y que se abre dejando caer un solo plato cada vez, y por ahí recoge los platos tu ayudante).

Usando una cola, tienes las mismas ventajas y desventajas que usando una pila, pues son sustancialmente lo mismo, pero en la cola se preserva el orden, el primer plato que metes, es el primer plato que sale (FIFO, First Input, First Output)

Es lógico que la gente use pilas y no colas para el problema de los platos, pues el orden en ese caso, no importa.

En toda esta explicación hay un concepto implicito, no tan fácil de ver, que es el concepto de lista, una lista es una forma de ordenar datos en la cual, cada datos apunta al siguiente, y el siguiente al siguiente, y nosotros solo tenemos el primero de todos, pero accediendo a su siguiente, y al siguiente del siguiente etc, podemos acceder a cualquier dato de la lista.

Una pila, es una lista, pues utilizamos el concepto siguiente, y una cola igual, cada vez que alguien desapila un plato de la pila, queda visible el siguiente, y cada vez que tu apilas un plato en la pila, lo haces encima del siguiente.

Como se puede ver, la pila y la cola, son formas de trabajar con listas, formas de ir metiendo y sacando cosas de listas, listas en las cuales, nosotros solo vemos el elemento que hay a la cabeza (como en el caso de los platos) y luego su siguiente, y su siguiente…

Existen otras estructuras de datos, pero de momento solo he querido entrar en estas 4 básicas: Vector, Pila, Cola y Lista.

En resumen:

- Si nuestro conjunto de datos, requiere que se pueda acceder a un dato concreto, de forma rápida, hay que utilizar un vector, donde podemos pedir la casilla X, sin pasar por las demas (acceso aleatorio)
- Si nuestro conjunto de datos tiene un volumen indeterminado y variable, debemos usar una lista
- En dependencia del orden y la forma en la que queramos ir sacando y metiendo cosas de la lista, debemos trabajar con ella en forma de cola, o en forma de pila

Como curiosidad, he desarrollado un ejemplo muy muy simplificado de Pila en C++, para que se vea una aplicación práctica, es un programa que apila 3 números, luego los desapila, y los muestra por pantalla:

Ejemplo de Pila en C++

Espero que esto ayude un poco a cualquiera que esté estudiando todos estos temas y se sienta un poco perdido :)

Por cierto, cuando le explicaba a un conocido mio, un fanático de kde, que estaba ayudando a algunos conocidos a entender FP2, me dijo: “es que todo eso ya te lo da Qt, no hace falta saberlo cuando programas en Qt)” Qt es una librería de clases, utilizada como base de KDE… mi duda es: ¿y entonces, como disciernes que estructura de datos usar en cada caso y por que?



Seguir

Recibe cada nueva publicación en tu buzón de correo electrónico.