Lenguaje de Programacion C
Lenguaje de Programacion C
Lenguaje de Programacion C
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
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
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
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
19
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;
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
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
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
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
Expresiones y sentencias
Sentencia: especifica una accin a realizar
Ej. printf()
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;
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.
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
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
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
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
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
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
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
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
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
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
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);
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
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
while
Hay que ponerlo fuera, antes del ciclo Hay que ponerlo fuera, antes del ciclo
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
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); }
90
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
94
Ejemplo
95
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
Izquierda
Centro
Derecha
100
102
Contenidos:
1. Arrays
o o o o Declaracin Subndices Almacenamiento en memoria Tamao de los arrays
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
Listas
cmo se utilizan?
Usar un elemento de la lista variable_lista[posicion]; Pasar a funciones
en la declaracin
Empieza en 0
temperaturas[10];
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 *
Listas de nmeros
cmo se utilizan?
Usar toda la lista. Podemos:
Pasar la lista a una funcin de tamao ajustado
void main() { int vector_a[TAM_VECTOR]; int vector_b[TAM_VECTOR]; leer ( vector_a); copiar (vector_a, vector_b); escribir (vector_b); }
108
109
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
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
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
117
Ej.
#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)
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]);
Ejemplo
#include <stdio.h>
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
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; };
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
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
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
#include <stdio.h> #include <string.h> #define NUMCAJAS 3 typedef struct { char pieza[20]; int cantidad; char existe; } registro_piezas;
Caja 1
*/ */ */
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
138
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
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
146
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
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()
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
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
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
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
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
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
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
VALOR 0 1 2
176
Ejemplo:
#include <stdio.h> #include <string.h>
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;
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:
(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
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.
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
187
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
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++
Declara la macro de depuracin assert Define la clase bcd Define funciones utilizadas en rutinas de ROM-BIOS
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
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
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
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
C++ ANSI C
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
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;
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
(&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
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
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
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
Punteros y vectores
El nombre del vector representa la direccin del primer elemento del vector
float vector[MAX_TAM]; vector == &vector[0]
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.
228
Ejemplo.
229
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
232
234
}
void imprimir_punto(struct punto p) { printf("x = %f\n", p.x); printf("y = %f\n", p.y); }
235
236
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