You are on page 1of 238

Lenguajes de Programacin I

Referencia Marta Zorrilla Universidad de Cantabria

Ing. Santiago Esparza Guerrero Ingeniera en Computacin Unidad Acadmica de Ingeniera Elctrica

Introduccin al C
Objetivos:
Presentar la historia del lenguaje C y sus caractersticas principales. Presentar la estructura de un programa en C mediante ejemplos sencillos.

Contenidos:
1. La historia del C. 2. Caractersticas. 3. Mi primer programa en C.

Historia del C
Muchas ideas provienen de BCPL (Martin Richards, 1967) y de B (Ken Thompson, 1970). C fue diseado originalmente en 1972 para el SO UNIX en el DEC PDP-11 por Dennis Ritchie en los Laboratorios Bell. Primer Libro de referencia de C: The C Programming Language (1978) de Brian Kernighan y Dennis Ritchie. En los 80, gran parte de la programacin se realiza en C. En 1983 aparece C++ (orientado a objetos). En 1989 aparece el estndar ANSI C. En 1990 aparece el estndar ISO C (actual estndar de C). WG14 se convierte en el comit oficial del estndar ISO C. En dcada de los 90, WG14 trabaja en el estndar C9X/C99 que resuelve problemas de fiabilidad del ANSI C, amplia su funcionalidad con nuevos tipos de dato, funciones matemticas, arrays irrestringidos, etc.
3

Caractersticas del C
Lenguaje de programacin de propsito general, muy adecuado para programacin de sistemas (unix fue escrito en C). Lenguaje relativamente pequeo: solo ofrece sentencias de control sencillas y funciones. La E/S no forma parte del lenguaje, sino que se proporciona a travs de una biblioteca de funciones. Permite la agrupacin de instrucciones. Programacin estructurada. Permite la separacin de un programa en mdulos que admiten compilacin independiente. Diseo modular. Programas portables.

Inconvenientes del C
No es un lenguaje fuertemente tipado. Es bastante permisivo con la conversin de datos. Sin una programacin metdica puede ser propenso a errores difciles de encontrar. La versatilidad de C permite crear programas difciles de leer.
#define _ -F<00||--F-OO--; int F=00,OO=00; main(){F_OO();printf("%1.3f\n",4.*-F/OO/OO);}F_OO() {..}

Primer programa en C
/* Ejemplo 1. Programa DOCENA.C */ #include <stdio.h> main () { int docena; docena = 12; printf ("Una docena son %d unidades\n", docena); }

Segundo programa en C
/* Ejemplo 1. Programa saludo.c*/ #include <stdio.h> #define MENSAJE alumnos /*prototipo funciones*/ int imprimir_saludo (char * destino); int main (void) { int error=0; error=imprimir_saludo (MENSAJE); return(0); } int imprimir_saludo (char * destino) { printf (hola %s \n", destino); return(0); }
7

Crear, compilar y ejecutar un programa C


Crear un fichero con extensin .c con un editor de texto Mandato de compilacin bsico:
cc ejemplo.c - Genera el cdigo objeto ejemplo.o - Genera el ejecutable a.out - El programa se ejecuta tecleando a.out

El mandato cc -c ejemplo.c genera el fichero objeto ejemplo.o El mandato cc ejemplo.o -o ejemplo genera el ejecutable ejemplo
- El programa se ejecuta tecleando ejemplo.

Modelo de compilacin C

Entorno desarrollo IDE

10

Ejercicio
#include <stdio.h> int cuadrado (int); int main (void) { int lado2, lado1;

Sean dos cuadrados de lados L1 y L2 inscritos uno en otro. Calcula el rea de la zona comprendida entre ambos, utilizando para ello una funcin (que se llamar AreaCuadrado) que devuelve el rea de un cuadrado cuyo lado se pasa como argumento

printf ("dame lado del cuadrado 1:"); scanf( "%d",&lado1); printf ("dame lado del cuadrado 2:"); scanf(" %d",&lado2); printf ("El resultado de la diferencia es %d", cuadrado(lado1)-cuadrado(lado2)); return(0); } int cuadrado (int lado) { return(lado*lado); }
11

Elementos de un programa en C

12

Elementos de un programa C
Objetivos:
Mostrar la utilidad de documentar el cdigo utilizando los comentarios. Explicar los conceptos de variable y tipo de dato. Conocer los identificadores vlidos y tipos de constantes. Ensear las instrucciones de lectura y escritura junto con el formato de los datos.

Contenidos:
1. 2. 3. 4. 5. Comentarios Identificadores y palabras reservadas Constantes Variables y tipos de dato Escritura de datos con printf()
13

6. Lectura de datos con scanf()

Elementos de un programa C
Bsicamente el C est compuesto por los siguientes elementos:
Comentarios Identificadores Palabras reservadas Variables y tipos de datos Constantes Operadores

14

Comentarios
Sirven para incrementar la legibilidad de los programas. No se pueden anidar. Dentro de un comentario no puede aparecer el smbolo /*

/* Este es un comentario que ocupa ms de una lnea */ // Este comentario ocupa una sola lnea

15

Identificador
Nombre que se asigna a los distintos elementos del programa (variables, funciones,). Identificadores NO vlidos:
Empezar por Empezar por un nmero Utilizar la "

Ejemplos vlidos:
numero area_circulo valor_1
16

Palabras reservadas
auto break case char const continue default do double else enum extern float for goto if int long register return short sizeof static struct switch typedef union unsigned void volatile while

Es preciso insistir en que C hace distincin entre maysculas y minsculas. Por lo tanto, la palabra reservada for no puede escribirse como FOR, pues el compilador no la reconoce como una instruccin, sino que la interpreta como un nombre de variable.
17

Variables
Identificador utilizado para representar un cierto tipo de informacin. Cada variable es de un tipo de dato determinado. Una variable puede almacenar diferentes valores en distintas partes del programa.

18

Tipos de datos bsicos


TIPO sin valor carcter entero coma flotante (simple precisin) coma flotante (doble precisin) PALABRA RESERVADA void char int float double TAMAO EN BYTES 0 1 2 4 8

19

Tipos de datos. Modificadores


Tipo char Modificadores unsigned signed int short unsigned signed long unsigned signed float double long 0 a 255 -128 a 127 0 a 65.535 -32.768 a 32.767 0 a 4.294.967.295 -2.147.483.648 a 2.147.483.647 4 bytes 3,4*10-38 a 3,4*10+38 1,7*10-308 a 1,7*10+308 3,4*10-4932 a 1,1*10+4932 4 bytes 8 bytes 10 bytes Rango Ocupa 1 byte 1 byte 2 bytes 2 bytes 4 bytes

El tipo de dato int coincide con el tamao de palabra del procesador, generalmente 4 bytes

20

Declaracin de variables
Una declaracin asocia un tipo de datos determinado a una o ms variables. El formato de una declaracin es:
tipo_de_dato var1, var2, ..., varN;

Ejemplos:
int a, b, c; float numero_1, numero_2; char letra; unsigned long entero;

Deben declararse todas las variables antes de su uso. Deben asignarse a las variables nombres significativos.
int temperatura; int k;
21

Tipos definidos
Permite dar nuevo nombre a tipos de datos que ya existen, siendo estos ms acordes con aquello que representan. Sintaxis:
typedef tipo_basico nombre;

Declaracin :
typedef float Kg; typedef float Mts;

Y su uso al declarar variables:


Kg peso; Mts longitud;
22

La funcin printf()
Permite imprimir informacin por la salida estndar (pantalla) Formato:
printf(formato, argumentos);

Ejemplos:
printf("Hola mundo\n"); printf("El numero 28 es %d\n", 28); printf("Imprimir %c %d %f\n", 'a', 28, 3.0e+8);
23

La funcin printf() (y 2)
Formatos.
TIPO DE ARGUMENTO Numrico CARCTER DE FORMATO %d %i %o %u %x %X %f %e %g %E %G %c %s %% %n %p FORMATO DE SALIDA signed decimal int signed decimal int unsigned octal int unsigned decimal int unsigned hexadecimal int (con a, ..., f) unsigned hexadecimal int (con A, ..., F) [-]dddd.dddd [-]d.dddd o bien e[+/-]ddd el ms corto de %e y %f [-]d.dddd o bien E[+/-]ddd el ms corto de %E y %f carcter simple cadena de caracteres el carcter % se refieren a punteros y se 24

Carcter

Punteros

La funcin printf() (y 3)
Secuencias de escape.
CARCTER BARRA \a \b \t \n \v \f \r \" \' \\ SIGNIFICADO Alarma (Beep) Retroceso (BS) Tabulador Horizontal (HT) Nueva Lnea (LF) Tabulador Vertical (VT) Nueva Pgina (FF) Retorno Comillas dobles Comilla simple Barra invertida

25

La funcin printf (y 4)
Especificadores de ancho de campo:
printf("Numero entero = %5d \n", 28); produce la salida: Numero entero = 28 printf("Numero real = %5.4f \n", 28.2); produce la salida: Numero real = 28.2000

26

Funcin scanf()
Permite leer datos del usuario. La funcin devuelve el nmero de datos que se han ledo bien. No va texto Formato:

scanf(formato, argumentos);
Especificadores de formato igual que printf(). Ejemplos:
scanf("%f", &numero); & scanf("%c\n", &letra); scanf("%f %d %c", &real, &entero, &letra); scanf("%ld", &entero_largo); no & scanf("%s", cadena);

27

Funcin scanf() (y 2)
Ejemplo: lee un nmero entero y lo eleva al cuadrado:
#include <stdio.h> void main() {
int numero; int cuadrado; printf("Introduzca un numero:"); scanf("%d", &numero); cuadrado = numero * numero; printf("El cuadrado de %d es %d\n", numero,cuadrado);
Comenzar
ESCRIBIR Dame numero

LEER numero cuadrado=numero * numero

ESCRIBIR numero y cuadrado

FIN

}
28

Constantes simblicas
Para evitar el uso de valores constantes dentro del cdigo, se definen las constantes simblicas Suele escribirse en maysculas.
#define #define #define #define PI 3.141593 CIERTO 1 FALSO 0 AMIGA "Marta" no acaba en ;

29

Constantes o literales
Caracteres:
Ejemplos: "Marta ", " barco"

Valores enteros:
Notacin decimal: 987 Notacin hexadecimal: 0x25 0X25 Notacin octal: 034 Enteros sin signo: 485U Enteros de tipo long: 485L Enteros sin signo de tipo long: 485UL Valores negativos (signo menos): -987

Valores reales (coma flotante):


Ejemplos: 12, 14, 8., .34 Notacin exponencial: .2e+9, 1.04E-12 Valores negativos (signo menos): -12 -2e+9
30

Ejemplo.
Programa que lee el radio de un crculo y calcula su rea
#include <stdio.h> #define PI 3.141593 void main() { float radio; float area; printf("Introduzca el radio: "); scanf("%f", &radio); area = PI * radio * radio; printf("El area del circulo es %5.4f \n", area); }
Comenzar
PI =3.141593 ESCRIBIR Dame radio

LEER radio

area = PI * radio * radio

ESCRIBIR area

FIN

31

