Centro de Investigación y de Estudios Avanzados Herramientas de programación Ivan López Arévalo [email protected] 17-21 de Julio de 2006 Objectivo: 1­ Conocer herramientas básicas de programación en ambiente Linux 2­ Conseguir una visión general de programación (lenguaje C) Linux Herramientas Windows Lenguaje C Consideraciones teoría y práctica Conocimientos YA ADQUIRIDOS Y Capacidad de razonamiento y aprendizaje 1. Introducción 2. Herramientas de programación en Linux 2.1 Editor vi 2.2 Compilador gcc 2.3 Utilidad make 2.4 Utilidad man 3. Breve introducción al Lenguaje C 3.1 Tipos básicos y funciones 3.2 Operadores 3.3 Funciones 3.4 Control de flujo 3.5 Vectores 3.6 Registro 3.7 Ámbito de variables y funciones 3.8 Punteros 3.9 Registros Introducción Lenguajes de programación Según el tipo de programación ● Procedimentales, OO (C, C++, Java, Smalltalk, etc) ● Declarativos (Prolog, LISP, CLISP, etc) Según su forma de compilación/ejecución ● Compilados (C, C++, Pascal, etc) ● Interpretados (Basic, Java) Lenguajes de programación Según el conjunto de instrucciones ● Lenguaje máquina ● Lenguaje ensamblador ● Lenguaje de alto nivel Desarrollo de aplicaciones Análisis (Especificar lo que se desea) ● Diseño (Decidir la estructura de datos y algoritmo que han de resolver el problema) ● Codificación (Implementar el algoritmo usando un lenguaje de programación) ● Pruebas (Validar que el programa obtenido es la solución al problema planteado) ● Mantenimento ● Lenguaje C ● ● ● ● ● ● ● De propósito general, pequeño y sencillo pero muy potente y de aplicación ilimitada No está ligado a ningún sistema operativo ni a ninguna máquina concreta Permite escribir compiladores y sistemas operativos (programación de sistemas) No mecanismos para tipos de datos no básicos No mecanismos de almacenamiento de datos que no sea el estático No mecanismos de entrada ni salida ANSI C Creación de un programa en C main() { } ­­­­­­­­­­­­­­­­­­­­­­­­­­­ #include <stdio.h> main() { printf("Hola a todos!\n"); } Modularización de un programa C A menor tamaño la compilación es más rápida Mayor legibilidad y estructuración del programa Los módulos se combinan con las librerías necesarias para formar el programa en su versión ejecutable. La compilación, enlazado y ejecución de un programa dependen del sistema operativo. Por ejemplo cc prog <­­ compilación cc modulo1, modulo2 <­­ compilación link prog, modulo1, modulo2 <­­ enlazado prog <­­ ejecución fuente prog.c fuente comp1.c fuente comp2.c cc prog cc comp1 cc comp2 objeto prog.obj objeto comp1.obj objeto comp2.obj link prog, comp1, comp2 ejecutable prog.exe o prog.out librería C Mecánica de Codificación Edición Compilación ANSI C (C estándar) Ejecución Herramientas de programación Editores vi emacs gedit kwrite kate ... ... ... ... ... ... Compilador gcc Utilidades make man editor vi make man gcc Editor vi editor estándar de UNIX no existen menús, existen órdenes modos inserción: teclear texto comandos: guardar, salir, copiar, mover, etc. tecla "ESC" para modo órdenes tecla "i" para modo inserción Para comandos se emplea “:” + comando Comandos básicos (sin usar “:”) Insertar texto i, a Movimientos teclas de cursor o h, l, k, j Borrar caracter x, backspace, supr Usando “:” Salir sin grabar los cambios Salir grabando los cambios Guardar los cambios actuales Guardar como archivo Insertar desde el cursor archivo Editar archivo q wq (aconsejable) w w archivo r archivo e archivo Moverse hasta el fin de la línea Moverse hasta el principio de la línea Moverse hasta la siguiente palabra Moverse hasta la anterior palabra Moverse a la línea n*** Moverse hasta el final de la siguiente palabra Moverse hasta el final de la siguiente palabra* Encontrar el siguiente caracter c en la línea actual Encontrar el anterior caracter c en la línea actual Moverse hasta la siguiente frase Moverse hasta la anterior frase Moverse hasta el anterior párrafo Moverse hasta el siguiente párrafo Moverse hasta la parte superior de la pantalla Moverse hasta la parte media de la pantalla Moverse hasta la parte inferior de la pantalla L Avanzar página Retroceder página $ 0 w b nG e E fc Fc ( ) { } H M ^F ^B Insertar después del caracter actual a Insertar al final de la línea Añadir línea por debajo e insertar texto Añadir línea por arriba e insertar texto A o O Borrar caracter Borrar palabra Copiar linea Copiar palabra Pegar x dw ­ dnw yy yw ­ ynw p Deshacer el último cambio Buscar texto Repetir última búsqueda Repetir última búsqueda hacia abajo Repetir última búsqueda hacia arriba Repetir último cambio u /texto n / ? . IDE's Integrated Development Environment's (“Entornos” integrados de programación) ­ personalizar ● emacs ● xemacs ● nedit ● jedit ● elvis ● crimson ● cute ● andjunta ● MinGW ● Kdevelop Compilador GCC (GNU Compiler Collection) Conjunto de compiladores creados por el proyecto GNU GCC es software libre (licencia GPL) GCC significaba GNU C Compiler Casi todo GCC está escrito en C Lenguajes soportados Ada (GNAT) C (GCC) C++ (G++) Fortran (GFortran) Java (GCJ) Objective C lcc para windows GCC Front ends para Pascal, Modula­2, Modula­3, Mercury, VHDL y PL/I Arquitecturas Alpha ARM H8/300 System/370, System 390 x86 y x86­64 IA­64 "Itanium" Motorola 68000 Motorola 88000 MIPS PA­RISC PDP­11 PowerPC SuperH SPARC VAX GCC uso (preprocesamiento, compilación, ensamblado y enlazado) gcc [ opción | archivo ] gcc hola.c compila "hola.c" y genera el ejecutable a.out gcc ­o hola hola.c compila "hola.c" y genera ejecutable hola gcc ­c hola.c compila "hola.c" pero no genera el ejecutable ­­> código objeto (hola.o) gcc ­c ­o objeto.o hola.c compila "hola.c" y genera código objeto (objeto.o) gcc ­o resulta.o hola.c adicional.c otromas.c [host sources]$ gcc ­o ~/tmp/sources/execs/prueba.exe prueba.c [host sources]$ gcc ­o execs/prueba.exe prueba.c [host sources]$ ./execs/prueba.exe Hola mundo ­Iruta especifica la ruta hacia el directorio donde se encuentran los archivos marcados para incluir en el programa fuente. gcc ­I/usr/include fuente.c ­Lruta especifica la ruta hacia el directorio donde se encuentran los archivos de biblioteca con el código objeto de las funciones referenciadas en el programa fuente. gcc ­L/usr/lib fuente.c ­Wall muestra todos los mensajes de error y advertencia del compilador make ● Herramienta para actualizar, en forma optimizada y automática, los archivos fuente que integran un proyecto de software. ● Emplea un archivo de texto llamado makefile o Makefile (reglas) ● Proyectos con diversos archivos fuentes ● Recompila sólo partes que han sido modificadas y enlaza los módulos en código objeto construyendo el ejecutable. ● Es independiente del lenguaje de programación. ● Puede manejar cualquier conjunto de archivos en los cuales haya archivos que deban actualizarse ● Control explícito de dependencias Reglas make destino : requisito ... requisitoN comando ... destino ­ el nombre del archivo a crear, un ejecutble o un archivo objeto (.o) requisito ­ el nombre de un archivo del cual depende el destino a crear. comando es una acción a realizar. ● debe comenzar con TABULADOR, no sirven los espacios. ● es un comando normal ejecutable desde el shell legibilidad \ es el caracter de continuación de línea # indica comentario # makefile ejemplo para tres archivos y una libreria ejecutable: main.o fuenteA.o fuenteB.o fuenteC.o gcc ­o ejecutable main.o fuenteA.o fuenteB.o getch.o main.o: main.c libreria.h gcc ­c main.c fuenteA.o: fuenteA.c libreria.h gcc ­c fuenteA.c fuenteB.o: fuenteB.c gcc ­c fuenteB.c fuenteC.o: fuenteC.c libreria.h gcc ­c fuenteC.c elimina_todo_recompilar: rm ejecutable \ main.o fuenteA.o fuenteB.o fuenteC.o $ ./polaca <­­ ejecutar aplicacion $ make clean <­­ eliminar todo lo generado y empezar de cero # makefile ejemplo MODIFICADO CC = gcc ARCHIVOS = fuenteA.o fuenteB.o fuenteC.o ejecutable: main.o $(ARCHIVOS) $(CC) ­o ejecutable main.o $(ARCHIVOS) main.o: main.c libreria.h $(CC) ­c main.c fuenteA.o: fuenteA.c libreria.h $(CC) ­c fuenteA.c fuenteB.o: fuenteB.c $(CC) ­c fuenteB.c fuenteC.o: fuenteC.c libreria.h $(CC) ­c fuenteC.c elimina_todo_recompilar: rm ejecutable \ main.o fuenteA.o fuenteB.o fuenteC.o destino requisito destino destino requisito requisito regla destino regla regla destino regla destino regla regla destino requisito regla man (manual) comando que informa sobre otros comandos útil para consultas rápidas (desde consola) La ayuda está estructurada en las siguientes secciones: 1. Programas ejecutables o comandos del usuario. 2. Llamadas al sistema (programación). 3. Librerías (programación). 4. Archivos del sistema (normalmente relativos a dispositivos). 5. Formatos de fichero y convenciones. 6. Juegos. 7. Macro paquetes y convenciones. 8. Administración del sistema. 9. Rutinas del Kernel (sección no estándar). Orden de búsqueda secuencial en secciones man [no. seccion] [mandato] man 3 printf man 1 printf Ayuda del comando man de la sección 7: man 7 man Consultar TODA la ayuda relativa a man: man ­a man Órdenes Búsqueda de cadenas (tecla "/" + cadena). Avance y retroceso de pagina Teclas de dirección Salir "q" Recursos y comandos básicos Linux ivanlopez.cjb.net/repositorio.html Introducción al Lenguaje C Tipos básicos y variables caracteres (char) ­­ (normalmente 8 bits) números enteros short ­­ entero corto con signo (normalmente 16 bits) int ­­ entero con signo (depende de la implementación) long ­­ entero largo con signo (normalmente 32 bits) números de punto flotante float – flotante simple (normalmente 32 bits) double Variable Una variable es un área en memoria que tiene un nombre y un tipo asociado. Es obligatorio declarar las variables antes de usarlas. Declaración: tipo_variablenombre ; int i; // declaracion de un entero char letra; // declaracion de un caracter Comentarios: // comentario para una linea /* comentario para varias lineas */ Una variable o expresión de un tipo se puede convertir explícitamente a otro tipo, anteponiéndole el tipo entre paréntesis. Se le llama casting void cambio_tipo (void) { float a; int b; b = 10; a = 0.5; if ( a <= (float) b ) printf(“El valor de a es menor igual que el valor de b”); } float c = a + (float) b Operadores lógicos y booleanos <<, >> rotación de bits a la derecha, izquierda & AND booleano | OR booleano ^ EXOR booleano ~ complemento a 1 ! complemento a 2, NOT lógico ==, != igualdad, desigualdad &&, || AND, OR lógico <, <= menor, menor o igual >, >= mayor, mayor o igual Operadores numéricos +, ­ suma, resta ++, ­­ incremento, decremento *, /, % multiplicación, división, módulo operadores aritméticos con asignación: += igual a la suma de ­= igual a la resta de *= igual a la multiplicación de /= igual a la división de <e> ? <x> : <y>. Se evalúa si e entonces x; si no, y Funciones En C toda la lógica de programación (algoritmos) está agrupada en funciones. Al menos existe la función main() se declara con el nombre de la función precedido del tipo de valor que retorna, ● recibe parámetros o argumentos (opcionalmente), ● contiene sentencias o instrucciones para realizar algo (opcionalmente) y ● devuelve un valor de algún tipo conocido (opcionalmente). ● Los paréntesis ­de argumentos­ son obligatorios. ● Funciones La sintaxis global es: Tipo_Valor_devuelto nombre_función (lista_argumentos){ bloque_de_codigo; } int sumaEnteros ( int a, int b ) { int c = a + b; return c; } La claúsula return se usa para finalizar el método devolviendo algún valor o el control de flujo. Funciones void El tipo_dato de retorno es opcional. Si es necesario devuelva un valor se declara el tipo que devuelve. Si no necesita ningún valor el tipo_dato devuelto es void. void haceAlgo() { . . . } No es necesaria la cláusula return. . . . . haceAlgo(); // ningún valor no se asigna a ninguna variable. // (No hay nada que asignar). int calculo_A (int param_1, int param_2){ ... ... ... } int calculo_A (int param_1, int param_2){ ... ... ... } void saludo(){ printf(“Bienvenidos de nuevo al lenguaje C”); } main(){ int var_A=calculo_A(1, 2); int var_B=calculo_B(3, 4) * 1/2; saludo(); return 0; } #include <....> #include <....> #define ­­­­­­­ #define ­­­­­­­ ... ... ... ... ... ... main(){ } Todas las líneas que comienzan con el símbolo “#” indican una directiva del precompilador. include incluye archivos en el codigo fuente define sustituye texto del codigo fuente con el definido Se debe tener muy en cuenta que en C todos los argumentos son pasados 'por valor'. No existe el concepto de paso de parámetros 'por variable' o 'por referencia'. int incr ( int v ){ return v + 1; } main(){ int a, b; b = 3; a = incr(b); } ******************************************* a = 4 mientras que b = 3 no ha cambiado después de la llamada ******************************************* Control de flujo if () { } else { } int cero ( double a ){ if ( a == 0.0 ) return (TRUE); else return (FALSE); } Si la expresión no es condicional y es aritmética se considera falso si vale 0; y si no, verdadero. Opciones múltiples switch (valor) { case valor1: <sentencias>; ... break; case valor2: <sentencias>; ... break; case valor3: case valor4: ... default: <sentencias> } while (<expresión>){ <sentencias> } do { <s> } while ( <expresión> ); for ( <inicialización>; <expresión>; <modificación> ){ <sentencias> } Vectores Porción de memoria para almacenar un grupo de elementos del mismo tipo tipo nombre [tamaño]; int f, modulo[52]; for ( f = 0; f < 52; f++ ) modulo[f] = 0; ... } char vocal[5] = { 'a', 'e', 'i', 'o', 'u' }; int dimensiones[25][80][2]; char nombre[60], direccion[80]; Los elementos de un vector son accedidos por índices que van desde 0 hasta N­1 para un vector de N elementos. Tamaño con sizeof() Registros Agrupa distintos tipos de datos en una misma entidad. struct nombre { lista de declaraciones }; Los elementos (campos) pueden ser tipos básicos u otros registros. struct planeta { struct 3D r, v, a; double masa; char nom[10]; }; struct 3D { double x,y,z; }; Registros Los campos de cada registro son accesibles mediante el nombre del registro seguido de punto y el nombre del campo venus.r.x = 1.0; Cada campo se comporta como lo hace su tipo básico. typedef struct planeta PLANETA; PLANETA mercurio, venus, tierra, marte; PLANETA mercurio = { { 0.350, 0, 0 }, { 0, 0, 0 }, { 0, 0, 0 }, struct planeta { 100, "Mercurio" } }; struct 3D r, v, a; double masa; char nom[10]; }; struct 3D { double x,y,z; }; Ambito de funciones y variables locales, globales, estáticas y constantes locales y globales #include<stdio.h> int x, y; // globales int calculo_A( int a, int b ){a = b*x} int calculo_B( int c, int d ){d = c*y} main(){ int a, b; // locales a=calculo_A + calculo_B / x; b=calculo_A + calculo_B / y; } estáticas locales: Accesibles por la misma función y conservan su valor a través de llamadas sucesivas. globales: No visibles desde otro fuente. Lo mismo para funciones. void contar (){ static long cuenta = 0; cuenta++; printf("Llamada %ld veces\n", cuenta ); } main(){ int i; for (i=0; i < 5; i++){ contar(); } } Llamada 1 veces Llamada 2 veces Llamada 3 veces Llamada 4 veces Llamada 5 veces static void saludoInicial(){ printf("Hola mundo\n"); } Archivo fuente A ************************ #include<stdio.h> main(){ saludoInicial(); printf("Otro mensaje\n"); } Archivo fuente B Hola mundo Otro mensaje ********************** undefined reference to 'saludoInicial' const Define variables cuyo valor debe permanecer constante durante toda la ejecución del programa. Se puede usar con argumentos de funciones. const double pi = 3.14159; double lcercle ( const double r ){ return 2.0 * pi * r; } Punteros ● Variable que permite acceder y manipular otras variables mediante su dirección de memoria ● Son el tipo más potente y la clave del éxito del lenguaje ● Permiten que una función reciba y cambie el valor de una variable variable vector de char's Lorenzo Ávila puntero 57a@25Q$284 Declaración float *numero_flotante; REG_DIMENSIONES *registro_dimension; char *caracter; Operaciones básicas ● manipular un puntero (como variable) ­­> su nombre ● acceder a la variable a la que apunta ­­> *nombre (indirección) ● asignar/manipular dirección ­­> & (dirección de) void operaciones(){ La edad es 50 long edad; La edad es 25 long *p; p = &edad; edad = 50; printf("La edad es %ld\n", edad ); *p = *p / 2; printf("La edad es %ld\n", edad ); } void imprimir_string ( char string[] ){ char *p; for ( p = string; *p != '\0'; p++ ) imprimir_char(*p); } Punteros con registros “­>” en lugar de punto. Ej. Sea p un puntero a un tipo PLANETA, y queremos conocer su masa: p­>masa #define NUM_PLANETAS static PLANETA Ssolar[NUM_PLANETAS]; void init_SistemaSolar ( void ){ PLANETA *p; for ( p = SSolar; p < SSolar[NUM_PLANETAS]; p++ ) init_planeta(p); // asigna datos iniciales } void init_planeta ( PLANETA *p ){ p­>masa = 0; p­>nom = ""; init_co(&(p­>r)); init_co(&(p­>v)); init_co(&(p­>a)); } void init_co ( struct coords *c ){ c­>x = c­>y = c­>z = 0; } Punteros como parámetros void swap ( int *x, int *y ){ int tmp; tmp = *x; *x = *y; *y = tmp; } void intercambio (){ int a, b; a = 1; b = 2; swap( &a, &b ); printf(" a = %d b = %d\n", a, b ); } Resumen de punteros int f1(); función que devuelve un entero int *p1; puntero a entero int *f2(); función que devuelve un puntero a entero int (*pf)(int); puntero a función que toma y devuelve un entero int (*pf2)(int *pi); puntero a función que toma un puntero a entero y devuelve un entero int a[3]; vector de tres enteros int *ap[3]; vector de tres punteros a entero int *(ap[3]); vector de tres punteros a entero int (*pa)[3]; puntero a vector de tres enteros int (*apf[5])(int *pi); vector de 5 punteros a función que toman un puntero a entero y devuelven un entero Archivos Todas las operaciones se realizan a través de streams. Un stream está formado por una serie ordenada de bytes. Leer o escribir de un archivo implica leer o escribir del stream. Se debe asociar un stream con un archivo, mediante un puntero a una estructura FILE. Este puntero se inicializa con la llamada a la función fopen() para abrir un archivo. Streams comunes de consola: stdin ­­> scanf() stdout ­­> printf() stderr ­­> archivo log de errores text stream: serie de lineas de texto acabadas con un caracter newline. binario stream: colección de bytes sin ninguna estructura especial. Manejo de archivos ­­> consumo de recursos ­­> BUFFERS RAM buffer sistema de archivos operaciones (adición, archivo modificación, eliminación, etc. acceso secuencial o aleatorio stdio.h define los prototipos de todas las funciones, la declaración de la estructura FILE y algunas macros y definiciones: EOF: es el valor devuelto cuando se llega al final de archivo Pasos: abrir, realizar el tratamiento y cerrar. fopen(nom_archivo, modo_acceso) fclose ( puntero_archivo ) abrir un archivo cerrar un archivo Los modos de acceso para streams de texto son los siguientes: r w a r+ w+ a+ Abre un archivo existente para lectura Crea un nuevo archivo para escribir Abre un archivo que existente para añadir información al final Abre un archivo que existente para actualizarlo Crea un nuevo archivo para actualizarlo, si existe lo sobreescribe. Abre un fichero para añadir información al final. Si no existe lo crea. fgetc y fputc ­­> manejo de caracteres int fgetc ( FILE *stream ); lee el siguiente caracter del stream y los devuelve convertido a entero sin signo. Si no hay caracter devuelve EOF int fputc ( int c, FILE *stream ); devuelve el propio carácter si no hay error. Si lo hay, devuelve el carácter EOF feof() que devuelve cero si no se ha llegado al final del stream while ( !feof(infile)) fputc ( fgetc ( infile ), outfile ); fgets y fputs ­­ manejo de líneas char *fgets ( char *s, int n, FILE *stream ); lee caracteres del stream hasta que encuentra un final de línea o se lee el carácter n­1. Mantiene el carácter \n en el string y añade el carácter \0. Devuelve la dirección del string o NULL si se produce algún error. int fputs ( const char *s, FILE *stream ); fputs pone el string en el stream, no añade ni elimina caracteres \n y no copia la marca de final de string \0. fread y fwrite ­­> manejo de bloques (array, struct, tec). Se especifica el tamaño de cada elemento y el número de elementos. size_t fread ( void *p, size_t s, size_t n, FILE *f ); size_t fwrite ( void *p, size_t s, size_t n, FILE *f ); p s n *f puntero hacia el área de datos que se desea leer o escribir tamaño de cada elemento número de elementos stream. Ambas devuelven el número de elementos leídos o escritos, que debe ser el mismo que se le indica acceso aleatorio ( fseek y ftell ) fseek ( FILE *stream, long offset, int whence ); mueve el cursor (indicador de posición) a un lugar determinado por el parámetro whence: SEEK_SET ­­> inicio del archivo SEEK_CUR ­­> posición actual SEEK_END ­­> final del archivo long ftell ( FILE *stream ); devuelve la posición del cursor. Este valor indica el número de bytes desde el inicio del fichero