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