Ejercicios
Encuentra errores
include studio.h /* Programa que dice cuntos das hay en una semana /* main {} ( int d d := 7; print (Hay d das en una semana);

32

Ejercicios
Indica cul sera la salida de cada uno de los siguientes grupos de sentencias: a) printf ("Historias de cronopios y famas."); printf ("Autor: Julio Cortzar"); b) printf ("Cuntas lneas \nocupa esto?"); c) printf ("Estamos \naprendiendo /naprogramar en C"); d) int num; num = 2; printf ("%d + %d = %d", num, num, num + num);

33

Operadores y expresiones

34

Operadores y expresiones
Objetivos:
Mostrar el concepto de expresin, operador y sentencia. Mostrar el repertorio de operadores de C y el orden de precedencia.

Contenidos:
1. 2. 3. 4. Expresiones y sentencias Operador asignacin. Conversin de tipos Operadores aritmticos Operadores relacionales

5. Operadores lgicos 6. Operadores de asignacin compuestos 7. Precedencia


35

Expresiones y sentencias
Sentencia: especifica una accin a realizar
Ej. printf()

Expresin: secuencia de operadores y operandos que especifican un valor


Ej. 4+5

Una expresin se convierte en una sentencia cuando va seguida de un punto y coma. Cuando un grupo de sentencias se encierran entre llaves { }, forman un bloque, sintcticamente equivalente a una sentencia.
36

Operador de asignacin
Forma general: identificador = expresin ; Ejemplos:
a = 3; area = lado * lado;

El operador de asignacin = y el de igualdad == Asignaciones mltiples:


id_1 = id_2 = ... = expresin

Las asignaciones se efectan de derecha a izquierda. En i = j = 5


1. A j se le asigna 5 2. A i se le asigna el valor de j
37

Reglas de asignacin
Si los dos operandos en una sentencia de asignacin son de tipos distintos, entonces el valor del operando de la derecha ser automticamente convertido al tipo del operando de la izquierda. Adems:
1. Un valor en coma flotante se puede truncar si se asigna a una variable de tipo entero. 2. Un valor de doble precisin puede redondearse si se asigna a una variable de coma flotante de simple precisin. 3. Una cantidad entera puede alterarse si se asigna a una variable de tipo entero corto o a una variable de tipo carcter.

Es importante en C utilizar de forma correcta la conversin de tipos.

38

Conversin de tipos
(tipo de dato) expresin
int x; x = 5; y = x / 2; el valor asignado a la variable y ser 2, pues / realiza una divisin entera. int x; x = 5; y = (float) x / 2; Ahora, la variable y almacena el valor 2.5. int x; x = 5; y = (float) (x / 2); no se asigna a y el valor 2.5, sino 2, ya que los parntesis que envuelven a la expresin x / 2 hacen que primero se efecte la divisin entera y luego la conversin a flotante

39

Operadores aritmticos
Divisin entera ( / ): divisin de una cantidad entera por otra se desprecia la parte decimal del cociente. El operador % requiere que los dos operandos sean enteros. La mayora de las versiones de C asignan al resto el mismo signo del primer operando. Valores negativos con el signo OPERADOR UNARIOS -++ BINARIOS + * / % DESCRIPCIN Cambio de signo Decremento Incremento Resta Suma Producto Divisin Resto de divisin entera

40

Ejemplo
int x, y; x = 9; y = 2; la operacin x / y devuelve el valor 4, mientras que la operacin x % y devuelve 1. Sin embargo, despus de las sentencias float x; int y; x = 9.0; y = 2; la operacin x / y devuelve 4.5, no pudindose aplicar, en este caso, el operador % puesto que uno de los operandos no es entero.
41

Operadores incremento, decremento


La expresin
i++; ++i; i--; --i;

es equivalente a
i i i i = = = = i i i i + + 1; 1; 1; 1;

Si el operador sigue al operando el valor del operando se modificar despus de su utilizacin. Si el operador precede al operando el valor del operando se modificar antes de su utilizacin. Ejemplo: si a = 1 printf("a printf("a printf("a printf("a = = = = %d %d %d %d \n", \n", \n", \n", a); ++a); a++); a); Imprime: a a a a = = = = 1 2 2 3
42

Operadores relacionales
Se utilizan para formar expresiones lgicas. El resultado es un valor entero que puede ser: cierto, se representa con un 1 falso, se representa con un 0
BINARIOS

OPERADOR > >=

DESCRIPCIN Mayor que Mayor o igual que Menor que Menor o igual que Igual que Diferente que

Ejemplo 1: Si a = 1 y b = 2 Expresin a<b a>b (a + b) ! = 3 a == b a == 1 Valor 1 0 0 0 1 Interpretacin cierto falso falso falso cierto

< <= == !=

43

Operadores lgicos
Actan sobre operandos que son a su vez expresiones lgicas que se interpretan como: cierto, cualquier valor distinto de 0 falso, el valor 0

Tabla de verdad
a b F V F V !a V V F F a && b F F F V a || b F V V V
44

OPERADOR DESCRIPCIN UNARIOS BINARIOS ! && || not and or


F F V V

Ejemplo
&& y || se evalan de izquierda a derecha. ! se evala de derecha a izquierda.
Ejemplos: si a = 7 y b = 3
Valor 0 1 1 1 Interpretacin falso cierto cierto cierto

Expresin (a + b) < 10 !((a + b) < 10) (a ! = 2) || ((a +b) <= 10) (a > 4) && (b < 5)

45

Operadores de asignacin compuestos


El operador de asignacin se puede combinar con otros operadores como *, /, %, +, -, <<, >>, &, |, ^ para operaciones acumulativas
es equivalente a m *= 5; m += b; m += y - 3; m - = (y = 5); m = m * 5; m = m + b; m = m + y - 3; m = m - (y = 5);

46

Precedencia
Evaluacin a igual nivel de prioridad Nivel de prioridad 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 () ! * + << < == & ^ | && || ?: operadores de asignacin , 47 [] ~ / >> <= != > >= . ++ % Operadores

-> -(cast) * & sizeof

Ejercicios
Indica cules de los siguientes identificadores no son correctos y por qu. a) e) contador dias2 b) CONTADOR c) _hola f) 2dias d) hola_

g) Suma_Total h) Suma-Total

Sean x, y, z, u, v y t, variables que contienen, respectivamente, los valores 2, 3, 4, 5, 6 y 7, qu almacenarn despus de ejecutar las siguientes sentencias?
x++; y = ++z; t = - -v; v = x + (y *= 3) / 2; u = x + y / 2;
48

Ejemplo
Programa que convierte grados Fahrenheit a grados centgrados.
C = (5/9) * (F - 32) #include <stdio.h> void main() { float centigrados; float fahrenheit; printf("Introduzca una temperatura en grados fahrenheit: "); scanf("%f", &fahrenheit); centigrados = 5.0/9 * (fahrenheit - 32); printf("%f grados fahrenheit = %f grados centigrados \n", fahrenheit, centigrados); }

49

ERRORES COMUNES
Olvidar que el resultado de dividir dos enteros es entero Realizar divisin por cero Olvidar la prioridad de los operadores Errores en la conversin de tipos Confundir el operador de igualdad y el de asignacin

50

Funciones

51

Introduccin a funciones
Objetivos:
Introducir al alumno en el diseo estructurado. Presentar el concepto de funcin. Mostrar la definicin y declaracin de funciones en C.

Contenidos:
1. Introduccin al diseo estructurado. Concepto de funcin 2. Definicin de funciones
o Argumentos o Valor de retorno o Llamada a funcin

3. Declaracin de funciones. Prototipos 4. Ejemplos

52

Introduccin
Una funcin es un segmento de programa que realiza una determinada tarea. Todo programa C consta de una o ms funciones. Una de estas funciones se debe llamar main() Todo programa comienza su ejecucin en la funcin main() El uso de funciones permite la descomposicin y desarrollo modular. Permite dividir un programa en componentes ms reutilizacin pequeos.

53

Definicin de una funcin


tipo nombre_func (tipo1 arg1, ..., tipoN argN) { /* CUERPO DE LA FUNCION */ }
Los argumentos se denominan parmetros formales. La funcin devuelve un valor de tipo de dato tipo
Si se omite tipo se considera que devuelve un int Si no devuelve ningn tipo void Si no tiene argumentos void

void explicacion(void) Entre llaves se encuentra el cuerpo de la funcin (igual que main()). La sentencia return finaliza la ejecucin y devuelve un valor a la funcin que realiz la llamada. return(expresion); En C no se pueden anidar funciones
54

Declaracin de funciones: prototipos


No es obligatorio pero si aconsejable. Permite la comprobacin de errores entre las llamadas a una funcin y la definicin de la funcin correspondiente.

tipo nombre_func (tipo1 arg1, ..., tipoN argN);

55

Llamadas a funciones
Para llamar a una funcin se especifica su nombre y la lista de argumentos sin poner el tipo de dato.

nombre_func (var1,var2,,varN);
Parmetros formales: los que aparecen en la definicin de la funcin. Parmetros reales: los que se pasan en la llamada a la funcin. En una llamada habr un argumento real por cada argumento formal, respetando el orden de la declaracin. Los parmetros reales pueden ser:
Constantes. Variables simples. Expresiones complejas.

Deben ser del mismo tipo de datos que el argumento formal correspondiente. Cuando se pasa un valor a una funcin se copia el argumento real en el argumento formal.

56

Paso de parmetros por valor


En las llamadas por valor se hace una copia del valor del argumento en el parmetro formal. La funcin opera internamente con estos ltimos. Como las variables locales a una funcin (y los parmetros formales lo son) se crean al entrar a la funcin y se destruyen al salir de ella, cualquier cambio realizado por la funcin en los parmetros formales no tiene ningn efecto sobre los argumentos.

57

Ejemplo
Programa que calcula el mximo de dos nmeros.

58

Ejemplo:
Funcin que calcula x elevado a y (con y entero)
#include <math.h> float potencia (float x, int y); /* prototipo */ float potencia (float x, int y) /* definicin */ { int i; float prod = 1; prod = pow(x,y); return(prod); }
59

Ejemplo 3
Programa que indica si un nmero es cuadrado perfecto.
#include <stdio.h> #include <math.h> #define TRUE 1 #define FALSE 0 void explicacion(void); int cuadrado_perfecto(int x); void main() { int n, perfecto; explicacion(); scanf("%d", &n); perfecto = cuadrado_perfecto(n); if (perfecto) printf("%d es cuadrado perfecto.\n", n); else printf("%d no es cuadrado perfecto.\n", n); }

60

