Programación : C (6) Dr. J.B. Hayet CENTRO DE INVESTIGACIÓN EN MATEMÁTICAS Septiembre 2013 , J.B. Hayet Programación, Septiembre 2013 1 / 40 Outline 1 Directivas al preprocesador 2 Input/Output , J.B. Hayet Programación, Septiembre 2013 2 / 40 Directivas al preprocesador Outline 1 Directivas al preprocesador 2 Input/Output , J.B. Hayet Programación, Septiembre 2013 3 / 40 Directivas al preprocesador Preprocesador .c Ensamblaje Compilacion Preprocesador .i .s Edicion de ligas .o EJECUTABLE .o .o El preprocesador transforma el código en otro código. Funciona por directivas que pueden : Incluir el contenido de otros archivos (#include). Definir constantes (#define). Definir macros (#define). Permitir compilación condicional (#if, #ifdef). Las directivas al preprocesador se introducen por el sı́mbolo “#”. , J.B. Hayet Programación, Septiembre 2013 4 / 40 Directivas al preprocesador Preprocesador No hace fundamentalmente nada determinante en cuanto al código objeto generado, sólo permite facilidades de escritura en el código. Por ejemplo : Evitar repetir unas constantes numéricas largas. Definir una macro que permita remplazar una función corta (se gana memoria y tiempo). , J.B. Hayet Programación, Septiembre 2013 5 / 40 Directivas al preprocesador La directiva #include Permite incluir el contenido de código de otro archivo. Sirve en particular para incluir declaraciones de funciones incluidas en archivos header. #i n c l u d e <math . h> double x = 0 . 1 4 4 ; double y=pow ( x , 3 . 5 ) ; , J.B. Hayet Programación, Septiembre 2013 6 / 40 Directivas al preprocesador La directiva #include Ejemplo : el contenido de math.h /∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ Math F u n c t i o n s ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗ ∗/ extern double acos ( double ) ; extern f l o a t acosf ( float ); extern double a s i n ( double ) ; extern f l o a t asinf ( float ); extern double atan ( double ) ; extern f l o a t atanf ( float ); extern double atan2 ( double , double ) ; extern f l o a t atan2f ( float , float ) ; extern double cos ( double ) ; extern f l o a t cosf ( float ); extern double s i n ( double ) ; extern f l o a t sinf ( float ); extern double tan ( double ) ; extern f l o a t tanf ( float ); extern double acosh ( double ) ; extern f l o a t acoshf ( float ); extern double a s i n h ( double ) ; extern f l o a t asinhf ( float ); , J.B. Hayet Programación, Septiembre 2013 7 / 40 Directivas al preprocesador La directiva #include Dos sintaxis posibles : 1 Para la inclusión de archivos de la biblioteca estándar (math.h, stdio.h... o en los directorios especificados a la compilación por “-I”): #i n c l u d e < s t d i o . h> 2 Para la inclusión de archivos que están localizados en el mismo directorio que el código compilado (y luego en los directorios estándar) #i n c l u d e ” miPrograma . h” , J.B. Hayet Programación, Septiembre 2013 8 / 40 Directivas al preprocesador La directiva #define #d e f i n e nombre c u a l q u i e r a c o s a En su primer uso, sirve para definir constantes : el preprocesador reemplaza cada ocurrencia de “nombre” por lo que sigue en la definición, “cualquieracosa” (que puede ser cualquiera cosa, incluso palabras llaves, elementos de sintaxis, constantes numericas. . . ). , J.B. Hayet Programación, Septiembre 2013 9 / 40 Directivas al preprocesador La directiva #define Se pueden combinar : #d e f i n e NUM LINEAS 480 #d e f i n e NUM COLUMNAS 640 #d e f i n e TAMAÑO IMAGENES NUM LINEAS ∗ NUM COLUMNAS , J.B. Hayet Programación, Septiembre 2013 10 / 40 Directivas al preprocesador La directiva #define Hay un cierto número de constantes definidas ya por #define por el compilador : Constante Uso LINE Numero de la linea corriente FILE Nombre del archivo compilado DATE Fecha de la compilación % TIME Hora de la compilación % , J.B. Hayet Programación, Septiembre 2013 11 / 40 Directivas al preprocesador La directiva #define Ejemplo : #i n c l u d e < s t d i o . h> i n t main ( ) { p r i n t f ( ” E r r o r en l i n e a %d d e l a r c h i v o %s \n” , LINE , FILE ) ; return 0; } Da : Macaye [ CLASE5 ] [ 2 1 : 2 3 ] > . / t e s t E r r o r en l i n e a 5 d e l a r c h i v o t e s t . c , J.B. Hayet Programación, Septiembre 2013 12 / 40 Directivas al preprocesador La directiva #define Cuidado : el preprocesador va a remplazar cada ocurrencia del texto, entonces, puede eventualmente llevar a problemotas : #d e f i n e num 10 void func1 ( ) { i n t numCosas ; ... } (una variable no puede empezar por valores numéricos !) Evitar pues que el nombre sea demasiado “frecuente”. , J.B. Hayet Programación, Septiembre 2013 13 / 40 Directivas al preprocesador La directiva #define Macros : puede considerar argumentos al nombre que se va a cambiar, y actuar como “función” (pero no tiene nada que ver con funciones C !). Remplaza expresiones más genéricamente que simples valores. En general #d e f i n e nombre ( l i s t a −p a r a m e t r o s ) c u e r p o −de−l a −macro , J.B. Hayet Programación, Septiembre 2013 14 / 40 Directivas al preprocesador La directiva #define Ejemplo clásico: #d e f i n e max ( x , y ) ( x>y ? x : y ) #d e f i n e min ( x , y ) ( x<=y ? x : y ) , J.B. Hayet Programación, Septiembre 2013 15 / 40 Directivas al preprocesador Macros : cuidado Las macros están consideradas como macros a partir del carácter de paréntesis que sigue inmediatamente el nombre de la macro. #d e f i n e c u a d r a d o ( x ) ( x ∗ x ) ¡No dejar espacio antes del ”(”! , J.B. Hayet Programación, Septiembre 2013 16 / 40 Directivas al preprocesador Macros : cuidado Efectos de bordo : #d e f i n e c u a d r a d o ( x ) ( ( x ) ∗ ( x ) ) i n t b = c u a d r a d o(++a ) ; , J.B. Hayet Programación, Septiembre 2013 17 / 40 Directivas al preprocesador Macros : cuidado Efectos de bordo : #d e f i n e c u a d r a d o ( x ) ( x ∗ x ) i n t c = c u a d r a d o ( a+b ) ; , J.B. Hayet Programación, Septiembre 2013 18 / 40 Directivas al preprocesador Macros : cuidado Evitar el abuso. . . (Algol-like, en Bourne shell) #d e f i n e I F if ( #d e f i n e THEN ){ #d e f i n e ELSE } else { #d e f i n e ELIF } else i f ( #d e f i n e F I ;} #d e f i n e ENDSW } #d e f i n e FOR for ( #d e f i n e WHILE while ( #d e f i n e LOOP for (;;){ #d e f i n e POOL } assign (n , v ) NAMPTR n; STRING v; { I F n−>n a m f l g&N RDONLY THEN f a i l e d ( n−>namid , w t f a i l e d ) ; ELSE r e p l a c e (&n−>namval , v ) ; FI } , J.B. Hayet Programación, Septiembre 2013 19 / 40 Directivas al preprocesador Compilación condicional #i f c o n d i c i o n −1 pedazo −1 #e l i f c o n d i c i o n −2 pedazo −2 ... #e l i f c o n d i c i o n −n pedazo−n #e l s e pedazo−e l s e #e n d i f , J.B. Hayet Programación, Septiembre 2013 20 / 40 Directivas al preprocesador Compilación condicional Cuando se quiere hacer pruebas, o dejar un pedazo de código sin compilarlo : #i f 0 // E s t e p e d a z o no l o t e r m i n é e n t o n c e s // l e d e j o a s i , no e s t a r á c o m p i l a d o int x = blabla ; #e n d i f Se puede checar el valor de una constante definida por un #define #i f PROCESADOR == ALPHA tamano long = 64; #e n d i f , J.B. Hayet Programación, Septiembre 2013 21 / 40 Directivas al preprocesador Compilación condicional Se puede checar la existencia de un sı́mbolo definido con #define con #ifdef. #d e f i n e DEBUG .... #i f d e f DEBUG // Aquı́ h a rı́ a s c o s a s que s e r v i rı́ a n // p a r a d e b o g a r #e n d i f /∗ DEBUG ∗/ , J.B. Hayet Programación, Septiembre 2013 22 / 40 Directivas al preprocesador Compilación condicional Existe también el operador defined que va con un #if y que tiene la ventaja de puede ir por varias instancias a la vez : #i f d e f i n e d ( LINUX ) | | d e f i n e d (DARWIN) , J.B. Hayet Programación, Septiembre 2013 23 / 40 Directivas al preprocesador Compilación condicional : #include Los #include pueden ser fuentes de error, por multiplicidad de las declaraciones de funciones en los headers. Si en un código aparecen varias declaraciones de la misma función, se genera un error de compilación. , J.B. Hayet Programación, Septiembre 2013 24 / 40 Directivas al preprocesador Compilación condicional : #include Para evitar eso, los archivos están marcados con #define (guardias) : #i f n d e f #d e f i n e MYPROG H MYPROG H ... #e n d i f , J.B. Hayet Programación, Septiembre 2013 25 / 40 Directivas al preprocesador Compilación condicional : #include Ejemplo : /∗ ∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗ ∗ ∗ ∗ F i l e : math . h ∗ ∗ ∗ ∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗ ∗/ MATH #i f n d e f #d e f i n e MATH , J.B. Hayet Programación, Septiembre 2013 26 / 40 Directivas al preprocesador La directiva #pragma Es una directiva que se usa para dar opciones al compilador; las comandos que se pueden pasar a éste a través de #pragma dependen fuertemente de la arquitectura. Ejemplo : #pragma once igual a los guardias de inclusión. , J.B. Hayet Programación, Septiembre 2013 27 / 40 Input/Output Outline 1 Directivas al preprocesador 2 Input/Output , J.B. Hayet Programación, Septiembre 2013 28 / 40 Input/Output printf Impresión formateada en la salida estándar (terminal) f o r ( i = 0 ; i < 5 ; i ++) p r i n t f ( ”\n i = %d” , i ) ; } La cadena de control (primer argumento de printf) contiene el formato de la impresión. Los otros argumentos son los datos que se van a imprimir. Observar que printf puede tener un número variable de argumentos (!) , J.B. Hayet Programación, Septiembre 2013 29 / 40 Input/Output printf Formato Conversión en Representación %d int decimal con signo %ld long int decimal con signo %u unsigned int decimal sin signo %lu unsigned long int decimal sin signo %o unsigned int octal sin signo %lo unsigned long int octal sin signo %x unsigned int hexadecimal sin signo %lx unsigned long int hexadecimal sin signo Ademas se puede especificar un espacio total que imprimir: %10d por ejemplo pone 10 cifras (con ceros donde necesario, y alineado a la derecha). , J.B. Hayet Programación, Septiembre 2013 30 / 40 Input/Output printf Formato %f %Lf %e %Le %g %Lg %c %s Conversión en double long double double long double double long double unsigned char char* Representación decimal coma fija decimal coma fija decimal notación exponencial decimal notación exponencial más corta entre %f y %e más corta entre %lf y %le carácter cadena de caracteres , J.B. Hayet Programación, Septiembre 2013 31 / 40 Input/Output printf Ademas: se puede indicar el espacio mı́nimo que usar para imprimir : %7f significa que se imprimirá el flotante con mı́nimo 7 caracteres. se puede indicar cuantos dı́gitos al mı́nimo consideras después del punto: %.4f significa que se imprimirá el flotante con mı́nimo 4 dı́gitos después del punto. se puede completar los espacios vacı́os con ceros : %07.2f usar el % en el texto de salida con %% , J.B. Hayet Programación, Septiembre 2013 32 / 40 Input/Output scanf Entrada de datos por el input estándar; similar a printf, excepto que el segundo argumento lleva la dirección en memoria donde poner el dato leı́do. Cuidado a la compatibilidad formato/tipo de la variable. #i n c l u d e < s t d i o . h> i n t main ( ) { int i [10] , k ; f o r ( k =0;k <10; k++) { p r i n t f ( ” e n t r a un e n t e r o ” ) ; s c a n f ( ”%d” ,& i [ k ] ) ; p r i n t f ( ” i [%d ] = %d\n” , k , i [ k ] ) ; } return 0; } , J.B. Hayet Programación, Septiembre 2013 33 / 40 Input/Output I/O para caracteres Las funciones getchar() y putchar(char c) realizan las operaciones de lectura/escritura de caracteres en la entrada/salida estándar. , J.B. Hayet Programación, Septiembre 2013 34 / 40 Input/Output Noción de flujo En realidad: s c a n f ( ”%d” , &v a l o r ) ; p r i n t f ( ” V a l o r = %d\n” , v a l o r ) : es equivalente de: f s c a n f ( s t d i n , ”%d” , &v a l o r ) ; f p r i n t f ( s t d o u t , ” V a l o r = %d\n” , v a l o r ) : donde stdin y stout son dos objetos de tipo apuntadores a archivos (FILE *). , J.B. Hayet Programación, Septiembre 2013 35 / 40 Input/Output Noción de flujo En C la impresión estándar (en la terminal) y la lectura estándar son vistas como operaciones de escritura/lectura a archivos abiertos. stdin y stdout representan a unas abstracciones de las entradas/salidas como archivos (flujos). A diferencia de un archivo normal, no se tienen que abrir. Otro del mismo tipo es stderr (salida de error). , J.B. Hayet Programación, Septiembre 2013 36 / 40 Input/Output fprintf/fscanf i n t f p r i n t f ( FILE ∗ st rea m , const char ∗ f o r m a t , i n t f s c a n f ( FILE ∗ st rea m , const char ∗ f o r m a t , ...); ...); La primera regresa el número de caracteres escritos (<0 si error). La secunda regresa el número de datos de inputs leı́dos (0 si error). , J.B. Hayet Programación, Septiembre 2013 37 / 40 Input/Output scanf: peligros #i n c l u d e < s t d i o . h> i n t main ( ) { int entero ; while (1) { p r i n t f ( ” E s c r i b a un e n t e r o : ” ) ; i n t r e t = s c a n f ( ”%d” , &e n t e r o ) ; i f ( r e t == 0 ) { p r i n t f ( ” Eso no e s un e n t e r o \n” ) ; c o nt i n ue ; } else { p r i n t f ( ” E n t r a s t e %d\n” , e n t e r o ) ; break ; } } } , J.B. Hayet Programación, Septiembre 2013 38 / 40 Input/Output scanf: peligros El scanf, en caso de error (el input no es del formato requerido), deja la lectura en el mismo punto. Se necesita limpiar la entrada estándar antes de re-empezar: w h i l e ( f g e t c ( s t d i n ) != ’ \n ’ ) ; , J.B. Hayet Programación, Septiembre 2013 39 / 40 Input/Output scanf: peligros char x , y , c ; printf ( ” First : ” ); s c a n f ( ”%c ” , &x ) ; // w h i l e ( ( c = f g e t c ( s t d i n ) ) != ’ \ n ’ ) {} p r i n t f ( ” Second : ” ) ; s c a n f ( ”%c ” , &y ) ; p r i n t f ( ”\n\n%c , %c ” , x , y ) ; , J.B. Hayet Programación, Septiembre 2013 40 / 40