Luis Valencia Cabrera lvalencia@us.es (http://www.cs.us.es/~lvalencia) Ciencias de la Computacion e IA (http://www.cs.us.es/) Ejercicios Lenguaje C Relación 3a (2010/2011) Universidad de Sevilla
Tablas (arrays) en C (I) Declaración de tablas: Unidimensional: tipo nombre [dim]; Multidimensional: Tipo nombre [dim1][dim2] [dimn]; Ejemplos: #define TAM 10 #define MAXCAR 80 #define NHORAS 24 #define NFIL 2 #define NCOL 5 int v[tam]={1,2,3,4,5,6,7,8,9,10; char palabra[maxcar]; double temperaturas[nhoras]; int m[nfil][ncol] = {{1,2,3,4,5,{6,7,8,9,10;
Tablas (arrays) en C (II) Definición de tipos tabla: typedef tipo Nombre[dim1][dim2] [dimn]; Ejemplos: typedef int Vector10[TAM]; typedef char Cadena[MAXCAR]; typedef double Tempe[NHORAS]; typedef int Matriz2x5[NFIL][NCOL]; Vector10 v; Cadena palabra; Tempe temperaturas; Matriz2x5 m;
Tablas (arrays) en C (III) Acceso a un elemento de una tabla: variable_tabla[indice]; // indice comienza en 0 Ejemplos: i = v[5]; palabra[0] = A ; m[1][4] = 5; Nota El nombre de una tabla es un «puntero» a la propia tabla, es decir, contiene la dirección de comienzo donde el compilador ubica la tabla (m = m[0] = m[0][0]).
Tablas (arrays) en C (IV) Paso de una tabla como parámetro de entrada: Prototipo: void funcion1 (const Vector10, int); void funcion1 (const int [TAM], int); void funcion1 (const int [], int); Llamada: Vector10 v; int n; funcion1(v,n); Definición: void funcion1 (const Vector10 vector, int num){ int i; for (i=0; i<num; i++) printf("%d\n", vector[i]);
Tablas (arrays) en C (V) Paso de una tabla como parámetro de entrada/salida: Prototipo: void funcion2 (Vector10, int); void funcion2 (int [TAM], int); void funcion2 (int [], int); Llamada: Vector10 v; int n; funcion2(v,n); Definición: void funcion2 (Vector10 vector, int num){ int i; for (i=0; i<num; i++) vector[i]++;
Tablas (arrays) en C (VI) Tabla multidimensional: Prototipo: void funcion3 (const Matriz2x5, int,int); void funcion3 (const int [NFIL][NCOL], int); void funcion3 (const int [][NCOL], int); Llamada: Matriz2x5 m; int n, l; funcion3(m,n,l); Definición: void funcion3 (const Matriz2x5 matriz, int elem_x, int elem_y){ int i, j; for (i=0; i < elem_x; i++) for (j=0; j < elem_y; j++) printf("%d\n", matriz[i][j]);
Ejercicio 4.1: es correcto? #include <stdio.h> #define TAM 10 typedef int Tabla [TAM]; int main (){ Tabla t1, t2; int i; for (i=0; i <= TAM; i++){ t1[i]=2*i; t2[i]=i*i; for (i=0; i <= TAM; i++) printf("\n%d %d\n", t1[i],t2[i]); return 0;
Ejercicio 4.2: se comporta como esperaba? #include <stdio.h> #define TAM 10 typedef int Tabla [TAM]; void muestratabla (const Tabla); int main (){ Tabla tab; int i, n=7; for (i=0; i <n; i++) tab[i]=i; muestratabla(tab); return 0; void muestratabla (const Tabla t){ int i; for (i=0; i < TAM; i++) printf("\nelemento %d: %d", i, t[i]);
Ejercicio 4.3: Traduzca este pseudocódigo a lenguaje C Objetivo: ordenar array de menor a mayor proc ordenacion_intercambio (ent n: entero; entsal v: Tt) var i: entero ordenado: logico Prin ordenado := falso mientras NO ordenado ordenado := cierto desde i:=1 hasta n-1 si v[i]>v[i+1] <v[i], v[i+1]> := <v[i+1],v[i]> ordenado := falso fsi fdesde fmientras fin
Ejercicio 4.4: Lee, almacena, ordena y muestra Escriba un programa que lea una lista de un máximo de 50 números enteros positivos, los almacene en una tabla, los ordene de menor a mayor y los imprima en dicho orden.
Cadenas de Caracteres (I) Como sabemos, C no tiene tipo predefinido para almacenar cadenas de caracteres. Se puede hacer mediante el uso de tablas: char nombre [dimensión]; Ejemplos: #define MAXCAR 256 char palabra[maxcar]; char palabra[maxcar]={ H, o, l, a, \0 ; char palabra[maxcar]=«hola»; char palabra[]=«hola»; /* Dimensión por tamaño del valor inicial. Último carácter \0 */
Cadenas de Caracteres (II) Definición del Tipo Cadena: #define MAXCAR 256 typedef char Cadena[MAXCAR]; Cadena palabra; Acceso a los elementos: palabra[0]= H ; Lectura: scanf(«%s»,palabra); /* Ojo, sin & ya que la propia cadena es una dirección. */ gets(palabra); Escritura: printf(«%s», «Hola»); puts(«hola»);
Cadenas de Caracteres (III) Longitud: strlen(s) Asignación/copia: strcpy(s, ct) /* Copiar ct en s. */ Comparar: strcmp(cs,ct) /* Comparar cs con ct. */ Concatenar: strcat /* Concatenar ct tras cs. */ Todas estas y otras funciones sobre cadenas están definidas en <string.h>
Tablas de cadenas Declaración: Cadena nombre[dim]; Ejemplos: #define NDIAS 7 #define MAXCAR 256 typedef char Cadena[MAXCAR]; Cadena diassemana[ndias]; Cadena diassemana[ndias]={«lunes»,«martes», «miércoles», «jueves», «viernes», «sábado», «domingo»
Cadenas en C y punteros Declaración de variables: Cadena palabra; char palabra[maxcar]; char *palabra; /* No equivalente al anterior. */ Declaración de prototipos: void funcion (Cadena cadena1, Cadena cadena2); void funcion (char cadena1[], char cadena2[]); void funcion (char *cadena1, char *cadena2); /* Válido porque el nombre de una tabla es un Puntero al comienzo de la tabla de memoria. */
Ejercicio 4.5. Qué falta? #include <stdio.h> #define MAXCAR 256 typedef char Cadena [MAXCAR]; void lee_cadena(cadena); int main (){ Cadena cad; lee_cadena(?????); printf("cadena leida: %s", cad); return 0; void lee_cadena(?????){ int i = 0; char c; c = getchar(); while (c!='\n' && i<maxcar-1){ cadena[i] = c; i++; c = getchar(); cadena[i]=????????;
Ejercicio 4.6. Cuenta carac Escriba una función: int cuenta_caracter (const Cadena cad, char c) que cuente el número de apariciones de un carácter c en una cadena cad, devolviéndolo como resultado.
Estructuras (registros) (I) Una estructura es un conjunto de datos (llamados campos) con las siguientes propiedades: Pueden ser de distinto tipo (int, char, float, etc.) Se denominan por identificadores distintos.
Estructuras (registros) (II) Definición de un registro (estructura): typedef struct { T1 c1; T2 c2; Tn cn; Tr; typedef Tr * PTr; Tr r; PTr pr; Tr r = {v1, v2,, vn;
Estructuras (registros) (III) Ejemplos: typedef struct { Cadena nombre, apellido1, apellido2; int edad; long dni; char sexo; Tpersona; /* Tipo de datos. No reserva memoria! */ Tpersona empleado; Tpersona empleado = {«Alicia», «Gómez», «Cruz», 21, 12345678, m ; /* Se puede inicializar en la declaración. */
Estructuras (registros) (IV) Acceso a los campos de una estructura: A través de una variable estructura: Si hemos declarado: Tr r; Accedemos al campo c1 con: r.c1; A través de puntero a estructura: Si hemos declarado: Tr *pr; Accedemos con pr->c1; o (*pr).c1; Ejemplo: Normal: printf(«%d»,empleado.edad); Strcpy(empleado.nombre, «Alicia»); Puntero: p->sexo = m ; o bien (*p).sexo = m ;
Tablas de estructuras Declaración de tipo, y variable del tipo: typedef Tr Ttabla [dim]; Ttabla nombre; Ejemplos: #define N 200 Typedef Tpersona Ttpersona [N]; Ttpersona clase; Clase del elemento i-ésimo de la clase: clase[i-1].nombre
Paso de parámetros Entrada: void escribe_empleado (Tpersona e) { printf(«%s %s %s\n», e.nombre, e.apellido1, e.apellido2); printf(«%d %ld %c», e.edad, e.dni, e.sexo); Salida: Typedef Tpersona * Ptpersona; //En main tendremos empleado, y lo pasamos como &empleado. void lee_empleado (PTpersona e) { gets(e->nombre); gets((*e).apellido1); gets(e->apellido2); scanf(«%d%ld%c»,&e->edad, &e->dni, &(*e).sexo);
Estructuras anidadas #include <stdio.h> #define MAXCAR 256 typedef char Cadena [MAXCAR]; typedef struct { int dia; int mes; int anyo; Fecha; typedef struct { Cadena nombre, apellido1, apellido2; Fecha fechanacimiento; long dni; char sexo; Tpersona; int main (){ Tpersona empleado = {"José", "López", "Pérez", {10,10,1999, 87654321, 'm'; printf("\nnacido el %d...", empleado.fechanacimiento.dia); return 0;
Ejercicio 4.7. Nºs complejos Utilizando la siguiente estructura para representar números complejos: typedef struct { double a, b; // Forma dinámica double r, arg; // Forma polar (r: módulo, arg: alfa). Complejo; escriba una función que, dado un número complejo en forma binómica, calcule las coordenadas en forma polar: void binomica_a_polar (Pcomplejo pc), siendo:
Ficheros de Texto (I) Un fichero o archivo es un conjunto de datos del mismo tipo, almacenados en un soporte externo. En lenguaje C, atendiendo al tipo de datos que almacenan, los ficheros se dividen en: Ficheros de texto. Ficheros binarios. Los ficheros de texto son aquellos en los que la información almacenada son secuencias de caracteres (letras, números, símbolos, etc.) y se utilizan funciones de lectura y escritura que manejan caracteres.
Ficheros de Texto (II) Declaración de ficheros de texto: typedef FILE * Fichero; Fichero variable_fichero; Ejemplos: typedef FILE * Fichero; Fichero fcad, fent; Apertura de ficheros de texto: Variable_fichero = fopen(nombre_fichero, modo), pudiendo tomar modo los valores: «r», «w», «r+», «a».
Ficheros de Texto (III) Ejemplo de apertura de ficheros de texto: typedef FILE * Fichero; Fichero f; f = fopen("datos.txt","r"); f = fopen("datos.txt","w"); f = fopen("datos.txt","r+"); f = fopen("datos.txt","a"); Si la apertura no puede llevarse a cabo devuelve NULL: En modo «r» (leer) si no existe el fichero. En modo «w» (escribir) si disco lleno o protegido contra escritura. En modo «r+» (lectura/escritura) si no existe el fichero. En modo «a» (añadir detrás» si disco lleno o protegido contra escritura. Cierre de fichero: fclose(f);
Ficheros de Texto (IV) Detección de fin de fichero: feof(variable_fichero); Leer elementos del fichero: While (!feof(f)){ //tratar elemento //leer siguiente elemento
Ficheros de Texto (V) Lectura y escritura de ficheros de texto: Caracteres: fgetc, fputc Cadenas: fgets, fputs Con formato: fscanf, fprintf Lectura 1 carácter: c = fgetc(fcar); Lectura cadena: fgets(s, MAXCAR, fcad); Lectura entero: fscanf(fent, «%d», &i); Diferencia entre gets/fgets y puts/fputs: gets lee hasta \n y sustituye por \0 fgets añade \0 detrás del último carácter leído puts imprime \n tras la cadena, y fputs no lo hace
Ficheros de Texto (VI) Algoritmo de recorrido de fichero de texto: #include <stdio.h> typedef FILE * Fichero; int main { T r; Fichero f; f = fopen(nombre_fichero, "r"); if (f == NULL) puts("\nerror al abrir el fichero"); else { //leer r de f while (!feof(f)){ //tratamiento de r //leer f de r fclose(f) return 0;
Ficheros de Texto (VII) #include <stdio.h> typedef FILE * Fichero; int main (){ char c; Fichero f; f = fopen("libro1.txt", "r"); if (f == NULL) puts("\nerror al abrir el fichero"); else { c = fgetc(f); while (!feof(f)){ putchar(c); c = fgetc(f); fclose(f); return 0;
Ficheros Binarios (I) Ficheros Binarios: Son aquellos en los que la información almacenada está organizada en base a registros (estructuras), y se utilizan funciones de lectura y escritura que manejan registros.
Ficheros Binarios (II) Declaración de ficheros binarios: typedef FILE * Fichero; Fichero variable_fichero; Ejemplos: typedef FILE * Fichero; Fichero f; Apertura de ficheros binarios: Variable_fichero = fopen(nombre_fichero, modo), pudiendo tomar modo los valores: «rb», «wb», «r+b», «ab».
Ficheros Binarios (III) Ejemplo de apertura de ficheros de texto: typedef FILE * Fichero; Fichero f; f = fopen("datos.dat","rb"); f = fopen("datos.dat","wb"); f = fopen("datos.dat","r+b"); f = fopen("datos.dat","ab"); Si la apertura no puede llevarse a cabo devuelve NULL: En modo «rb» (leer) si no existe el fichero. En modo «wb» (escribir) si disco lleno o protegido contra escritura. En modo «r+b» (lectura/escritura) si no existe el fichero. En modo «ab» (añadir detrás» si disco lleno o protegido contra escritura. Cierre de fichero: fclose(f);
Ficheros Binarios (IV) Detección de fin de fichero: feof(variable_fichero); Leer elementos del fichero: While (!feof(f)){ //tratar elemento //leer siguiente elemento
Ficheros Binarios (V) Lectura y escritura de ficheros de texto: fread(d, l, n, variable_fichero); fwrite(d, l n, variable_fichero); Donde: d: dirección de la variable donde lee o desde donde se graba l: longitud en bytes de la información que se lee o graba n: número de elementos, de longitud l, que se leen o se graban
Ficheros Binarios (VI) Ejemplos: int i, n; Tpersona empleado; Tpersona tablaemp [N]; Fichero femp; 1 empleado: fread(&empleado,sizeof(tpersona),1,temp); N empleados: Fread(tablaemp,sizeof(Tpersona),n,femp);
Ficheros Binarios (VII) int main (){ Tpersona empleado, empleadoescribir={"jose", "Lopez", "Perez", {10,10,1999, 87654321, 'm'; Fichero f; f = fopen("datos.bin", "wb"); fwrite(&empleadoescribir,sizeof(tpersona),1,f); fclose(f); f = fopen("datos.bin", "rb"); if (f == NULL) puts("\nerror al abrir el fichero"); else { fread(&empleado,sizeof(tpersona),1,f); while (!feof(f)){ escribe_empleado(empleado); fread(&empleado,sizeof(tpersona),1,f); fclose(f); return 0;
Ficheros Binarios (VIII) Acceso directo: fseek(variable_fichero, desp, pos_inicial); Donde: desp: nueva posición en bytes, desde la posición inicial, de desplazamiento del fichero. Ojo: puede ser negativo. pos_inicial: desde qué posición se cuenta el desplazamiento: SEEK_SET: comienzo del fichero SEEK_CUR: posición actual SEEK_END: fin del fichero
Ficheros Binarios (IX) Lectura (fichero abierto modo «rb»): fseek(variable_fichero, (pos-1)*sizeof(tr),seek_set); fread(dir_variable, sizeof(tr), 1, variable_fichero); Escritura (fichero abierto modo «wb»): fseek(variable_fichero, (pos-1)*sizeof(tr),seek_set); Fwrite(dir_variable, sizeof(tr), 1, variable_fichero); Modificación(fichero abierto modo «r+b»): fseek(variable_fichero, (pos-1)*sizeof(tr),seek_set); fread(dir_variable, sizeof(tr), 1, variable_fichero); //modificar el dato en dir_variable para luego escribirlo fflush(variable_fichero); fseek(variable_fichero, (pos-1)*sizeof(tr),seek_set); fwrite(dir_variable, sizeof(tr), 1, variable_fichero);
Ficheros Binarios (X) int pos; Tpersona empleado; Fichero femp; Lectura empleado posición pos (fichero modo «rb»): fseek(femp, (pos-1)*sizeof(tpersona),seek_set); fread(&empleado, sizeof(tpersona), 1, femp); Modificación empleado posición pos (fichero modo «r+b»): fseek(femp, (pos-1)* sizeof(tpersona),seek_set); fread(&empleado, sizeof(tpersona), 1, femp); //modificar el dato en dir_variable para luego escribirlo fflush(femp); fseek(femp, (pos-1)* sizeof(tpersona),seek_set); fwrite(&empleado, sizeof(tpersona), 1, femp);