Ejemplo 3 - Continuacin
void explicacion(void) { printf("Este programa dice si un numero "); printf("es cuadrado perfecto \n"); printf("Introduzca un numero: ); } int cuadrado_perfecto(int x) { int raiz; int perfecto; raiz = (int) sqrt(x); if (x == raiz * raiz) perfecto = TRUE; /* cuadrado perfecto */ else perfecto = FALSE; /* no es cuadrado perfecto */ return(perfecto); }
61

Paso de parmetros por referencia


Hasta ahora las funciones solo devolvan un valor, pero qu pasa si tienen que devolver ms? En este caso, se requiere pasar parmetros por referencia La declaracin de una funcin en este caso sera void nombreFunc (tipo in1, ..., tipo inN, tipo *out1, tipo *outN)
{ /* CUERPO DE LA FUNCION */ }

La llamada a la funcin nombre_func (in1, ..., inN, &out1, , &outN);


62

Paso de parmetros por referencia (II)


En este tipo de llamadas los argumentos contienen direcciones de variables. Dentro de la funcin la direccin se utiliza para acceder al argumento real. En las llamadas por referencia cualquier cambio en la funcin tiene efecto sobre la variable cuya direccin se pas en el argumento. No hay un proceso de creacin/destruccin de esa direccin. Aunque en C todas las llamadas a funciones se hacen por valor, pueden simularse llamadas por referencia utilizando los operadores & (direccin) y * (en la direccin). Mediante & podemos pasar direcciones de variables en lugar de valores, y trabajar internamente en la funcin con los contenidos, mediante el operador *.
63

Ejemplo 3 con parmetros por referencia


void explicacion ( int *numero) { printf("Este programa dice si un numero "); printf("es cuadrado perfecto \n"); printf("Introduzca un numero: ); scanf("%d", *&n); } void main() { int n, perfecto; explicacion(&n); perfecto = cuadrado_perfecto(n); .. }

64

Ejercicio 4
Programa que calcula la hipotenusa de un tringulo rectngulo. h = (a2 + b2) Pasos a seguir:
1. Leer a y b funcin leer 2. Calcular h segn la frmula dada definimos una funcin hipotenusa 3. Imprimir el valor de h usar printf().

65

Solucin
#include <stdio.h> #include <math.h> void hipotenusa(float a, float b, float *h) { *h = sqrt(pow(a,2) + pow(b, 2)); } void leer (float *a, float *b) { printf("Dame valores a y b:\n"); scanf("%f %f", *&a, *&b); }
66

void main() { float a, b, h; leer (&a,&b); hipotenusa(a,b,&h); printf("La hipotenusa es %f\n", h); }

Recapitulacin
Antes de escribir un programa:
Leerlo detenidamente Hacer pseudocdigo o diagrama de flujo Decidir divisin en funciones Determinar parmetros de entrada y salida Desde main() invocar a las funciones

67

Sentencias de control

68

Estructuras de control
Objetivos:
Introducir los tres tipos bsicos de sentencias de control: secuencia, seleccin e iteracin. Explicar la sintaxis y la semntica de las sentencias de control dedicadas a definir estructuras de seleccin.

Contenidos:
1. Tipos de estructuras 2. Estructuras condicionales
o Instruccin if - else o Instruccin switch

3. Instruccin break

69

Tipos de estructuras
Secuencia: ejecucin sucesiva de dos o ms operaciones. Seleccin: se realiza una u otra operacin, dependiendo de una condicin. Iteracin: repeticin de una operacin mientras se cumpla una condicin.

70

If - else
if (expresin) sentencia; o bien if (expresin) sentencia; else sentencia;

71

Ejemplo if - else
Programa que lee un nmero y dice si es par o impar. #include <stdio.h> main() { int numero; /* Leer el numero */ printf("Introduzca un numero: "); scanf("%d", &numero); if ((numero % 2) == 0) printf("El numero %d es par.\n", numero); else printf("El numero %d es impar.\n", numero); }
72

Operador condicional
Se utiliza para sentencias if-else simples y=(x>9 ? 100 : 200);

if (x > 9) { y=100; } else { y=200;


}

LO MISMO

73

switch
Tipo entero o letra

switch (variable) { case cte1: sentencia; break; case cte2: sentencia; break; ... ... default: sentencia; }
74

Ejemplo switch
#include <stdio.h> void main() { char letra; printf("Introduzca una letra: "); scanf("%c", &letra); switch(letra) { case 'a': case 'A': printf("Vocal %c\n", letra); break; case 'e': case 'E': printf("Vocal %c\n", letra); break; case 'i': case 'I': printf("Vocal %c\n", letra); break; case 'o': case 'O': printf("Vocal %c\n", letra); break; case 'u': case 'U': printf("Vocal %c\n", letra); break; default: printf("Consonante %c\n", letra); } }
75

Bucles
Objetivos:
Explicar la sintaxis y la semntica de las sentencias de control dedicadas a definir estructuras de iteracin. Mostrar patrones habituales de concatenacin de sentencias de control con vistas a su utilizacin en el seno de un programa real.

Contenidos:
1. Bucles
a. Instruccin for b. Instruccin while c. Instruccin do - while

2. Instrucciones break y continue 3. Bucles anidados


76

Instruccin for
for (inicializacin; condicin; incremento) sentencia;
Inicializacin: se inicializa algn parmetro que controla la repeticin del bucle. Condicin: es una condicin que debe ser cierta para que se ejecute sentencia. Incremento: se utiliza para modificar el valor del parmetro. El bucle se repite mientras condicin no sea cero (falso). Si sentencia es compuesta se encierra entre { } incializacin e incremento se pueden omitir. Si se omite condicin se asumir el valor permanente de 1 (cierto) y el bucle se ejecutar de forma indefinida.
77

Ejemplo for
Programa que imprime los 100 primeros nmeros #include <stdio.h> void main() { int numero; for (numero=0; numero <100; numero++) printf("%d\n", numero); }

78

Instruccin while
while (expresin) sentencia;
sentencia se ejecutar mientras el valor de expresin sea verdadero (distinto de 0). Primero se evala expresin. Lo normal es que sentencia incluya algn elemento que altere el valor de expresin, proporcionando la condicin de salida del bucle. Si la sentencia es compuesta se encierra entre { }
79

Ejemplo while
lee un nmero N y calcula 1 + 2 + 3 + + N
#include <stdio.h> void main() { int N; int suma = 0; /* leer el numero N */ printf("N: "); scanf("%d", &N); while (N > 0) { suma = suma + N; N = N - 1; /* equivalente a N-- */ } printf("1 + 2 +...+ N = %d\n", suma); }
80

do - while
do sentencia; while (expresin);
sentencia se ejecutar mientras el valor de expresin sea verdadero (distinto de 0). sentencia siempre se ejecuta al menos una vez (diferente a while). Lo normal es que sentencia incluya algn elemento que altere el valor de expresin, proporcionando la condicin de salida del bucle. Si la sentencia es compuesta se encierra entre { } Para la mayora de las aplicaciones es mejor y ms natural comprobar la condicin antes de ejecutar el bucle (while).

81

Ejemplo do -while
Programa que lee de forma repetida un nmero e indica si es par o impar. El programa se repite mientras el nmero sea distinto de cero.
#include <stdio.h> void main() { int numero; do { /* se lee el numero */ printf("Introduzca un numero: "); scanf("%d", &numero); if ((numero % 2) == 0) printf("El numero %d es par.\n", numero); else printf("El numero %d es par.\n", numero); } while (numero != 0) }

82

Bucles anidados
Los bucles se pueden anidar pero es importante estructurarlos de forma correcta. Ejemplo: Calcular 1 + 2 + N mientras N sea distinto de 0.

#include <stdio.h> main() { int N, suma, j; do { /* leer el numero N */ printf("Introduzca N: "); scanf("%d", &N); suma = 0; for (j = 0; j <= N; j++) /* bucle anidado */ suma = suma + j; printf("1 + 2 + ... + N = %d\n", suma); } while (N > 0); /* fin del bucle do */ }

83

Instruccin break
Se utiliza para terminar la ejecucin de bucles o salir de una sentencia switch. Es necesaria en la sentencia switch para transferir el control fuera de la misma. En caso de bucles anidados, el control se transfiere fuera de la sentencia ms interna en la que se encuentre, pero no fuera de las externas. No es aconsejable el uso de esta sentencia en bucles pues es contrario a la programacin estructurada. Puede ser til cuando se detectan errores o condiciones anormales.

84

Ej.

#include <stdio.h> void main() { int opcion; printf ("1 - Mensaje pantalla \n"); printf ("2 - salir \n"); printf (" cualquier carcter, no hace nada\n"); printf("Elija la opcin: "); scanf("%d", &opcion); while (opcion) { switch(opcion) { case 1: printf("Hola, selecciono opcion %d\n" , opcion); break; case 2: printf ("Adios \n"); return; break; default: printf("Seleccion invalida. Intentelo de nuevo\n"); } printf("Elija la opcion: "); scanf("%d", &opcion); } }

85

Sentencia continue
Esta sentencia se utiliza en los bucles for, while y do/while. Cuando se ejecuta, fuerza un nuevo ciclo del bucle, saltndose cualquier sentencia posterior.

86

Ejemplo continue
#include <stdio.h> #include <conio.h> void main () { int n; int positivos = 0; do { printf ("\n Teclea un nmero (-99 finaliza): "); scanf ("%d", &n); if (n <= 0) continue; positivos++; } while (n != -99); printf ("\n Has tecleado %d nmeros positivos", positivos); } La sentencia positivos++ slo se ejecuta cuando n es un nmero positivo. Si n es negativo o vale 0, se ejecuta continue que fuerza una nueva evaluacin de la condicin de salida del bucle.

87

Tabla de comparativas
Valores iniciales, operaciones previas for 1 campo Cond. para seguir repitiendo 2 campo Cuando se comprueba Cambios que hay que hacer pueden quedar campos vacos? si

Antes de cada 3 campo vuelta

while

Hay que ponerlo fuera, antes del ciclo Hay que ponerlo fuera, antes del ciclo

En el while entre parntesis

Antes de cada Dentro del ciclo vuelta despus de las instrucciones a repetir Despus de cada vuelta Dentro del ciclo despus de las instrucciones a repetir

No

do while

En el while entre parntesis

no

88

Ejercicios
Escriba un programa que calcule xn, siendo x y n dos nmeros que se introducen por teclado
#include <stdio.h> void main() { int n,x,i; float potencia=1; printf("Dame x y n \n: "); scanf("%d %d", &x, &n); for (i=0; i<n ; i++) { potencia=potencia * x; } printf("El resultado es: %f\n", potencia); }
89

Escriba un programa que calcule e imprima la suma de los pares y de los impares comprendidos entre dos valores que se piden por teclado (x y n)
#include <stdio.h> void leer (int *a, int *b) { do{ printf("Solicito dos numeros a<b \n"); printf("Dame a y b \n: "); scanf("%d %d", *&a , *&b); } while (a>b); } void calcula (int x, int n) { int i, int par=0, impar=0; for (i=x; i<=n; i++ ) { if ((i%2)==0) par+=i; else impar+=i; } printf("El resultado suma par: %d e impar: %d \n", par, impar); }

void main() { int n,x; leer (&x,&n); calcula(x,n); }

90

Ejemplo - funciones y bucles


#include <stdio.h> mensaje () { printf ("\nTeclee un nmero (0 finaliza): "); } int lee_numero () { int n; scanf ("%d", &n); return n; } cuadrado (int x) { printf ("\nEl cuadrado es %d", x * x); } void main () { int t; for (mensaje (); t = lee_numero (); cuadrado (t)); }

91

Recursividad

92

Recursividad
Objetivos:
Repaso: paso de parmetros por valor y por referencia a una funcin. Mostrar la capacidad de la recursin y las funciones recursivas.

Contenidos:
1.Paso de parmetros a una funcin 2.Recursividad

93

Paso de parmetros por valor


En las llamadas por valor se hace una copia del valor del argumento en el parmetro formal. La funcin opera internamente con estos ltimos. Como las variables locales a una funcin (y los parmetros formales lo son) se crean al entrar a la funcin y se destruyen al salir de ella, cualquier cambio realizado por la funcin en los parmetros formales no tiene ningn efecto sobre los argumentos.

94

Ejemplo

95

Paso de parmetros por referencia


En este tipo de llamadas los argumentos contienen direcciones de variables. Dentro de la funcin la direccin se utiliza para acceder al argumento real. En las llamadas por referencia cualquier cambio en la funcin tiene efecto sobre la variable cuya direccin se pas en el argumento. No hay un proceso de creacin/destruccin de esa direccin. Aunque en C todas las llamadas a funciones se hacen por valor, pueden simularse llamadas por referencia utilizando los operadores & (direccin) y * (en la direccin). Mediante & podemos pasar direcciones de variables en lugar de valores, y trabajar internamente en la funcin con los contenidos, mediante el operador *.
96

Ejemplo
#include <stdio.h> void funcion(int *a, int *b); /* prototipo */ main() { int x = 2; int y = 5; printf("Antes x = %d, y = %d\n", x, y); funcion(&x, &y); printf("Despues x = %d, y = %d\n", x, y); } void funcion(int *a, int *b) { *a = 0; *b = 0; printf("Dentro *a = %d, *b = %d\n", *a, *b); return; }

x, y punteros

97

Ejemplo
Funcin que intercambia el valor de dos variables. #include <stdio.h> void swap_ref (int *a, int *b); /* prototipo */ void main() { int x = 2; int y = 5; printf("Antes x = %d, y = %d\n", x, y); swap(&x, &y); printf("Despues x = %d, y = %d\n", x, y); } void swap_ref (int *a, int *b) { int temp; temp = *b; *b = *a; *a = temp; }
98

Recursividad
Una funcin se llama a s misma de forma repetida hasta que se cumpla alguna condicin.

Ejemplo: el factorial de un nmero: long int factorial(int n) { if (n <= 1) return(1); else return(n * factorial(n-1)); }
99

Ejemplo torres de Hanoi


#include <stdio.h> void transferir( int n, char desde, char hacia, char temp); void main() { int n; printf ("Bienvenido a las torres de Hanoi \n"); printf ("Cuntos discos?\n"); scanf("%d", &n); transferir(n,'I','D','C'); }

Izquierda

Centro

Derecha

100

Ejemplo torres de Hanoi (y 2)


void transferir(int n, char desde, char hacia, char temp) { /* transferir n discos de un pivote a otro*/ /* n = numero de discos desde = origen hacia = destino temp = almacenamiento temporal */ if (n>0) { transferir (n-1, desde, temp, hacia); printf ("mover disco %d desde %c hasta %c\n", n, desde, hacia); transferir (n-1, temp, hacia,desde); } return; }
101

Arrays (listas y tablas)

102

Arrays (listas y tablas)


Objetivos:
Introducir el concepto de tipo de dato estructurado. Mostrar la representacin de datos mediante arrays unidimensionales y multidimensionales. Conocer la representacin de cadenas de caracteres y las funciones de manipulacin.

Contenidos:
1. Arrays
o o o o Declaracin Subndices Almacenamiento en memoria Tamao de los arrays

2. Inicializacin de un array 3. Array de caracteres y cadenas de texto 4. Arrays multidimensionales

103

Listas
Conjunto de datos del mismo tipo a los que se da un nombre comn y a los que se accede a travs de un ndice tipo_dato variable_lista[num_elementos]; int numeros[20]; float temperaturas[100]; En un vector de N elementos, el primero se referencia con el ndice 0 y el ltimo con el ndice N-1 Inicializacin
int numeros[2]={0,1} int numeros[]={0,1} el compilador asume array de 2 elementos

El procesamiento se debe hacer elemento a elemento


104

Listas
cmo se utilizan?
Usar un elemento de la lista variable_lista[posicion]; Pasar a funciones
en la declaracin

Empieza en 0

temperaturas[10];

void nombreFuncion (int variable)


en la llamada a la funcin

nombreFuncion (variable_lista[posicion])
105

Listas de nmeros
cmo se utilizan?
Usar toda la lista. Podemos:
Copiar una lista en otra

memcpy (listadestino,listaorigen,tamao)
Pasar la lista a una funcin Sean de entrada o salida, no requieren *

void nombreFuncion (int nombreLista[TAMAO]) nombreFuncion ( nombreLista );


Ojo, corchetes
106

Listas de nmeros
cmo se utilizan?
Usar toda la lista. Podemos:
Pasar la lista a una funcin de tamao ajustado

void nombreFuncion (int tamano, int nombreLista[tamano]) nombreFuncion ( tamano, nombreLista );


Se debe declarar la lista dentro de un bloque Antes debe ser conocida la variable tamano La lista slo es conocida dentro del bloque
107

Ejemplo lista tamao fijo


#include <stdio.h> #define TAM_VECTOR 10 void leer (int vector_a[TAM_VECTOR]) { int j; /* variable utilizada como indice */ for (j = 0; j < TAM_VECTOR; j++) { printf("Elemento %d: ", j); scanf("%d", &vector_a[j]); } } void copiar (int vector_a[TAM_VECTOR], int vector_b[TAM_VECTOR]) { int j; for (j = 0; j < TAM_VECTOR; j++) vector_b[j] = vector_a[j]; } void escribir (int vector[TAM_VECTOR]) { int j; for (j = 0; j < TAM_VECTOR; j++) printf("El elemento %d es %d \n", j, vector[j]); }

void main() { int vector_a[TAM_VECTOR]; int vector_b[TAM_VECTOR]; leer ( vector_a); copiar (vector_a, vector_b); escribir (vector_b); }

108

Ejemplo lista tamao variable


#include <stdio.h> void leer (int cuantos, float lista[cuantos]) { int i; printf ("teclealos :\n"); for (i=0 ; i< cuantos ; i++) { scanf("%f", &lista[i]); } } void pintar(int cuantos, float lista[cuantos]) { int i; for (i=0 ; i< cuantos ; i++) { printf("%i\n", lista[i]); } } void main() { int cuantos; printf ("dame cuantos \t"); scanf("%i", &cuantos); { float lista[cuantos]; leer(cuantos,lista); pintar (cuantos, lista); } }

109

Ordenacin elementos de lista


#include <stdio.h> #include <stdlib.h> int comparar (int *num1, int *num2) return ((*num1)-(*num2)); } {

void main() { int cuantos; printf ("dame cuantos \t"); scanf("%i", &cuantos); { float lista[cuantos]; leer(cuantos,lista); qsort(lista,cuantos, sizeof(lista[0],comparar); pintar (cuantos, lista); } }

110

La funcin sizeof()
Devuelve el tamao en bytes que ocupa un tipo o variable en memoria.
#include <stdio.h> main() {
char cadena[10]; printf("un int ocupa %d bytes\n", sizeof(int)); printf("un char ocupa %d bytes\n", sizeof(char)); printf("un float ocupa %d bytes\n", sizeof(float)); printf("un double ocupa %d bytes\n", sizeof(double)); printf(" cadena ocupa %d bytes\n", sizeof(cadena));

}
111

Algoritmos de ordenacin y bsqueda


Transparencias en pdf aparte

112

Cadenas de caracteres
Un caso particular de lista es la cadena de caracteres. Se declara: char nombre[num_car]; y permite almacenar num_car-1 caracteres y el carcter nulo '\0' de terminacin. char frase[21]; es apta para almacenar 20 caracteres y el nulo. C permite la inicializacin de cadenas de caracteres en la declaracin, mediante sentencias del tipo char cadena[ ] = "Esto es una cadena de caracteres"; en la que no es necesario aadir el nulo final ni indicar el tamao, pues lo hace automticamente el compilador. Generalmente se utiliza tamao por exceso, no se suele preguntar al usuario cuntos caracteres va a introducir
113

Cadenas de caracteres
Cmo se utilizan?
Usar un elemento de la lista. Igual que lista de nmeros. Usar toda la lista. Hay diferencias:
Leer una lista de letras con una sola instruccin scanf (%s, palabra) scanf (%[^\n], frase) Escribir una lista de letras printf (%s, palabra) Copiar una lista de letras <string.h> strcpy (str_destino, str_origen)
114

coge hasta espacio o fin de lnea coge hasta fin de lnea

biblioteca estndar string.h


char *strcat (char *cad1, const char *cad2) Concatena cad2 a cad1 devolviendo la direccin de cad1. Elimina el nulo de terminacin de cad1 inicial. char *strcpy (char *cad1, const char *cad2) Copia la cadena cad2 en cad1, sobreescribindola. Devuelve la direccin de cad1. El tamao de cad1 debe ser suficiente para albergar a cad2. int strlen (const char *cad) int isalnum (int ch) int isalpha (int ch) int isdigit (int ch) int islower (int ch) int isupper (int ch) int tolower (int ch) int toupper (int ch) Devuelve el nmero de caracteres que almacena cad (sin contar el nulo final). Devuelve 1 si ch es alfanumrico (letra del alfabeto o dgito) y 0 en caso contrario. Devuelve 1 si ch es una letra del alfabeto y 0 en caso contrario. Devuelve 1 si ch es un dgito del 0 al 9, y 0 en caso contrario. Devuelve 1 si ch es un letra minscula y 0 en caso contrario. Devuelve 1 si ch es una letra mayscula y 0 en caso contrario. Devuelve el carcter ch en minscula. Si ch no es una letra mayscula la funcin devuelve ch sin modificacin. Devuelve el carcter ch en mayscula. Si ch no es una letra minscula la funcin devuelve ch sin modificacin.
115

Ejemplo: lectura y escritura de cadenas de caracteres


#include <stdio.h> #define TAM_CADENA 80 main() { char cadena[TAM_CADENA]; printf("Introduzca una cadena: "); scanf("%s", cadena); printf("La cadena es %s\n", cadena); }

no requiere &

scanf deja de buscar cuando encuentra un blanco si se introduce Hola a todos, solo se leer Hola. No es necesario el operador de direccin (&) ya que cadena representa de forma automtica la direccin de comienzo.
116

Ejemplo: lectura y escritura de cadenas de caracteres (y 2)


La funcin gets lee una lnea completa hasta que encuentre el retorno de carro incluyendo los blancos. La funcin puts escribe una cadena de caracteres junto con un salto de lnea.
#include <stdio.h> #define TAM_LINEA 80 main() { char linea[TAM_LINEA]; printf("Introduzca una linea: \n"); gets(linea); puts("La linea es"); puts(linea); } Son equivalentes: puts("La linea es:");

printf("La linea es: \n");

117

Ej.

Programa que lee una palabra y la escribe al revs

#include <stdio.h> #include <string.h> #define MAXLETRAS 20 void leer (char palabra[MAXLETRAS]) { printf ("\nTeclee una cadena de caracteres: "); scanf(%s, palabra); } void escribir (char palabra[MAXLETRAS]) { int primera=0, ultima=0, i; ultima=strlen(palabra)-1; for (i=ultima; i>=primera; i--) printf(%c,palabra[i]); } void main (void) { char palabra[MAXLETRAS]; leer(palabra); escribir(palabra); }

118

Ej.

El programa siguiente hace uso de alguna de las funciones anteriores para examinar una cadena de caracteres y convertir las minsculas a maysculas y viceversa. Adems cuenta cuntos caracteres son dgitos numricos.

#include <stdio.h> #include <string.h> #define MAXLETRAS 100 void leer (char cadena [MAXLETRAS]) { printf ("\nTeclee una cadena de caracteres: "); gets (cadena); } void escribir (char cadena[MAXLETRAS]) { int i, contador=0; for (i = 0; i <= strlen (cadena); i++) { if (isupper (cadena[i])) cadena[i] = tolower (cadena[i]); else if (islower (cadena[i])) cadena[i] = toupper (cadena[i]); else if (isdigit (cadena[i])) contador++; } printf ("\nLa cadena tiene %d dgitos numricos\n", contador); puts (cadena); } void main (void) { char frase[MAXLETRAS]; leer(frase); escribir(frase); }

119

Vectores multidimensionales
Un vector multidimensional se declara: tipo_dato vector[exp1] [exp2] ... [expN]; Matrices o vectores de 2 dimensiones: int matriz[20][30]; define una matriz de 20 filas por 30 columnas. Generalmente se declaran por exceso. La numeracin comienza en 0.
120

Tablas
Cmo se utilizan?
Usar un elemento de la tabla tabla[fila][columna] Pasar un elemento a una funcin.
llamada nombreFuncion (arg1,.., nombretabla[fila][columna]) declaracin void nombreFuncion (tipo arg1,, tipo variablesimple)

Usar una columna de la tabla: NO SE PUEDE EN C


121

Tablas
Usar un vector de la tabla como argumento a una funcin: tabla[fila]
declaracin void nombreFuncion (tipo arg1,, tipo lista[COLUMNAS]) llamada nombreFuncion (arg1,.., nombretabla[fila]);

Usar una tabla completa


Copiar memcpy(destino, origen,tamao) Ej: memcpy ( clientes2, clientes1, sizeof(int)*filas*columnas) Parmetro de una funcin
Declaracin de funcin

void nombreFuncion (tipo arg1,, tipo tabla[FILAS][COLUMNAS])


Llamada a una funcin

nombreFuncion (arg1,, tabla)


122

Ejemplo
#include <stdio.h>

Leer dos matrices de dimensiones indicadas por el usuario y escribir su suma

void sumar(int filas, int columnas, float tabla1[filas][columnas], float tabla2[filas][columnas]) { int i,j, acumulador=0; for (i=0;i<filas;i++) { for (j=0;j<columnas;j++) { printf("%f \t", tabla1[i][j]+tabla2[i][j]); } printf("\n"); } } void leer(int filas, int columnas, float tabla[filas][columnas]) { int i,j; printf("dame tabla:\n"); for (i=0;i<filas;i++) { for (j=0;j<columnas;j++) { scanf("%f", &tabla[i][j]); } } }

void main() { int filas, columnas; printf("dame filas y columnas: \n"); scanf("%i %i", &filas, &columnas); { float tabla1[filas][columnas], tabla2[filas][columnas]; leer(filas,columnas, tabla1); leer(filas,columnas, tabla2); sumar(filas, columnas,tabla1, tabla2); } }

123

Ejemplo
Funcin que calcula el producto de dos matrices cuadradas.
void multiplicar(float a[DIM][DIM], float b[DIM][DIM], float c[DIM][DIM]) { int i, j, k; for(i = 0; i < DIM; i++) for(j = 0; j < DIM; j++) { c[i][j] = 0.0; for(k = 0; k < DIM; k++) c[i][j] += a[i][k] * b[k][j]; } }
124

Ej.:

Leer lista de palabras y contar el n de veces que est una palabra que solicita el usuario

#include <stdio.h> #include <string.h> #define MAX 30 /*incluye el fin de lnea*/

void main() { int numpal; void leer(int numpal, int columnas, char tabla[numpal][MAX], char pal[MAX]) printf("dame n palabras: \n"); { scanf("%i", &numpal); int i; printf("dame palabras:\n"); { char tabla[numpal][MAX], pal[MAX]; for (i=0;i<numpal;i++) { leer(numpal, tabla, pal); scanf("%s",tabla[i]); calcular(numpal,tabla,pal); } } printf("dame palabra a buscar:\n"); } scanf("%s",pal); } void calcular(int numpal, int columnas, char tabla[numpal][MAX], char pal[MAX]) { int i,suma=0; for (i=0;i<numpal;i++) { if (strcmp(listapal[i],pal)==0) { suma ++; } } printf(la palabra buscada %s, aparece %d veces\,pal, suma); }

125

Estructuras y uniones

126

Estructuras y uniones
Objetivos:
Conocer la posibilidad de definir tipos de datos estructurados con campos heterogneos mediante el uso de estructuras. Explicar la posibilidad de combinar tipos de datos estructurados. Mostrar los tipos union.

Contenidos:
1. Estructuras
o Concepto de campo o Declaracin e inicializacin

2. 3. 4. 5.

Acceso a estructuras Declaracin typedef Combinacin de datos estructurados Campos variables con el uso de union

127

Estructuras
Es una estructura de datos compuesta de elementos individuales que pueden ser de distinto tipo. Cada uno de los elementos de una estructura se denomina miembro. Declaracin de una estructura:
struct nombre_estructura { tipoDato1 miembro_1; tipoDato2 miembro_2; . . tipoDatoN miembro_N; };

Los miembros pueden ser de cualquier tipo excepto void


128

Ejemplo
Declaracin de una estructura denominada CD. struct CD { char titulo[100]; char artista[50]; int num_canciones; int anio; Euros precio; }; Declaracin de una variable denominada cd1 de tipo struct CD. struct cd1 CD; Se pueden copiar estructuras, pero NO comparar:
struct CD cd1,cd2; cd2 = cd1;
129

Inicializacin de una estructura


Dos formas:
En la declaracin:
struct CD { char titulo[100]; char artista[50]; int num_canciones; int anio; Euros precio; } cd1= {Un sueo de verano,Miguel Rios,1989,10};

En el programa:
struct CD cd1; strcpy(cd1.titulo, Un sueo de verano"); strcpy(cd1.artista, Miguel Rios"); cd1.num_canciones = 2; c1.anio = 1989;
130

Acceso a una estructura


Los miembros de una estructura se procesan individualmente. Para hacer referencia a un miembro determinado, se utiliza el operador

. si la variable es de tipo estructura


variable_estructura.miembro

O, se utiliza el operador -> si la variable es de tipo puntero a estructura


variable_estructura->miembro

Ejemplo: imprimir la fecha de hoy


struct fecha { int dia, mes, anio; }; struct fecha hoy; struct fecha *ayer; printf("%d: %d: %d\n", hoy.dia,hoy.mes, hoy.anno); printf("%d: %d: %d\n", ayer->dia, ayer-> mes, ayer-> anno);

131

Ejemplo
#include <stdio.h> struct fecha { int dia; int mes; int anno; }; struct cuenta { int cuenta_no; char nombre[80]; float saldo; struct fecha ultimo_pago; };
132

Ejemplo (y 2)
main() { struct cuenta c1, c2; /* rellena la estructura c1 */ c1.cuenta_no = 2; strcpy(c1.nombre, "Pepe"); c1.saldo = 100000; c1.ultimo_pago.dia = 12; c1.ultimo_pago.mes = 5; c1.ultimo_pago.anno = 1997; /* asignacion de estructuras */ c2 = c1; printf("No. Cuenta %d \n", c2.cuenta_no); printf("Nombre %s \n", c2.nombre); printf("Saldo %f \n", c2.saldo); printf("Fecha de ultimo pago: %d:%d:%d \n", c2.ultimo_pago.dia, c2.ultimo_pago.mes, c2.ultimo_pago.anno); }

133

Combinacin de datos estructurados: vector de estructuras


Programa que permita introducir las piezas de un almacn (tipo, nombre, nro, precio) e imprimirlas

#include <stdio.h> #include <string.h> #define NUMCAJAS 3 typedef struct { char pieza[20]; int cantidad; char existe; } registro_piezas;

Caja N caja ...

Caja 1

/* Tipo de pieza. /* Nmero de piezas.

*/ */ */

float precio_unitario; /* Precio de cada pieza. /* Comprobar si el registro existe. */

134

main() { registro_piezas cajas[NUMCAJAS]; int registro=0; int i; do { /* Leer el nombre de la pieza. */ printf("Nombre de la pieza => "); scanf("%s", cajas[registro].pieza); /* Leer el nmero de piezas. */ printf("Numero de piezas => "); scanf("%d", &cajas[registro].cantidad); /* Leer el precio de cada pieza. */ printf("Precio de cada pieza => "); scanf("%f", &cajas[registro].precio_unitario); /* Indicar que el registro tiene datos, V */ cajas[registro].existe = 'V'; registro ++; } while (registro < NUMCAJAS);

135

Cont.
/* Imprimir la informacin. */ for(registro = 0; registro < NUMCAJAS; registro++) { if(cajas[registro].existe == 'V') { printf("La caja %d contiene:\n", registro + 1); printf("Pieza => %s\n", cajas[registro].pieza); printf("Cantidad => %d\n", cajas[registro].cantidad); printf("Precio unitario => $%f\n", cajas[registro].precio_unitario); } } /* Fin for. */ } /*fin main*/

136

Paso de estructuras a funciones


Una funcin puede devolver una estructura. Se pueden pasar miembros individuales y estructuras completas a una funcin. Si la estructura es grande, el tiempo para copiar un estructura (paso por valor) es prohibitivo, por eso se aconseja pasarlo por referencia. Paso de miembros individuales
struct punto { float x; float y; }; void imprime_x (float x) { printf ("el valor de x %f", x); } /*llamada a funcin*/ imprime_x (p1.x);
137

Paso de estructuras a funciones por valor


Ej.: leer y escribir una fecha.
#include <stdio.h> struct fecha { int dia; int mes; int anno; }; void imprimir_fecha(struct fecha f) { printf("Dia: %d\n", f.dia); printf("Mes: %d\n", f.mes); printf("Anno: %d\n", f.anno); return; } } main() { struct fecha fecha_de_hoy; fecha_de_hoy = leer_fecha(); imprimir_fecha(fecha_de_hoy); } struct fecha leer_fecha(void) { struct fecha f; printf("Dia: "); scanf("%d", &(f.dia)); printf("Mes: "); scanf("%d", &(f.mes)); printf("Anno: "); scanf("%d", &(f.anno)); return(f);

138

Paso de estructuras a funciones por referencia


void leer_punto(struct punto *p); void imprimir_punto(struct punto p); struct punto { float x; float y; }; main() { struct punto p1; leer_punto(&p1); imprimir_punto(p1); }
139

void leer_punto(struct punto *p) { printf("x = "); scanf("%f", &(p->x)); printf("y = "); scanf("%f", &(p->y)); } void imprimir_punto(struct punto p) { printf("x = %f\n", p.x); printf("y = %f\n", p.y); }

Uniones
Una union contiene miembros cuyos tipos de datos pueden ser diferentes (igual que las estructuras). Su declaracin es similar a las estructuras:
union nombre_estructura { tipoDato1 miembro_1; tipoDato2 miembro_2; . . tipoDatoN miembro_N; };

Todos los miembros que componen la union comparten la misma zona de memoria ahorro de memoria. Una variable de tipo union slo almacena el valor de uno de sus miembros.
140

Ejemplo
#include <stdio.h> #include <stdlib.h> union numero { int entero; float real; }; main() { union numero num; /* leer un entero e imprimirlo */ printf("Entero: "); scanf("%d", &(num.entero)); printf("El entero es %d\n", num.entero); /* leer un real e imprimirlo */ printf("Real: "); scanf("%f", &(num.real)); printf("El entero es %f\n", num.real); }
141

2
entero real

Combinacin de datos estructurados: vector de estructuras y union


struct ALUMNO { char grupo[15]; int asignat; char repite; }; struct PROFESOR { char nrp[16]; char cargo[21]; }; union AL_PR { struct ALUMNO al; struct PROFESOR pr; }; struct DATOS { char tipo; char nombre[40]; int edad; char direccion[40]; char telefono[15]; union AL_PR ambos; } personal[100];
142
Persona 1 Persona n Persona ...

El siguiente segmento de programa muestra los datos de la matriz personal.


for (i = 0; i < 100; i++) { printf ("\nNombre: %s", personal[i].nombre); printf ("\nEdad: %d", personal[i].edad); printf ("\nDireccin: %s", personal[i].direccion); printf ("\nTelfono: %s", personal[i].telefono); if (personal[i].tipo == 'A') { printf ("\nALUMNO"); printf ("\nGrupo: %s", personal[i].ambos.al.grupo); printf ("\nN de Asignaturas: %d", personal[i].ambos.al.asignat); printf ("\nRepite: %d", personal[i].ambos.al.repite); } else { printf ("\nPROFESOR"); printf ("\nN.R.P.: %s", personal[i].ambos.pr.nrp); printf ("\nCargo: %s", personal[i].ambos.pr.cargo); } }

143

Tipos enumerados
Un tipo enumerado es similar a las estructuras. Sus miembros son constantes de tipo int. Es til definir nuevos literales para
Asociar un nombre a un valor numrico Limitar los valores que puede tomar una variable entera Hacer el cdigo ms legible

Definicin: enum nombre {m1, m2, ..., mN}; Ejemplo: enum color {negro, blanco, rojo};
144

Ejemplo
#include <stdio.h> enum semaforo {rojo, amarillo, verde}; main() { enum estado semaforo; for(estado =rojo; estado <=verde; estado ++) switch(estado ) { case rojo: printf(Parar, sino multa\n"); break; case amarillo: printf(Parar si no tienes vehculo encima\n"); break; case verde: printf(Circular\n"); break; } }
145

Definicin de tipos de datos (typedef)


Permite dar nuevo nombre a tipos de datos que ya existen: typedef tipoDato nuevo_tipo; Ejemplos:
typedef char letra; letra c; typedef struct{ int dia; int mes; int anio; } FECHA; FECHA a;

146

Combinacin de typedef y enum


Usando typedef y enum se pueden definir tipos que slo pueden tomar ciertos valores Ej. tipo booleano en C
typedef enum {false, true} boolean; ... boolean f=false; ... if(f) printf("f es verdadero\n"); else printf("f es falso\n"); ... f=45; /* Error, no debera tomar ese valor */

147

Ficheros

148

Ficheros
Objetivos:
Presentar el tipo de dato FILE y los tipos de fichero. Explicar las instrucciones para abrir, cerrar y gestionar ficheros. Capacitar al alumno a trabajar con ficheros de texto y binarios.

Contenidos:
1. Concepto de ficheros y sus tipos 2. Declaracin de una variable tipo fichero 3. Operaciones con ficheros:
o Abrir y cerrar ficheros o Control de errores y fin de fichero o Lectura/escritura de ficheros de texto: caracteres, cadenas de caracteres y con formato o Lectura/escritura de ficheros binarios o Acceso directo a informacin de archivos
149

Canales y ficheros
El sistema de E/S del ANSI C proporciona un intermediario entre el programa y el dispositivo al que se accede (pantalla, cinta, disco,...). Este intermediario se llama canal o flujo (stream) y es un buffer independiente del dispositivo al que se conecte. Existen dos tipos de canales:
Canales de texto: Son secuencias de caracteres. Dependiendo del entorno puede haber conversiones de caracteres (LF CR + LF). Esto hace que el nmero de caracteres escritos/ledos en un canal pueda no coincidir con el nmero de caracteres escritos/ledos en el dispositivo. Canales binarios: Son secuencias de bytes. A diferencia de los canales de texto, en los canales binarios la correspondencia de caracteres en el canal y en el dispositivo es 1 a 1, es decir, no hay conversiones.

150

Canales y ficheros ( y 2)
Hay 3 canales que se abren siempre que comienza un programa C:
stdin stdout stderr (ANSI) Canal estndar de entrada. Por defecto el teclado. (ANSI) Canal estndar de salida. Por defecto la pantalla. (ANSI) Canal estndar de salida de errores. Por defecto la pantalla.

Un canal se asocia a un archivo cuando se abre o se crea ste para lo cual se utilizan funciones de la biblioteca stdio.h. Tambin incluye funciones para realizar las operaciones de lectura/escritura as como para desasociar un canal de un archivo (operacin de cierre).

151

Apertura de un archivo
Para abrir un archivo: desc = fopen(nombre_archivo, modo) donde desc, el descriptor, se declara como: FILE *desc; y modo especifica la forma de apertura del archivo. si fopen devuelve NULL, el fichero no se pudo abrir.
152

Parmetros para abrir un fichero


DESCRIPCIN MODO r w a r+ Abre un fichero slo para lectura. Si el fichero no existe fopen() devuelve un puntero nulo y se genera un error. Crea un nuevo fichero para escritura. Si ya existe un fichero con este nombre, se sobreescribe, perdindose el contenido anterior. Abre o crea un fichero para aadir. Si el fichero existe, se abre apuntando al final del mismo. Si no existe se crea uno nuevo. Abre un fichero para leer y escribir. Si el fichero no existe fopen() devuelve un puntero nulo y se genera un error. Si existe, pueden realizarse sobre l operaciones de lectura y de escritura. Crea un nuevo fichero para leer y escribir. Si ya existe un fichero con este nombre, se sobreescribe, perdindose el contenido anterior. Sobre el archivo pueden realizarse operaciones de lectura y de escritura. Abre o crea un fichero para leer y aadir. Si el fichero ya existe se abre apuntando al final del mismo. Si no existe se crea un fichero nuevo.

w+

a+

Modo TEXTO: aadir letra t. Ej: si modo es rt, se est abriendo el fichero en modo texto slo para lectura Modo BINARIO: aadir letra b. Ej: modo es w+b se abrir o crear un fichero en modo binario para lectura y escritura

153

Cierre de un fichero
Para cerrar un fichero y liberar el canal previamente asociado con fopen(), se debe usar la funcin fclose() int fclose (FILE *canal); Esta funcin devuelve 0 si la operacin de cierre ha tenido xito, y distinto de 0 en caso de error.

154

Ejemplo
#include <stdio.h> main() { FILE *desc; desc = fopen("ejemplo.txt", w"); if (desc == NULL) { printf("Error, no se puede abrir el archivo \n"); } else { /* se procesa el archivo */ /* al final se cierra */ fclose(desc); } exit(0); }

155

Control de errores
Cada vez que se realiza una operacin de lectura o de escritura sobre un fichero debemos comprobar si se ha producido algn error. Para ello disponemos de la funcin ferror() int ferror (FILE *canal); Esta funcin devuelve 0 si la ltima operacin sobre el fichero se ha realizado con xito.

156

Final de fichero
Cada vez que se realiza una operacin de lectura sobre un fichero, el indicador de posicin del fichero se actualiza. Es necesario, pues, controlar la condicin de fin de fichero. Por ello, debemos saber que cuando se intentan realizar lecturas ms all del fin de fichero, el carcter ledo es siempre EOF. Sin embargo en los canales binarios un dato puede tener el valor EOF sin ser la marca de fin de fichero. Es aconsejable, por ello, examinar la condicin de fin de fichero mediante la funcin feof()

int feof (FILE *canal);


Esta funcin devuelve un valor diferente de cero cuando se detecta el fin de fichero.
157

Ficheros de texto
Se trata de archivos cuyo contenidos son caracteres en formato ASCII, por tanto, son legibles y editables por cualquier editor de texto. Usualmente tienen la extensin txt. Para abrir un archivo en modo texto se debe emplear el modificador t en el modo de apertura del archivo. Existen dos formas de tratar ficheros de texto:
Carcter a carcter (fgetc y fputc) Cadenas de caracteres (fgets y fputs) Con formato (fprintf y fscanf)

158

Funciones de manejo carcter a carcter


Lectura: int fgetc(FILE *fich) Lee un carcter del archivo (EOF si estamos al final del mismo) Escritura: int fputc(char c, FILE *fich) Escribe el carcter c en el archivo. Si es correcto devuelve el mismo carcter y si no EOF.
159

Ejemplo
Ejemplo que realiza la lectura de un archivo carcter a carcter empleando un buffer:
char buffer[255], lineas[100][80], c; int n, t; FILE *entrada; entrada = fopen(ejemplo.txt, rt); while (!feof(entrada)) { t = 0; do { c = fgetc(entrada); buffer[t] = c; t++; } while (c!=EOF && c!=\n); //fin de fichero o de lnea strcpy(lineas[n], buffer); n++; } fclose(salida);
160

Funciones de manejo cadenas de caracteres


Lectura: char *fgets(const char *s, int n, FILE *fich) Lee n-1 caracteres o hasta carcter de fin de lnea (que tambin se almacena en s). Si no se produce error, la funcin devuelve un puntero a char; en caso contrario, devuelve un puntero nulo. Escritura: int fputs(char *s, FILE *fich) Escribe la cadena s en el archivo. Si es correcto devuelve un valor no negativo y si no EOF. No copia el carcter nulo ni aade el carcter de fin de lnea.
161

Ejemplo
#include <stdio.h> int main(void) { FILE *fent; FILE *fsal; char car[120]; int res = 0; char * ret; /* Apertura del archivo de entrada */ fent = fopen("./entrada.txt", "r"); if (fent == NULL) { fprintf(stderr, "Error abriendo entrada.txt \n"); return(0); } /* Apertura, con creacin si no existe, del archivo de salida */ fsal = fopen("./salida.txt", "w"); if (fsal == NULL) { fprintf(stderr, "Error creando salida.txt \n"); fclose(fent); return(0); }

162

Ejemplo (y 2)
/* Bucle de lectura y escritura con lneas */ do { /* Lectura de la lnea siguiente */ ret = fgets(car, 110, fent); if ( car == NULL) fprintf(stderr, "Error al leer \n"); else fprintf(stdin, "Longitud linea leida: %d \n", strlen(car)); /* Escritura de la lnea */ if (ret != NULL) { res = fputs(car, fsal); if (res == EOF) fprintf(stderr, "Error al escribir %s \n", car); } } while (ret != NULL); /* Cierre de los streams de entrada y de salida */ fclose(fent); fclose(fsal); return(0); }

163

Funciones de manejo con formato


Lectura: int fscanf(FILE *fich, char *formato, arg1,arg2,argN) Su uso es el mismo que scanf pero con la salvedad de que lee desde un archivo, en vez desde el teclado. Escritura: int fprintf(FILE *fich, char *formato, arg1,arg2,argN) Su uso es igual al de printf pero con la salvedad de que escribe en un archivo en vez de en la pantalla.

164

Ejemplo
Veamos un ejemplo para escribir una cadena de caracteres en un fichero:
char cadena[255]; FILE *salida; salida = fopen(salida.txt, wt); strcpy(cadena, Prueba de escritura); fprintf(salida,%s,cadena); fclose(salida);

165

Ficheros binarios
Son archivos cuyo contenido son caracteres en formato binario, por tanto NO son legibles ni editables. Para asegurarnos que la apertura de un archivo se hace en modo binario se debe emplear el modificador b en el modo de apertura del archivo. Si no ponemos nada se asume el modo binario por defecto. Las funciones bsicas de escritura y lectura asociadas a este modo son: fwrite y fread. Generalmente se utilizan para leer estructuras

166

Escribir a fichero binario


Escritura int fwrite(void *datos, int tam, int ndatos, FILE *fich); Devuelve: Nmero de elementos (no bytes) escritos en el archivo. Parmetros:
*ptr = puntero al origen de los datos. tam = tamao de cada elemento. ndatos = nmero de elementos. *fich = puntero a FILE (archivo donde escribir).
167

Ejemplo
FILE *archivo; int valor; Tficha ficha; int n; archivo=fopen(c:\archivo.dat,w); n = fwrite(&valor, sizeof(int), 1, archivo); if (n!=1) printf(Error: escritura incompleta.); n = fwrite(&ficha, sizeof(TFicha), 1, archivo); if (n!=1) printf(Error: escritura incompleta.);

168

Lectura de fichero binario


Sintaxis: int fread(void *datos, int tam, int ndatos, FILE *fich); Devuelve el nmero de elementos (no bytes) ledos del archivo. Parmetros:
*ptr = puntero al destino de los datos. tam = tamao de cada elemento. ndatos = nmero de elementos. *fich = puntero a FILE (archivo de donde leer).

169

Ejemplo
TFicha fichas[100]; int nfichas; FILE *agenda; nfichas =0; agenda = fopen(agenda.dat, rb); while (!feof(agenda)) { fread(&fichas[nfichas], sizeof(TFicha), 1, agenda); nfichas ++; } fclose(agenda);
170

Ejemplo agenda
El registro de ese archivo constar de los siguientes campos:
Nombre Domicilio Poblacin Provincia Telfono 40 caracteres 40 caracteres 25 caracteres 15 caracteres 10 caracteres

El programa crea el fichero llamado LISTIN.TEL con los datos suministrados por el usuario

171

Ejemplo
#include <stdio.h> typedef struct { char nom[41]; char dom[41]; char pob[26]; char pro[16]; char tel[11]; } REG; void main (void) { FILE *f; REG var; if (!(f = fopen ("LISTIN.TEL", "wb"))) { perror ("LISTIN.TEL"); return; } printf ("Nombre: "); gets (var.nom);

172

Ejemplo (y 2)
while (var.nom[0]) { printf ("\nDomicilio: "); gets (var.dom); printf ("\nPoblacin: "); gets (var.pob); printf ("\nProvincia: "); gets (var.pro); printf ("\nTelfono: "); gets (var.tel); fwrite (&var, sizeof (var), 1, f); if (ferror (f)) { puts ("No se ha almacenado la informacin"); getch (); } printf ("Nombre: "); gets (var.nom); } fclose (f); }
173

Ejemplo: Lectura en bloques


#include <stdio.h> typedef struct { char nom[41]; char dom[41]; char pob[26]; char pro[16]; char tel[11]; } REG; void main (void) { FILE *f; REG var[4]; int i, n; if (!(f = fopen ("LISTIN.TEL", "rb"))) { perror ("LISTIN.TEL"); exit (1); } do { n = fread (var, sizeof (REG), 4, f); for (i = 0; i < n; i++) printf ("\n%-41s %s", var[i].nom, var[i].tel); puts ("\nPulse una tecla ..."); getch (); } while (!feof (f)); fclose (f); }

174

Acceso directo
El acceso directo a un archivo, se realiza con la ayuda de la funcin fseek() que permite situar el indicador de posicin del archivo en cualquier lugar del mismo. int fseek (FILE *canal, long nbytes, int origen); Esta funcin sita el indicador de posicin del fichero nbytes contados a partir de origen. La funcin devuelve 0 cuando ha tenido xito. En caso contrario devuelve un valor diferente de 0. Esta funcin simplemente maneja el indicador de posicin del fichero, pero no realiza ninguna operacin de lectura o escritura. Por ello, despus de usar fseek() debe ejecutarse una funcin de lectura o escritura.
175

Acceso directo (y 2)
int fseek (FILE *canal, long nbytes, int origen);
Los valores posibles del parmetro origen y sus macros asociadas

ORIGEN Principio del fichero Posicin actual Fin del fichero

VALOR 0 1 2

MACRO SEEK_SET SEEK_CUR SEEK_END

176

Ejemplo:
#include <stdio.h> #include <string.h>

Se crea un archivo llamado FRASE.TXT con una cadena de

caracteres. Posteriormente lee un carcter de la cadena cuya posicin se teclea.

void main (void) { FILE *f; int nbyte, st; char frase[80], caracter; if (!(f = fopen ("FRASE.TXT", "w+t"))) { perror ("FRASE.TXT"); return; } printf ("Teclee frase: "); gets (frase); fwrite (frase, strlen (frase) + 1, 1, f); printf ("\nLeer carcter n: "); scanf ("%d", &nbyte); st = fseek (f, nbyte, SEEK_SET); if (st) puts ("Error de posicionamiento"); else { caracter = getc (f); if (caracter != EOF) printf ("\nEl carcter es: %c", caracter); else puts ("Se sobrepas el fin de fichero"); } fclose (f); }

177

Ejemplo:
#include <stdio.h> typedef struct { char nombre[40]; int edad; float altura; } REGISTRO;

programa escribe registros ayudndose de fseek().

void main (void) { FILE *f1; REGISTRO mireg; int num; long int puntero; if (!(f1 = fopen ("REGISTRO.DAT", "r+b"))) { puts ("Error de apertura"); return; } printf ("Escribir registro n: "); scanf ("%d", &num);

178

Ejemplo:

programa escribe registros ayudndose de fseek().

(y2)

while (num > 0) { getchar (); printf ("Nombre: "); gets (mireg.nombre); printf ("Edad: "); scanf ("%d", &mireg.edad); printf ("Altura: "); scanf ("%f", &mireg.altura); puntero = (num - 1) * sizeof (REGISTRO); if (fseek (f1, puntero, SEEK_SET)) puts ("Error de posicionamiento"); else { fwrite (&mireg, sizeof (mireg), 1, f1); if (ferror (f1)) { puts ("ERROR de escritura"); getch (); } } printf ("Escribir registro n: "); scanf ("%d", &num); } fclose (f1); } 179

Programacin modular
Tema 13

180

Tema 13
Objetivos:
Explicar el mbito de las variables del programa. Familiarizar al alumno con la creacin de programas modularizados y la creacin de libreras de funciones propias.

Contenidos:
1. Variables globales y locales 2. Variables estticas 3. El preprocesador C: #include y #define. 4. Programas modulares 5. Bibliotecas de funciones

181

mbito de las variables y tipos de almacenamiento


Existen dos formas de caracterizar una variable:
Por su tipo de dato Por su tipo de almacenamiento

El tipo de dato se refiere al tipo de informacin que representa la variable (int, char, . . . ). El tipo de almacenamiento se refiere a su permanencia y a su mbito. El mbito de una variable es la porcin del programa en la cual se reconoce la variable. Segn el mbito, las variables pueden ser:
Variables locales. Variables globales.

Segn el tipo, las variables pueden ser:


Variables Variables Variables Variables automticas. estticas. externas. de tipo registro.

182

Variables globales
Se declaran fuera de las funciones y antes de su uso. Pueden ser accedidas desde cualquier funcin.
#include <stdio.h> void funcion1(void); int a = 1000; /* variable global */ main() { int b = 2; /* variable local */ funcion1(); printf("a = %d, b = %d \n", a, b); } void funcion1(void) { int c = 4; /* variable local */ printf("a = %d, c = %d \n", a, c); return; }
183

Variables globales (y 2)
Mantienen los valores que se les asignan en las funciones. Es mejor hacer uso de variables locales para evitar efectos secundarios o laterales.
#include <stdio.h> void funcion1(void); int a=10; /* variable global */ main() { printf("Antes a = %d\n", a); funcion1(); printf("Despues a = %d\n", a); } void funcion1(void) { a = 1000; return; }
184

Variables locales
Las variables locales que se definen en las funciones. Su mbito es local. Su vida se restringe al tiempo en el que esta activa la funcin. Los parmetros formales se tratan como variables automticas. Se pueden especificar con la palabra reservada auto aunque no es necesario.
#include <stdio.h> main() { auto int valor; /* equivalente a int valor */ valor = 5; printf("El valor es %d\n", valor); }

185

Variables estticas
Su mbito es local a la funcin. Su vida coincide con la del programa retienen sus valores durante toda la vida del programa. Se especifican con static. #include <stdio.h> void funcion(void); main() { funcion(); funcion(); funcion(); } void funcion(void) { static int veces = 0; veces = veces + 1; printf("Se ha llamado %d veces a funcion\n", veces); }

186

Variables de tipo registro


Informan al compilador que el programador desea que la variable se almacene en un lugar de rpido acceso, generalmente en registros. Si no existen registros disponibles se almacenar en memoria. Se especifican con register
#include <stdio.h> main() { register int j; for (j = 0; j < 10; j++) printf("Contador = %d\n", j); }

187

Variables de tipo externas


Variables globales. Hay que distinguir entre definicin y declaracin de variable externa. La definicin se escribe de la misma forma que las variables normales y reserva espacio para la misma en memoria. Una declaracin no reserva espacio de almacenamiento se especifica con extern. Se emplean cuando un programa consta de varios mdulos. En uno de ellos se define la variable. En los dems se declara (extern)

188

Ejemplo
Modulo principal (main.c) #include <stdio.h> extern int valor; /* se declara */ void funcion(void); main() { funcion(); printf("Valor = %d\n", valor); } Modulo auxiliar (aux.c) int valor; /* se define la variable */ void funcion(void) { valor = 10; }

- Se compila por separado: gcc -c -Wall main.c gcc -c -Wall aux.c - Se obtienen dos mdulos objetos: main.o y aux.o. - El ejecutable (prog) se genera: gcc main.o aux.o -o prog

189

Recomendaciones
Evitar el uso de variables globales. Mantener las variables lo ms locales que se pueda. Cuando se precise hacer accesible el valor de una variable a una funcin, se pasar como argumento.

190

Macros
Una macro es un identificador equivalente a una expresin, sentencia o grupo de sentencias. #include <stdio.h> #define maximo(a,b) ((a > b) ? a : b) main() { int x, y; int max; printf("Introduzca dos numeros: "); scanf("%d %d", &x, &y); max = maximo(x,y); /* uso de la macro */ printf("El maximo es %d\n", max); }
191

Macros (y 2)
No puede haber blancos entre el identificador y el parntesis izquierdo. Una macro no es una llamada a funcin. El preprocesador sustituye todas las referencias a la macro que aparezcan dentro de un programa antes de realizar la compilacin:
No se produce llamada a funcin mayor velocidad. Se repite el cdigo en cada uso de la macro mayor cdigo objeto.

192

Directiva #include
Indica al preprocesador que incluya un archivo fuente nom_fich. El formato es: #include "nom_fich" o bien, #include <nom_fich> El uso de comillas dobles " " o ngulos < > indica dnde debe buscar el preprocesador el fichero nom_fich.
comillas dobles " " : en el directorio de trabajo o en el camino absoluto que se especifique en la sentencia include ngulos < >: en los directorios donde se encuentran las bibliotecas que proporciona el compilador

193

Archivos de cabecera (.h)


Permiten modularizar el cdigo y favorecer la ocultacin de informacin. Puede contener:
Definiciones de macros #define MIL 1000 Declaraciones de variables extern int dia; Declaraciones de funciones extern void f(void); Otras directivas de inclusin #include a.h Comentarios Definiciones de tipos de dato (typedef)

Nunca debe tener:


Definiciones de variables int dia; Definiciones de funciones void f(void);
194

Compilacin prog. varios mdulos


preprocesador leyOhm.h prog_ppal.c leyOhm.h prog_ppal.c prog_ppal.o enlazador
Inclusin del archivo leyOhm.c

leyOhm.c

compilador

leyOhm.o

prog_ppal.exe
195

La biblioteca de funciones
LENGUAJE ARCHIVO DE CABECERA ALLOC.H DESCRIPCIN Define funciones de asignacin dinmica de memoria

ANSI C C++

ASSERT.H BCD.H BIOS.H

Declara la macro de depuracin assert Define la clase bcd Define funciones utilizadas en rutinas de ROM-BIOS

C++ C++ ANSI C

COMPLEX.H CONIO.H CTYPE.H DIR.H

Define las funciones matemticas complejas Define varias funciones utilizadas en las llamadas a rutinas de E/S por consola en DOS Contiene informacin utilizada por las macros de conversin y clasificacin de caracteres Contiene definiciones para trabajar con directorios.

DOS.H

Declara constantes y da las declaraciones necesarias para llamadas especficas del 8086 y del DOS Declara mnemnicos constantes para cdigos de error Declara constantes simblicas utilizadas en conexiones con la biblioteca de rutinas open() Contiene parmetros para rutinas de coma flotante

ANSI C

ERRNO.H FCNTL.H

ANSI.C

FLOAT.H

196

La biblioteca de funciones
LENGUAJE ARCHIVO DE CABECERA FSTREAM.H GENERIC.H GRAPHICS.H IO.H DESCRIPCIN C++ C++ C++ Define los flujos de C++ que soportan E/S de archivos Contiene macros para declaraciones de clase genricas Define prototipos para las funciones grficas Declaraciones de rutinas de E/S tipo UNIX

C++ C++ ANSI C ANSI C ANSI C

IOMANIP.H IOSTREAM.H LIMITS.H LOCALE.H MATH.H MEM.H

Define los gestores de flujos de E/S de C++ y contiene macros para creacin de gestores de parmetros Define rutinas bsicas de flujo de E/S de C++ (v2.0) Parmetros y constantes sobre la capacidad del sistema Define funciones sobre el pas e idioma Define prototipos para las funciones matemticas Define las funciones de gestin de memoria

PROCESS.H

Contiene estructuras y declaraciones para las funciones spawn(), exec()

ANSI C

SETJMP.H SHARE.H

Declaraciones para dar soporte a saltos no locales Parmetros utilizados en funciones que utilizan arhivos-compartidos

ANSI C

SIGNAL.H

Declara constantes y declaraciones para utilizarlos en funciones signal() y raise()

197

La biblioteca de funciones
LENGUAJE ANSI C ANSI C ANSI C C++ ANSI C C++ ANSI C ARCHIVO DE CABECERA STDARG.H STDDEF.H STDIO.H STDIOSTR.H STDLIB.H STREAM.H STRING.H SYS\STAT.H DESCRIPCIN Soporte para aceptar un nmero variable de argumentos Declara varios tipos de datos y macros de uso comn Declara tipos y macros para E/S estndar Declara las clases de flujo para utilizar con estructuras del archivo stdio.h Define algunas de las rutinas comnmente utilizadas Define las clases de flujo de C++ para utilizarlas con arrays de bytes en memoria Define varias rutinas de manipulacin de cadenas y de memoria Declara constantes simblicas utilizadas para abrir y crear archivos

SYS\TIMEB.H

Define la funcin ftime() y la estructura timeb

C++ ANSI C

SYS\TYPES.H TIME.H VALUES.H

Define el tipo time_t Estructuras y prototipos para funciones de tiempo Declara constantes dependientes de la mquina

198

Punteros y arrays
Tema 14

199

Punteros y arrays
Objetivos:
Introducir el concepto de puntero. Introducir el concepto de tipo de dato estructurado. Mostrar la representacin de datos mediante arrays unidimensionales y multidimensionales. Conocer la representacin de cadenas de caracteres y las funciones de manipulacin.

Contenidos:
1. Punteros
o Declaracin o Operadores

2. Arrays
o o o o Declaracin Subndices Almacenamiento en memoria Tamao de los arrays

3. Inicializacin de un array 4. Array de caracteres y cadenas de texto 5. Arrays multidimensionales


200

Punteros
Un puntero es una variable que contiene una direccin de memoria. Por ejemplo, la direccin de otra variable .

201

Punteros (y 2)
Las variables puntero se declaran de la siguiente forma: tipo *nombre; siendo nombre el identificador de la variable puntero, y tipo el tipo de variable a la que apunta. Por ejemplo:
char *m; int *n; float *p;

En estas declaraciones, las variables m, n y p son punteros que apuntan, respectivamente, a datos de tipo char, int y float.

202

Punteros (y 3)
Los operadores de punteros son:
& * direccin de en la direccin de

El operador * slo se puede aplicar a punteros Las operaciones permitidas con punteros son:
Asignacin Incremento / Decremento Suma / Resta Comparacin

203

Asignacin punteros
Dadas las declaraciones
float x; float *p, *q;

la forma de asignar a p y q la direccin de x es:


p = &x; q = &x;

Ahora p y q almacenan la misma direccin de memoria: la de la variable x. El mismo efecto se consigue con la asignacin directa entre punteros: p = &x; q = p; No es correcta una sentencia como p = x;

204

Ejemplo
#include <stdio.h> main() { int x; /* variable entera */ int y; /* variable entera */ int *px; /* variable puntero a entero */ x = 5; px = &x; /* asigna a px la direccion de x */ y = *px; /* asigna a y el contenido de la direccion almacenada en px */ printf("x = %d\n", x); printf("y = %d\n", y); printf("*px = %d\n", *px); }
1

int x; int y; int *px; x=5; (&x) 1000 5 px=&x;

(&x) 1200

y=*px;
2

(&px) 3000

100 0

205

Ejercicio
Dado el siguiente fragmento de cdigo:
float n1; float n2; float *p1; float *p2; n1 = 4.0; p1 = &n1; p2 = p1; n2 = *p2; n1 = *p1 + *p2; Cunto vale n1 y n2?

206

Incremento / Decremento
Los operadores ++ y -- actan de modo diferente segn el tipo apuntado por el puntero. Si p es un puntero a caracteres (char *p) la operacin p++ incrementa el valor de p en 1. Si embargo, si p es un puntero a enteros (int *p), la misma operacin p++ incrementa el valor de p en 2 para que apunte al siguiente elemento, pues el tipo int ocupa dos bytes. Del mismo modo, para el tipo float la operacin p++ incrementa el valor de p en 4. Lo dicho para el operador ++ se cumple exactamente igual, pero decrementando, para el operador --.
207

Suma / Resta
Ocurre exactamente lo mismo que con las operaciones de incremento y decremento. Si p es un puntero, la operacin p = p + 5; hace que p apunte 5 elementos ms all del actual. Si p estaba definido como un puntero a caracteres, se incrementar su valor en 5, pero si estaba definido como un puntero a enteros, se incrementar en 10.

208

Comparacin
Pueden compararse punteros del mismo modo que cualquier otra variable, teniendo siempre presente que se comparan direcciones y NO contenidos. int *p, *q; if (p == q) puts ("p y q apuntan a la misma posicin de memoria");

209

Puntero NULL
Cuando se asigna 0 a un puntero, este no apunta a ningn objeto o funcin. La constante simblica NULL definida en stdio.h tiene el valor 0 y representa el puntero nulo. Es una buena tcnica de programacin asegurarse de que todos los punteros toman el valor NULL cuando no apuntan a ningn objeto o funcin. int *p = NULL; Para ver si un puntero no apunta a ningn objeto o funcin:
if (p == NULL) printf("El puntero es nulo\n"); else printf("El contenido de *p es\n", *p);
210

Arrays
Conjunto de datos del mismo tipo a los que se da un nombre comn y a los que se accede a travs de un ndice tipo_dato variable_array[num_elem]; int numeros[20]; float temperaturas[100]; En un vector de N elementos, el primero se referencia con el ndice 0 y el ltimo con el ndice N-1 Inicializacin
int numeros[2]={0,1} int numeros[]={0,1} el compilador asume array de 2 elementos

El procesamiento se debe hacer elemento a elemento


211

Ejemplo arrays
#include <stdio.h> #define TAM_VECTOR 10 main() { int vector_a[TAM_VECTOR]; int vector_b[TAM_VECTOR]; int j; /* variable utilizada como indice */ /* leer el vector a */ for (j = 0; j < TAM_VECTOR; j++) { printf("Elemento %d: ", j); scanf("%d", &vector_a[j]); } /* copiar el vector */ for (j = 0; j < TAM_VECTOR; j++) vector_b[j] = vector_a[j]; /* escribir el vector b */ for (j = 0; j < TAM_VECTOR; j++) printf("El elemento %d es %d \n", j, vector_b[j]); }

212

Cadenas de caracteres
Un caso particular de vector es la cadena de caracteres. Se declara: char nombre[num_car]; y permite almacenar num_car-1 caracteres y el carcter nulo '\0' de terminacin. char frase[21]; es apta para almacenar 20 caracteres y el nulo. C permite la inicializacin de cadenas de caracteres en la declaracin, mediante sentencias del tipo char cadena[ ] = "Esto es una cadena de caracteres"; en la que no es necesario aadir el nulo final ni indicar el tamao, pues lo hace automticamente el compilador.
213

Cadenas de caracteres

Una forma de asignar un valor a una cadena es la siguiente: char cadena[10]; strcpy(cadena, "Hola");

214

biblioteca estndar string.h


char *strcat (char *cad1, const char *cad2) Concatena cad2 a cad1 devolviendo la direccin de cad1. Elimina el nulo de terminacin de cad1 inicial. char *strcpy (char *cad1, const char *cad2) Copia la cadena cad2 en cad1, sobreescribindola. Devuelve la direccin de cad1. El tamao de cad1 debe ser suficiente para albergar a cad2. int strlen (const char *cad) int isalnum (int ch) int isalpha (int ch) int isdigit (int ch) int islower (int ch) int isupper (int ch) int tolower (int ch) int toupper (int ch) Devuelve el nmero de caracteres que almacena cad (sin contar el nulo final). Devuelve 1 si ch es alfanumrico (letra del alfabeto o dgito) y 0 en caso contrario. Devuelve 1 si ch es una letra del alfabeto y 0 en caso contrario. Devuelve 1 si ch es un dgito del 0 al 9, y 0 en caso contrario. Devuelve 1 si ch es un letra minscula y 0 en caso contrario. Devuelve 1 si ch es una letra mayscula y 0 en caso contrario. Devuelve el carcter ch en minscula. Si ch no es una letra mayscula la funcin devuelve ch sin modificacin. Devuelve el carcter ch en mayscula. Si ch no es una letra minscula la funcin devuelve ch sin modificacin.
215

Lectura y escritura de cadenas de caracteres


#include <stdio.h> #define TAM_CADENA 80 main() { char cadena[TAM_CADENA]; printf("Introduzca una cadena: "); scanf("%s", cadena); printf("La cadena es %s\n", cadena); } scanf deja de buscar cuando encuentra un blanco si se introduce Hola a todos, solo se leer Hola. No es necesario el operador de direccin (&) ya que cadena representa de forma automtica la direccin de comienzo.
216

Lectura y escritura de cadenas de caracteres (y 2)


La funcin gets lee una lnea completa hasta que encuentre el retorno de carro incluyendo los blancos. La funcin puts escribe una cadena de caracteres junto con un salto de lnea.
#include <stdio.h> #define TAM_LINEA 80 main() { char linea[TAM_LINEA]; printf("Introduzca una linea: \n"); gets(linea); puts("La linea es"); puts(linea); } puts("La linea es:"); es equivalente a: printf("La linea es: \n");

217

Ejemplo
El programa siguiente hace uso de alguna de las funciones anteriores para examinar una cadena de caracteres y convertir las minsculas a maysculas y viceversa. Adems cuenta cuntos caracteres son dgitos numricos. #include <stdio.h> #include <conio.h> #include <string.h> #include <ctype.h> void main (void) { char cadena[100]; int contador = 0; register int i; clrscr (); printf ("\nTeclee una cadena de caracteres: "); gets (cadena); for (i = 0; i <= strlen (cadena); i++) { if (isupper (cadena[i])) cadena[i] = tolower (cadena[i]); else if (islower (cadena[i])) cadena[i] = toupper (cadena[i]); else if (isdigit (cadena[i])) contador++; } printf ("\nLa cadena tiene %d dgitos numricos\n", contador); puts (cadena); }

218

La funcin sizeof()
Devuelve el tamao en bytes que ocupa un tipo o variable en memoria.
#include <stdio.h> main() {
char cadena[10]; printf("un int ocupa %d bytes\n", sizeof(int)); printf("un char ocupa %d bytes\n", sizeof(char)); printf("un float ocupa %d bytes\n", sizeof(float)); printf("un double ocupa %d bytes\n", sizeof(double)); printf(" cadena ocupa %d bytes\n", sizeof(cadena));

}
219

Vectores multidimensionales
Un vector multidimensional se declara: tipo_dato vector[exp1] [exp2] ... [expN]; Matrices o vectores de 2 dimensiones: int matriz[20][30]; define una matriz de 20 filas por 30 columnas. El elemento de la fila i columna j es matriz[i][j]

220

Ejemplo
Funcin que calcula el producto de dos matrices cuadradas.
void multiplicar(float a[][DIMENSION], float b[][DIMENSION], float c[][DIMENSION]) { int i, j, k; for(i = 0; i < DIMENSION; i++) for(j = 0; j < DIMENSION; j++) { c[i][j] = 0.0; for(k = 0; k < DIMENSION; k++) c[i][j] += a[i][k] * b[k][j]; } return; }
221

Funciones y argumentos de tipo puntero


Tema 16

222

Tema 16
Objetivos:
Mostrar el paso de estructuras y arrays a funciones, enfatizando la conveniencia de realizarlo por referencia. Indicar cmo se pasan parmetros al programa principal.

Contenidos:
1. Matrices como argumentos de funciones 2. Estructuras como argumentos de funciones 3. Argumentos de la funcin main()

223

Paso de vectores a funciones


Un vector se pasa a una funcin especificando su nombre sin corchetes. El nombre representa la direccin del primer elemento del vector los vectores se pasan por referencia y se pueden modificar en las funciones. El argumento formal correspondiente al vector se escribe con un par de corchetes cuadrados vacos. El tamao no se especifica. Programa que calcula la media de los componentes de un vector. #include <stdio.h> #define MAX_TAM 4 void leer_vector(int vector[]); int media_vector(int vector[]); main() { int v_numeros[MAX_TAM]; int media; leer_vector(v_numeros); media = media_vector(v_numeros); printf("La media es %d\n", media); }
224

Paso de vectores a funciones (y2)


void leer_vector(int vector[]) { int j; for(j=0; j<MAX_TAM; j++) { printf("Elemento %d: ", j); scanf("%d", &vector[j]); } return; } int media_vector(int vector[]) { int j; int media = 0; for(j=0; j<MAX_TAM; j++) media = media + vector[j]; return(media/MAX_TAM); }
225

Punteros y vectores
El nombre del vector representa la direccin del primer elemento del vector
float vector[MAX_TAM]; vector == &vector[0]

El nombre del vector es realmente un puntero al primer elemento del vector


&x[0] &x[1] &x[2] &x[i] x (x+1) (x+2) (x+i)

Es decir, &x[i] y (x+i) representan la direccin del i-esimo elemento del vector x x[i] y *(x+i) representan el contenido del i-esimo elemento del vector x.

226

Punteros y vectores (y 2)
Cuando un vector se define como un puntero no se le pueden asignar valores ya que un puntero no reserva espacio en memoria. float x[10] define un vector compuesto por 10 nmeros reales reserva espacio para los elementos. float *x declara un puntero a float. Si se quiere que float x se comporte como un vector habr que reservar memoria para los 10 elementos: x = (float *) malloc(10 * sizeof(float)); malloc(nb) (stdlib.h) reserva un bloque de memoria de nb bytes. Para liberar la memoria asignada se utiliza free() (stdlib.h) free(x); El uso de punteros permite definir vectores de forma dinmica.

227

Ejemplo.

Programa que calcula la media de un vector de tamao especificado de forma dinmica.


#include <stdio.h> #include <stdlib.h> void leer_vector(int vector[], int dim); int media_vector(int vector[], int dim); main() { int *v_numeros; int dimension; int media; printf("Dimension del vector: "); scanf("%d", &dimension); v_numeros = (int *) malloc(dimension*sizeof(int)); leer_vector(v_numeros, dimension); media = media_vector(v_numeros, dimension); printf("La media es %d\n", media); free(v_numeros); }

228

Ejemplo.

Programa que calcula la media de un vector de tamao especificado de forma dinmica. (y 2)


void leer_vector(int vector[], int dim) { int j; for(j=0; j<dim; j++) { printf("Elemento %d: ", j); scanf("%d", &vector[j]); } return; } int media_vector(int vector[], int dim) { int j; int media = 0; for(j=0; j<dim; j++) media = media + vector[j]; return(media/dim); }

229

Vectores y cadenas de caracteres


Una cadena de caracteres es un vector de caracteres cada elemento del vector almacena un carcter. Ejemplo: Funcin que copia una cadena en otra: void copiar(char *destino, char *fuente) { while (*fuente != '\0') { *destino = *fuente; destino++; fuente++ ; } *destino = '\0'; return;
}
230

Punteros a estructuras
Igual que con el resto de variables. struct punto { float x; float y; }; main() { struct punto punto_1; struct punto *punto_2; punto_1.x = 2.0; punto_1.y = 4.0; punto_2 = &punto_1; printf("x = %f \n", punto_2->x); printf("y = %f \n", punto_2->y); } En una variable de tipo puntero a estructura los miembros se acceden con ->

231

Paso de estructuras a funciones (ej. por valor)


Se pueden pasar miembros individuales y estructuras completas.Por valor o por referencia. Una funcin puede devolver una estructura. Ejemplo: leer y escribir una fecha.
void imprimir_fecha(struct fecha f) { printf("Dia: %d\n", f.dia); printf("Mes: %d\n", f.mes); printf("Anno: %d\n", f.anno); return; }

232

Paso de estructuras a funciones (y 2)


struct fecha leer_fecha(void) { struct fecha f; printf("Dia: "); scanf("%d", &(f.dia)); printf("Mes: "); scanf("%d", &(f.mes)); printf("Anno: "); scanf("%d", &(f.anno)); return(f); } main() { struct fecha fecha_de_hoy; fecha_de_hoy = leer_fecha(); imprimir_fecha(fecha_de_hoy); }
233

Paso de estructuras a funciones (ej. por referencia)


void leer_punto(struct punto *p); void imprimir_punto(struct punto p); main() {
struct punto *p1; p1 = (struct punto *)malloc(sizeof(struct punto)); leer_punto(p1); imprimir_punto(*p1); free(p1);

234

Paso de estructuras a funciones (ej. por referencia) (y 2)


void leer_punto(struct punto *p) {
printf("x = "); scanf("%f", &(p->x)); printf("y = "); scanf("%f", &(p->y));

}
void imprimir_punto(struct punto p) { printf("x = %f\n", p.x); printf("y = %f\n", p.y); }
235

Argumentos de la funcin main()


Ejecutar un programa con parmetros de entrada (en lnea de comandos) main (int argc, char *argv[ ])
argc: Entero que indica el nmero de parmetros tecleados (incluye el nombre del programa). argv[ ]: Matriz de cadenas de caracteres. Cada uno de los elementos argv[i] es una cadena que almacena un argumento.

236

Argumentos de la funcin main()


La variable argc vale 1 como mnimo, puesto que se cuenta el nombre del programa. Los parmetros se identifican mediante argv de la siguiente manera: argv[0] argv[1] argv[2] ... ... argv[argc] cadena que almacena el nombre del programa. cadena que almacena el primer parmetro. cadena que almacena el segundo parmetro.

vale cero (En realidad es un puntero nulo).

Para que los argumentos sean tratados como diferentes tienen que ir separados por uno o varios espacios blancos
237

Ejemplo
Programa que lista los parmetros, si los hay, de la lnea de rdenes. #include <stdio.h> void main (int argc, char *argv[ ]) { register int i; printf ("\nNombre del programa: %s", argv[0]); if (argc == 1) printf ("\nNo se han introducido parmetros"); else { printf ("\nParmetros en la lnea de rdenes: "); for (i = 1; i < argc; i++) printf ("\n%d: %s", i, argv[i]); } }
238

You might also like