Do you want to meet me?
16 02 2009 Categorías: Vídeos
Comentarios : Sin comentarios »
Para la instalación es necesario tener habilitados los repositorios Universe. Podemos buscar los paquetes necesarios en Synaptic llamados jflex y cup o bien ejecutamos en consola:
1 | $ sudo apt-get install jflex cup |
Para que las bibliotecas esten disponibles al realizar nuestros programas, debemos agregarlas al classpath del sistema. JFlex y Cup se encuentran en:
1 | /usr/share/java |
Por lo tanto, para incluir dichas bibliotecas en el classpath:
1 | $ export CLASSPATH=$CLASSPATH:/usr/share/java/cup.jar:/usr/share/java/JFlex.jar |
Si queremos que se ejecute en cada sesión y no tener que volver a hacerlo cada vez que iniciamos sesión siendo un cambio permanente, lo incluimos en el bashrc (ejecutandolo una sola vez y en una línea):
1 | echo "export CLASSPATH=$CLASSPATH:/usr/share/java/cup.jar:/usr/share/java/JFlex.jar" | tee -a ~/.bashrc |
,
Open Source
OpenGL es un librería de gráficos bastante versátil. En este artículo vamos a ver un pequeño ejemplo de su potencial.
El ejemplo consiste en dibujar un triángulo blanco en una ventana y que al pulsar la tecla ‘c’ nuestro triángulo se coloree de rojo, verde y blanco en cada vértice. Por otro lado si pulsamos la tecla escape ‘Esc’ la aplicación terminará. Además añadiremos un pequeño menú que se accionara al pulsar el botón derecho del ratón, donde tendremos la opción de cambiar de modo y salir.
Una pequeña imagen que detalla el proceso:

Ejemplo sencillo con OpenGL
A continuación pongo el código y más adelante lo detallo paso a paso:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 | #include < stdio.h >; #include < stdlib.h >; #include < GL/glut.h >; enum {  MENU_CHANGE = 1,  MENU_EXIT }; static int mode = 0; void SelectFromMenu(int idCommand) {     switch (idCommand)    {        case MENU_CHANGE:            mode = (mode == 0) ? 1: 0;            glutPostRedisplay();            break;        case MENU_EXIT:            exit(0);            break;    }    glutPostRedisplay(); } void Keyboard(unsigned char key, int x, int y) {    switch (key)    {        case 27: // ESCAPE key            exit(0);            break;        case 'c':            SelectFromMenu(MENU_CHANGE);            break;    } } int buildPopupMenu(void) {    int menu = glutCreateMenu(SelectFromMenu);    glutAddMenuEntry("Cambiar modo\tc", MENU_CHANGE);    glutAddMenuEntry("Salir\tEsc", MENU_EXIT);    return menu; } void display () {    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);    glLoadIdentity();    glTranslatef(0.0, 0.0, -4.0);    if(mode == 0)    {        glBegin(GL_TRIANGLES);            glColor3f (1.f, 1.f, 1.f);   // White colour            glVertex3f(0.0, 1.0, 0.0);            glVertex3f(-1.0, -1.0, 0.0);            glVertex3f(1.0, -1.0, 0.0);        glEnd();    }    else    {        glBegin(GL_TRIANGLES);            glColor3f (0.f, 1.f, 0.f);   // Green colour            glVertex3f(0.0, 1.0, 0.0);            glColor3f (1.f, 1.f, 1.f);   // White colour            glVertex3f(-1.0, -1.0, 0.0);            glColor3f (1.f, 0.f, 0.f);   // Red colour            glVertex3f(1.0, -1.0, 0.0);        glEnd();    }    glutSwapBuffers(); } void resize (int w, int h) {    glViewport(0, 0, w, h);    glMatrixMode(GL_PROJECTION);    glLoadIdentity();    gluPerspective(50., w/(double)h, 1., 10.);    glMatrixMode(GL_MODELVIEW); } void init (void) {    glEnable(GL_DEPTH_TEST); } int main(int argc, char *argv[]) {    glutInit(&argc, argv);    glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB);    glutInitWindowSize(400, 400);    glutInitWindowPosition(200, 200);    glutCreateWindow("Ejercicio");    init();    glutDisplayFunc(display);    glutReshapeFunc(resize);    glutKeyboardFunc(Keyboard);    buildPopupMenu();    glutAttachMenu(GLUT_RIGHT_BUTTON);    glutMainLoop();    return 0; } |
El funcionamiento principal, es tener una función display(), que según en el modo que estemos, dibujara una u otra figura (coloreada de una manera u otra). Para ello utilizaremos una variable global estática con la que guardaremos el modo en el que estamos, cuando se requiera redibujar, miraremos el modo y lo cambiaremos y dibujaremos la nueva figura. Las funcion de keyboard() llamará al menu según la tecla (salir o cambiar modo) y el menú se encargara de llamar a display y cambiar el modo.
De forma más detalla en la funcion main() primero pasamos los argumentos de entrada con glutInit() y inicializamos glutInitDisplaymode con un doble buffer y RGB, ya que necesitaremos un buffer doble para que nuestras figuras se rendericen en un frame y mientras en otro se procesen.
Le damos un tamaño a la ventana de 400×400 con glutInitWindowSize() y en la posición 200×200 con un título de ventana “Ejercicio”. y llamamos a la función init para que active la prueba de profundidad.
Luego asignamos una funcion de retrollamada (callback) para mostrar nuestra ventana con lgutDiplayFunc(), la función de retrollamada sera display(), que la veremos más adelante.
Otra función de retrollamada para cuando redimensionemos la ventana y despues llamaremos a buildPopupMenu() que sera una función para construir nuestro menú.
Y adjuntaremos el menú cuando se presione el botón derecho del ratón con glutAttachmenu(). Despues llamamos al bucle principal de glut.
Nota: algo importante a resaltar, si utilizas una tarjeta gráfica ATI, es posible que tengas algun fallo si pones la línea, ya que el buffer no quedara totalmente limpio al dibujar en pantalla:
1 | glClear(GL_COLOR_BUFFER_BIT); |
Por eso es mejor ponerlo así y evitamos este tipo de fallos (desconozco si en otras tarjetas se da dicho fallo):
1 | glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); |
Para compilar:
gcc -lGL -lGLU -lglut ejercicio.c -o ejercicio
Y ejecutarlo:
./ejercicio
¿Te ha gustado o resultado útil? Pues deja un comentario con tu opinión
Estos días he tenido que hacer un pequeño ejemplo de un programa en C, aparentemente sencillo, pero del que no he encontrado buenas soluciones en Google, ni siguiera en otros idiomas más dados.
Casi todos los ejemplos que veía por internet eran poco elegantes, no cuidaban el tratamiento de errores y además todos pedían la entrada de datos por línea de órdenes. Asi que me ha parecido útil ponerlo en el blog, para que gente que se encuentre con el problema en un futuro, tenga una buena referencia o al menos aproximada a su solución.
El problema consiste en crear un programa en C que pida el nombre de un archivo de texto y devuelva el número y el palíndromo de todos los posibles palíndromos encontrados en dicho archivo.
Un palíndromo segun Wikipedia es:
Una palabra, número o frase que se lee igual hacia adelante que hacia atrás.
Por ejemplo algunas palabras: ala, bob, solos, reconocer, …
Y alguna frases como:
“Dabale arroz a la zorra el abad”
En nuestro caso por simplicidad y caso común detectaremos solo las palabras y no frases o textos enteros, ya que si no esto podría complicarse hasta un nivel mayor, aunque tampoco sería demasiado complicado.
Supongamos que tenemos un fichero de ejemplo con algunos palíndromos como el siguiente:
1 2 3 4 5 | Este es un archivo de prueba que contiene palíndromos como pueden ser: ala anilina reconocer solos otto bob pero por ejemplo no son palindromos solas ola |
El siguiente programa, detectara los palíndromos según nuestros propósitos (lo explico más detalladamente después):
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 | #include < stdio.h>; #include < stdlib.h>; #include < string.h>; int searchPalin(char *cad) { unsigned int i = 0, d = (int) strlen(cad)-1; int palin=1; while ((palin == 1) && (i < ((int)strlen(cad)))) { if (cad[i] != cad[d]) palin=0; else { i++; d--; } } return palin; } int main(int argc, char** argv) { if(argc < 2) { fprintf(stderr,"palin: opción inválida\nEl primer argumento debe ser un nombre de archivo.\n"); return 1; } char *namefile=argv[1]; FILE *fd; if((fd=fopen(namefile,"r")) == NULL) { fprintf(stderr,"palin: Error al abrir el archivo.\n"); return 1; } else { printf("Buscando palíndromos en archivo: %s\n",namefile); fseek(fd, 0, SEEK_END); long length = ftell(fd); fseek(fd, 0, SEEK_SET); char *w; w = (char *) malloc(length*sizeof(char *)); int i,j,p=0; fread(w, sizeof(unsigned int), length, fd); fclose(fd); char *aux; aux = (char *) malloc(strlen(w)*sizeof(char *)); for(i=0,j=0;i<strlen(w);i++) { if(w[i] == ' ' || w[i]=='\n') { aux[j] = '\0'; j=0; if(searchPalin(aux)) printf("%d. %s\n",++p,aux); } else { if(w[i] != '\t' && w[i] != ' '); { aux[j] = w[i]; j++; } } } } return 0; } |
Bien pasemos a la explicación detallada:
Las tres primeras lineas incluyen en las bibliotecas necesarias para el funcionamiento del programa, la de entrada/salida estandar, la biblioteca estandar y la biblioteca de cadenas (útil para estos propósitos).
La función searchPalin es la que puedes encontrar en la mayoría de los sitios de internet, se encarga de contar los caracteres de la cadena e ir viendo desde el principio al final si van coincidiendo por el principio y por el final. Si es así retorna un valor booleano verdadero (líneas 5 a 19).
En la función main primero comprobamos que hemos recibido un número correcto de argumentos, al menos los necesarios, ya que más de los estrictos, serán ignorados (líneas 23 a 27).
Como segunda comprobación tenemos que asegurarnos que el parámetro del nombre de fichero dado, existe y se puede abrir para lectura, si es así ya podemos procesar el archivo en busca de palíndromos (líneas 29 a 36).
Por comodidad para realizar la lectura del archivo utilizamos la función fread() (línea 48), por lo que será necesario saber la longitud del fichero. La longitud de un fichero no es difícil de calcular, pero hay que tener un aspecto en cuenta.
La función que tenemos disponible para el cálculo de la longitud de un fichero es ftell(), pero dicha función retorna el indicador de posición de fichero, que al comenzar la lectura será 0, luego, necesitamos posicionarnos al final del fichero, después llamar a ftell() y por último volver al principio del fichero para empezar a leer caracteres mediante fread(). Para posicionarnos al principio y al final utilizamos fseek() consiguiendo nuestro propósito (lineas 41 a 43) .
Después cerraremos el archivo con fclose() (línea 49), ya que habremos leído todos los caracteres y los habremos almacenado en una variable llamada w, con la peculiaridad, de que se hace una reserva dinámica de memoria con la cantidad exacta de caracteres del archivo, aprovechando que ya habíamos calculado la longitud del archivo (línea 44 y45), por lo que no nos limitamos a una cantidad en un archivo (como hacen otras posibles implementaciones).
También necesitaremos una cadena auxiliar (aux) en la que reservaremos la cantidad de carácteres que tenga w (línea 51 y 52).
Posteriormente procesaremos nuestra cadena y si leemos un carácter normal que no sea un espacio en blanco o un tabulador, lo almacenaremos en nuestra cadena auxiliar (líneas 61 a 68). Si por el contrario encontramos un salto de línea o un espacio en blanco (lineas 55 a 60) , entonces sera una palabra distinta, por lo que procesaremos el contenido que tengamos en aux, ademas de añadir el carácter ‘\0′ de final de cadena (línea 57). Esto último es importante, ya que si no añadimos ese carácter no se interpretara bien la cadena al no estar completa y ser una sucesión de caracteres (peculiaridades de C).
Llamaremos a la función searchPalin para que nos verifique si la cadena aux es un palindromo y si es, mostraremos el número de palindromo y el palíndromo en sí.
Para compilar el archivo, se puede hacer a pelo, o bien podemos utilizar un makefile (mucho más cómodo) como el siguiente:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | BINARY = palin CFLAGS = -o CC = gcc RM = rm all: @echo Compilando... $(CC) $(BINARY).c $(CFLAGS) $(BINARY) @echo Hecho. clean: @echo Limpiando... $(RM) -f *.o *~ @echo Hecho. |
Para compilar escribimos:
1 | $ make |
Para ejecutar el binario con el fichero de ejemplo.txt:
1 | $ ./palin ejemplo.txt |
Y debe dar una salida como:
1 2 3 4 5 6 7 | Buscando palíndromos en archivo: ejemplo_old.txt 1. ala 2. anilina 3. reconocer 4. solos 5. otto 6. bob |
Para limpiar la compilación:
1 | $ make clean |
Y eso es todo, no es muy complicado, pero requiere varios detalles en los que se debe prestar atención.
Cualquier sugerencia de mejora o comentario adicional es bienvenido.
Happy coding!
,
Open Source
El testing de programas puede convincentemente demostrar la presencia de errores, pero nunca puede demostrar su ausencia.
Edsger W. Dijkstra.
Sobre la crueldad de verdaderamente enseñar ciencias de la computación
Comentarios recientes