Introduccin al Lenguaje de Programacin C Primera Edicin Electrnica Rev. 14/ 11/ 2001 Autores: G Margarita Daz Roca G Juan Carlos Rodrguez del Pino G Zenn Hernndez Figueroa Asignaturas G Tecnologa de la Programacin (II). Facultad de Informtica (ULPGC) G Metodologa de la Programacin II (ITIS/ ITIG). Escuela Universitaria de Informtica (ULPGC) Copyright Los autores de "Introduccin al Lenguaje de Programacin C" han elaborado estos documentos para la docencia en las asignaturas que aparecen arriba.. Se permite la reproduccin exclusivamente para uso personal a los alumnos actualmente matriculados en las mismas, siempre que este uso no altere total o parcialmente el contenido y no tenga como finalidad la obtencin de beneficios ajenos a la docencia correspondiente. http://www.gedlc.ulpgc.es/docencia/mp_ii/SoloAlumnos/c.html/Portada.html [14/11/01 18:33:42] Contenido. Introduccin al Lenguaje de Programacin C Contenido 1. Introduccin 1.1 Identificadores y palabras reservadas 2. Tipos bsicos de datos 2.1 Tipos de datos 2.2 Conversin entre tipos 3. Operadores 3.1 Operadores aritmticos 3.2 Operadores relacionales 3.3 Operadores lgicos 3.4 Operadores a nivel de bits 3.5 Operadores de asignacin 3.6 Otros operadores 3.7 Precedencia de operadores 4. Tipos de datos construidos 4.1 Punteros 4.2 Vectores y matrices 4.3 Vectores y punteros 4.4 Ristras de caracteres 4.5 Tipos struct y union 4.6 Tipo enum 4.7 Definicin de tipos 5. Estructuras de control 5.1 Inicializacin de variables 5.2 Bloques 5.3 Sentencia if 5.4 Sentencia while 5.5 Sentencia do-while 5.6 Sentencia for 5.7 Sentencia break http://www.gedlc.ulpgc.es/docencia/mp_ii/SoloAlumnos/c.html/Contenido.html (1 of 2) [14/11/01 18:33:15] Contenido. Introduccin al Lenguaje de Programacin C 5.8 Sentencia continue 5.9 Sentencia switch 6. Funciones 6.1 Definicin de funciones 6.2 Paso de parmetros a una funcin 6.3 Sentencia return 6.4 Prototipado de funciones 6.5 Otros ejemplos 6.6 Operaciones bsicas de entrada y salida 7. Preprocesador de C 7.1 Inclusin de ficheros. 7.2 Definicin y expansin de macros. 7.3 Compilacin condicional. 8. Estructura de un programa 8.1 Introduccin 8.2 Modularidad 8.3 Obtencin del ejecutable de un programa 9. Biblioteca de funciones 9.1 <stdio.h> 9.2 <stdlib> 9.3 <string.h> 9.4 <assert.h> 9.5 <math.h> 10. Operaciones sobre ficheros 10.1 Operaciones generales 10.2 Ficheros de texto 10.3 Ficheros binarios http://www.gedlc.ulpgc.es/docencia/mp_ii/SoloAlumnos/c.html/Contenido.html (2 of 2) [14/11/01 18:33:15] Introduccin. Introduccin al Lenguaje de Programacin C 1. Introduccin C fue desarrollado en los aos setenta por Dennis Ritchie en los laboratorios AT&T Bell, aunque no se dio a conocer hasta 1978 cuando Brian Kernighan y Ritchie (1) publicaron una descripcin del lenguaje. La definicin de Kernighan y Ritchie se conoce comnmente como "K&R C". Despus han aparecido varias actualizaciones al lenguaje de la mano de algunos fabricantes o bien del comit ANSI (2) que se encarg de su definitiva normalizacin el 7 de diciembre de 1989. C es un lenguaje de uso muy extendido, sobre todo en el mundo UNIX y linux Entre las muchas razones de su popularidad estn las siguientes: G Es un lenguaje de programacin estructurado, de alto nivel y flexible. G Tiene caractersticas de bajo nivel de las que slo se dispone normalmente en ensamblador. G Los programas escritos en C generan un cdigo reducido y eficiente. G Existen compiladores para la mayora de los ordenadores actuales. G Est claramente definido y estandarizado lo que permite su transportabilidad entre mquinas. G A los apartados anteriores hay que aadir sobre todo que es uno de los lenguajes ms usados actualmente. Para tomar contacto con el lenguaje comenzaremos comentando un programa sencillo escrito en C: /*Funcin que define tres variables y les asigna valores */ int main() /* esto es un comentario */ { int i, j, k; /* definicin de tres variables enteras */ i = 10; /* asigna 10 (decimal) a i */ j = i + 015; /* asigna i + 015 (octal) a j */ k = j * j + 0xFF; /* asigna j * j + 0xFF (hexadecimal) a k*/ return 0; } Explicacin: G El nombre de la funcin es main y en este caso no tiene parmetros y devuelve un entero; main es una funcin especial que ser la primera en ejecutarse en todo programa en C. G El cuerpo de la funcin est encerrado entre llaves { }Las llaves tambin determinan un bloque de cdigo a ejecutar como una unidad. G Las variables deben declararse antes de ser utilizadas. En cualquier punto donde se abra un bloque ({}) se pueden definir variables locales. G Todas las sentencias deben terminar en punto y coma ";" . G Los comentarios se encierran entre/ * */ y son ignorados, pudiendo aparecer en http://www.gedlc.ulpgc.es/docencia/mp_ii/SoloAlumnos/c.html/Introduccion.html (1 of 2) [14/11/01 18:33:17] Introduccin. Introduccin al Lenguaje de Programacin C cualquier parte del cdigo excepto en medio de un identificador. 1.1Identificadores y palabras reservadas Los identificadores y palabras reservadas en C son sensibles a maysculas y minsculas. Lo que quiere decir que no es lo mismo un carcter en minscula que en mayscula. Ejemplo: la funcin "main" no es la misma que la "Main". Los identificadores son los nombres de los elementos que el programador puede establecer. En C los identificadores se usan para referenciar variables, funciones, nuevos tipos de datos, etc. Las reglas para construir un identificador son las siguientes: se pueden usar los 26 caracteres del alfabeto ingls en maysculas o minsculas, los 10 dgitos y el guin bajo (underscore "_"), con la nica restriccin de que no pueden comenzar con un dgito. No existe lmite en cuanto a la longitud de los identificadores, aunque el estndar establece que para diferenciar dos identificadores slo es necesario comparar los primeros 31 caracteres. La lista de palabras reservadas por el lenguaje y que no se pueden usar como identificadores es la siguiente: auto break case char const continue default do double else enum extern float for goto if int long register return short signed sizeof static struct switch typedef union unsigned void volatile while 1 Brian W. Kernighan y Dennis M. Ritchie, The C Programming Lenguage, Prentice-Hall 1978 2 American Nacional Standards Institute, comit X3J11 Dennis Ritchie Brian Kernighan D http://www.gedlc.ulpgc.es/docencia/mp_ii/SoloAlumnos/c.html/Introduccion.html (2 of 2) [14/11/01 18:33:17] Tipos Bsicos. Introduccin al Lenguaje de Proramacin C 2. Tipos bsicos de datos 2.1Tipos de datos El lenguaje C posee gran variedad de tipos bsicos de datos. En el siguiente cuadro se muestran los distintos tipos bsicos y sus modificadores. Tipo Descripcin Rango (3) Modificadores char Carcter o nmeros pequeos -128 a 127 (8 bits) unsigned el mismo tipo pero sin signo int Entero -32768 a 32767 (16 bits) short entero corto (16 bits) unsigned long entero largo (32 bits) float Real 3.4x10e-38 a 3.4x10e38 (32 bits) double Real con mayor o igual precisin que el float 1.7x10e-308 a 1.7x10e308 (64 bits) long real muy grande (80 bits) void dato descartado, tipo comodn dato descartado, tipo comodn Los modificadores se usan precediendo el tipo original. El tipo por defecto es int, por ejemplo: long es equivalente a long int. El tipo void se emplea principalmente para definir procedimientos. Ejemplos: int i ; /* entero */ short int s1, s2; /* enteros pequeo */ char c; /* carcter */ unsigned short int us; /* entero pequeo sin signo*/ long y; /* puede omitirse el int */ double x; /* variable real de doble precisin*/ 2.2 Literales C dispone de formatos para constantes literales del tipo entero, real, carcter, ristra y enumerados. Estos dos ltimos tipos los describiremos en su momento. Los enteros se pueden representar en tres sistemas numricos distintos: decimal, octal y hexadecimal. Un nmero esta escrito en hexadecimal si comienza por "0x" o "0X". Los caracteres que representan el 10, 11, 12, 13, 14 y 15 son a, b, c, d, e y f, en minscula o mayscula. Los nmeros en octal son los que comienzan por 0. Los nmeros en decimal son el http://www.gedlc.ulpgc.es/docencia/mp_ii/SoloAlumnos/c.html/TiposBasicos.html (1 of 3) [14/11/01 18:33:19] Tipos Bsicos. Introduccin al Lenguaje de Proramacin C resto. Ejemplos: literal Descripcin 0x10 16 en hexadecimal 0XAA 170 en hexadecimal 010 8 en octal 025 21 en octal 0x11r Error, "r" no es un dgito vlido 019 Error, 9 no es un dgito vlido. Los nmeros en coma flotante se escriben en base 10 y contienen un punto decimal o un exponente o ambos. El formato sera un nmero decimal con o sin signo que represente la parte entera opcionalmente un punto y la parte decimal, opcionalmente se puede establecer un exponente aadiendo la letra e, minscula o mayscula, y un entero que represente el exponente en base diez. Ejemplos: literal Descripcin 10.1 5e10 50000000000 1.1e-20 0.000000000000000000011 Los caracteres se escriben entre comillas simples. Los datos de tipo carcter son a todos los efectos enteros muy cortos y representan el valor del cdigo ASCII del carcter. Es lo mismo asignar a un carcter el valor 'A' que su cdigo ASCII 65. Para representar caracteres no imprimibles se usa una secuencia de escape que comienza por "\ " seguido de uno o varios caracteres. Por ejemplo para representar el salto del lnea (LF) se puede representar por '\ n'. Ejemplos: literal Descripcin 'a'..'z', '$', '<',... Caracteres imprimibles. '\ '' Representa una comilla simple '\ \ ' Representa una "\ " '\ r' Carcter de retorno de carro '\ 0' Carcter nulo 2.3 Conversin entre tipos C permite convertir valores de distinto tipo de forma automtica, pudindose asignar casi cualquier variable a cualquier otra. Las conversiones automticas funcionan correctamente si se realizan desde un tipo con un rango de valores que se encuentre dentro del rango del receptor; el problema aparece cuando esto no es as, el lenguaje garantiza un correcto funcionamiento si el http://www.gedlc.ulpgc.es/docencia/mp_ii/SoloAlumnos/c.html/TiposBasicos.html (2 of 3) [14/11/01 18:33:19] Tipos Bsicos. Introduccin al Lenguaje de Proramacin C valor actual se encuentra dentro del rango del tipo receptor, pero no se garantiza el resultado en los dems casos. Si se producen problemas en la conversin no se generarn errores en tiempo de ejecucin, siendo el programador el responsable de que la ejecucin de la conversin sea la correcta. Ejemplo: y = i; /* Conversin de valor int a long int nunca existe problema*/ c = i; /* Conversin de valor int a char puede haber problemas */ i = x; /* Conversin de valor double a int puede haber problemas*/ Siempre que un operador se aplique sobre operandos de distinto tipo se realizar una conversin desde el de menor rango al de mayor. Puede que nos interese controlar la conversin de forma manual; para ello se emplea el operador de conversin, en ingls "cast", molde, tomando la forma: (tipo) expresin_a_convertir . Un uso frecuente es cuando al realizar una divisin entre enteros deseamos obtener un resultado real. La forma de realizar esto es convertir uno de los operadores en real para que la divisin cambie a una operacin entre reales. Ejemplo: x = ((double) i) / s1 3 Este rango esta tomado de las especificaciones del compilador Borland C++ 3.1 para PC. Estos valores puede que no coincidan con los de otros compiladores o equipos. D http://www.gedlc.ulpgc.es/docencia/mp_ii/SoloAlumnos/c.html/TiposBasicos.html (3 of 3) [14/11/01 18:33:19] Operadores. Introduccin al Lenguaje de Programacin C 3. Operadores Uno de los puntos fuertes de C es su gran variedad de operadores y la flexibilidad de estos. Esta caracterstica de C nos permite la construccin de expresiones muy complejas de forma sencilla. Existen cinco grandes grupos de operadores: aritmticos, relacionales, lgicos, operaciones a nivel de bits, y asignaciones. 3.1Operadores aritmticos C suministra las operaciones bsicas adems del operador restoque devuelve el resto de la divisin entera. Al operador restotambin se le denomina mdulo. Se carece de operadores ms complejos, como la exponenciacin, aunque si se desean se pueden tomar funciones de la biblioteca que realicen estas tareas. Operadores Aritmticos Operador Descripcin Ejemplo a=3, b=2 Resultado + suma a+b 5 - resta y valor negativo (unario) a-b -b 1 -2 * multiplicacin a*b 6 / divisin a/ b 1 % resto a%b 1 Los operadores anteriores se pueden usar en todos los tipos numricos, con la excepcin del mdulo que slo se puede emplear en enteros y caracteres. Operador de Incremento (++), decremento (--). Estos operadores son unarios y realizan el incremento o decremento respectivamente de la variable a la que se le aplica. Adems de la accin de modificar la variable devuelven el valor de la variable. El operador de incremento o decremento puede ir delante o detrs de la variable, teniendo diferente significado. Si el operador "++" se sita despus de la variable se denomina "postincremento", haciendo que primero se tome el valor y despus se incrementa la variable. Ejemplo: n = k++; /*El valor original de k se asigna a n y luego se incrementa k.*/ Si el operador "++" se sita antes de la variable se denomina "preincremento" y hace que primero se incrementa la variable y despus se tome el valor. Ejemplo: n = ++k; /*Primero se incrementa k y luego se asigna a n */ http://www.gedlc.ulpgc.es/docencia/mp_ii/SoloAlumnos/c.html/Operadores.html (1 of 4) [14/11/01 18:33:22] Operadores. Introduccin al Lenguaje de Programacin C El operador de decremento acta de forma anloga al de incremento. 3.2 Operadores relacionales Se emplean tpicamente en las expresiones condicionales. La principal diferencia con respecto a otros lenguajes son los smbolos empleados en los operadores de igualdad y distinto. El de igualdad por su similitud con la asignacin lleva muchas veces a provocar errores tipogrficos involuntarios. En C no existe el tipo de dato lgico o booleano, los enteros hacen este trabajo interpretandose un cero como falso y un valor distinto de cero como verdadero. Los operadores relacionales devuelven cero si la comparacin es falsa, y un uno en caso contrario. Las condiciones en C son expresiones enteras que si tienen un valor distinto de cero son verdaderos y si no, son falsas. Operadores Relacionales Operador Descripcin Ejemplo Resultado > mayor que 2 > 3 0 < menor que 2 < 3 1 >= mayor o igual que 2 >= 3 0 <= menor o igual que 2 <= 3 1 == igual 2 == 3 0 != distinto 2 != 3 1 3.3 Operadores lgicos Los operadores lgicos estn relacionados con los relacionales ya que normalmente los operandos que usan son resultado de expresiones relacionales. De nuevo, los valores resultantes son cero y uno para falso y verdadero respectivamente. Operadores Lgicos Operador Descripcin Ejemplo A=1, B=2, C=3 Resultado && y (and) (a > b) && c 0 | | o (or) (c > a) | | c 1 ! no (not) !(a >c) 0 3.4 Operadores a nivel de bits Uno de los objetivos del lenguaje es no alejarse de la mquina y usar sus operaciones primitivas. Por ello, no podan faltar operadores que pudiesen ejecutar instrucciones a nivel de bits, comunes en el lenguaje mquina. Operadores a nivel de bits http://www.gedlc.ulpgc.es/docencia/mp_ii/SoloAlumnos/c.html/Operadores.html (2 of 4) [14/11/01 18:33:22] Operadores. Introduccin al Lenguaje de Programacin C Operador Descripcin Ejemplo a=1, b=2, c=3 Resultado & y (and) bit a bit. a & b a & c 0 1 | o (or) bit a bit a | b 3 ^ o (or) exclusivo bit a bit a ^c 2 ~ (ALT-126) complemento a uno de bits. Invierte todos y cada uno de los bits del operando. Formato: ~operando ~a depende del tipo y rango de a << desplazamiento a la izquierda del primer operando tantas veces como indique el segundo a << b c << b 4 12 >> desplazamiento a la derecha del primer operando tantas veces como indique el segundo c >> a 15 >> 2 1 3 Estos operadores actan sobre tipos de datos integrales: "char" e "int" con modificadores. 3.5 Operadores de asignacin Una asignacin tambin es un operador que devuelve la variable modificada. C tiene la capacidad de descartar los resultados devueltos y no usados. Los otros operadores de asignacin no son sino abreviaciones que pueden hacer ms cmodas y simples las expresiones, aunque a veces sean ms ilegibles. Operadores de Asignacin Operador Ejemplo Equivalencia = a=b=c a=c; b=c; += a+=3 a=a+3 -= a-=3*b a=a-(3*b) *= a*=2 a=a*2 / = a/ =35+b a=a/ (35+b) %= a%=8 a=a%8 >>= a>>=1 a=a>>1 <<= a<<=b a=a<<b &= a &=(c+=3) c=c+3; a=a&c ^= a ^= 2 a = a^2 | = a | = c a = a | c http://www.gedlc.ulpgc.es/docencia/mp_ii/SoloAlumnos/c.html/Operadores.html (3 of 4) [14/11/01 18:33:22] Operadores. Introduccin al Lenguaje de Programacin C 3.6 Otros operadores Operador de seleccin. Es un operador triario que requiere una condicin y dos expresiones. Se utiliza para ejecutar una expresin u otra dependiendo de la condicin. formato: Condicin ? Exp1 : Exp2. si se cumple la condicin se evala y devuelve la expresin Exp1 si no la Exp2. Ejemplo: i = ( x < y ? 6 : k+1); Si x es menor que y, i toma el valor seis, en otro caso i toma el valor k + 1. Operador "," El operador "," evala varias expresiones donde la sintaxis permite solamente una, siendo el valor resultante la ltima expresin calculada. Ejemplo: i = (j=5, k*=8, l=4/2); Al terminar la ejecucin i valdr 2. 3.7 Precedencia de operadores Normalmente las expresiones en C se evalan de izquierda a derecha, aunque hay algunas excepciones que es necesario tener en cuenta. No se evalan de izquierda a derecha los operadores de asignacin y el operador de seleccin. Cuando una expresin tiene diversas posibilidades de evaluacin se aplica el orden de precedencia para establecer el clculo a realizar. Ejemplo: a+b*c+d podra calcularse como (a+b)*(c+d) a+(b*c)+d siendo la segunda expresin la correcta. En C existen diversos niveles de precedencia su aprendizaje puede ser laborioso y su utilidad muy concreta, por lo que se recomienda emplear parntesis en las expresiones en las que haya duda en el orden de evaluacin. D http://www.gedlc.ulpgc.es/docencia/mp_ii/SoloAlumnos/c.html/Operadores.html (4 of 4) [14/11/01 18:33:22] Tipos de datos construidos. Introduccin al Lenguaje de Programacin C 4. Tipos de datos construidos 4.1Punteros Se utilizan para contener direcciones de memoria en C. Se definen con un "*" antes del nombre de la variable puntero. Para acceder al contenido de la direccin a la que apunta se usa de nuevo el "* " precediendo la variable puntero Ejemplos: int i, j, *pi, **ppi; define: un entero i. un puntero pi a un entero. un puntero ppi a un puntero, a un entero. Operador & El operador & es un operador unitario que devuelve la direccin de lo que sigue a continuacin. El uso de este operador permite asignar la direccin de cualquier variable a un puntero. Atravs del puntero podemos acceder a la variable. Operador * El operador "*" al ser aplicado a un puntero nos permite acceder a la variable a la que apunta pudiendo tomar su valor o modificarlo. El formato es *expresin, donde la expresin nos debe devolver un puntero. Ejemplo: pi = &i; /* ahora pi seala a la variable i */ *pi = 3; /* le asignamos un 3 a i */ ppi = π /* ppi apunta a pi */ j = **ppi; /* ahora j vale 3 */ Operador sizeof. Este operador nos devuelve el tamao del tipo del operando en bytes ya sea un tipo, el nombre de una variable o expresin. El clculo se produce en tiempo de compilacin por lo que devuelve una constante. 4.2 Vectores y matrices Un vector es una coleccin de elementos del mismo tipo. En C pueden construirse matrices de cualquier dimensin. Es necesario destacar dos propiedades de los vectores en lenguaje C: 1. El subndice del primer elemento de cada dimensin es cero. 2. El nombre de un vector es un puntero constante a la direccin del primer elemento. Como consecuencia de la segunda propiedad no es posible asignar directamente un vector a otro. El formato de definicin de vectores es: TipoDeDato NombreVector[TamaoDimension1][TamaoDimension2] ...; http://www.gedlc.ulpgc.es/docencia/mp_ii/SoloAlumnos/c.html/TiposConstruidos.html (1 of 6) [14/11/01 18:33:24] Tipos de datos construidos. Introduccin al Lenguaje de Programacin C Lo que se establece al definir una matriz es "el tamao" de cada dimensin y no "el lmite". Un error muy comn es pensar que los ndices aceptables van desde 1 hasta el tamao de la dimensin. El rango de ndices aceptables va desde 0 hasta el tamao de la dimensin menos 1. Ejemplos: int a[10]; /*define un vector de 10 enteros, referenciados desde a[0] a a[9] */ float c[5][7][30]; /*define una matriz que va de c[0][0][0] a c[4][6][29] */ Para acceder a una posicin en el vector o matriz se escribe el nombre y a continuacin el ndice entre corchetes para cada dimensin. Ejemplo: c[0][6][15]=0.0; 4.3 Vectores y punteros Los vectores y punteros en C tienen una relacin muy estrecha. A todos los efectos, la nica diferencia importante en el uso de un puntero y un vector est en que el vector (su nombre sin ndice) es constante y el puntero es variable. Los punteros ademas de las operaciones vistas anteriormente soportan otras que podemos utilizar en conjuncin con vectores: G Suma y resta con enteros, dando lugar a otra direccin. Esta direccin resulta de sumar o restar a la original el valor que se obtiene al multiplicar el entero por el tamao del tipo de elemento al que apunta el puntero. G Incrementar y decrementar, equivalente a sumar o restar 1. G Comparacin de punteros (==, !=, <, >, <=, >=) G Diferencia de punteros que da como resultado un entero que indica el nmero de elementos que los separa. Partiendo de la siguiente definiciones e inicializacin int a[10], *v; v=a; se tiene el siguiente conjunto de expresiones equivalentes *a <=> *v <=> a[0] <=> v[0] <=> *(a+0) <=> *(v+0) a[3] <=> v[3] <=> *(a+3) <=> *(v+3) Existe un valor de punteros especial denominado "NULL". Esta direccin nos sirve para dar un valor conocido a los punteros cuando no apuntan a un elemento vlido. Es importante destacar que el hecho de definir un puntero no implica que tenga un valor vlido para su uso inmediato. Para usar el operador * con un puntero es necesario que tenga asignada la direccin de un elemento vlido y existente. Existen tres formas tpicas de asignar un valor correcto a un puntero: 1. Asignndole la direccin de un vector int a[10],*v; v=a; *v=0; /* v[0] toma el valor 0 */ ... v[3]=v[1]+v[2]; http://www.gedlc.ulpgc.es/docencia/mp_ii/SoloAlumnos/c.html/TiposConstruidos.html (2 of 6) [14/11/01 18:33:24] Tipos de datos construidos. Introduccin al Lenguaje de Programacin C 2. Asignarle la direccin de una variable utilizando el operador &. Ejemplo: v = &a[3]; *v= 5; /*a[3] toma el valor 5 */ v++; Inicialmente v apunta a a[3], v++ significa incrementar v en el nmero de bytes que ocupa el tipo de datos al que apunta. Despus de ejecutar v++, v apuntar a a[4]. Si a continuacin se ejecutase v--, v volvera a apuntar a a[3]. 3. Asignndole una direccin de memoria dinmica. Para ello se utiliza la funcin malloc que asigna un bloque contiguo de almacenamiento del tamao que indica el parmetro y devuelve un puntero al comienzo del bloque. Si ocurre un error devuelve NULL. El argumento pasado a malloc es un entero sin signo que representa el nmero de bytes requeridos. Si el almacenamiento est disponible malloc devuelve un puntero de tipo void que se puede transformar mediante un cast al tipo deseado. Ejemplo: #include <stdlib.h> ... float *pf; int nf=20; ... pf=(float *) malloc(nf*sizeof(float)); /*sizeof devuelve el tamao en bytes del elemento al que se aplica*/ pf[0]=0; ... pf[nf-1]=pf[0]*3; ... free(pf); /* libera la memoria previamente asignada */ 4.4 Ristras de caracteres En el lenguaje C no existe un tipo de dato especifico para cadenas de caracteres. Las cadenas de caracteres se representan como vectores de caracteres. Cada elemento del vector es un carcter de la ristra. Tras el ltimo carcter de la ristra debe haber un carcter especial que marca el final de sta, este carcter es el nulo, ASCII 0, tambin representado en C como '\ 0'. Los literales de ristras se escriben como una secuencia de caracteres encerrados entre comillas dobles ("). Estos literales cuando estn fuera de las inicializaciones representan direcciones del tipo "char *" a una zona de memoria donde el compilador almacena el literal en cuestin. El programador no debe modificar dicha ristra. Ejemplo: char *s; /* Se define un puntero a caracteres */ s="Ristra literal"; /* Ahora s apunta a una zona de memoria donde se almacena la ristra*/ Por desgracia el lenguaje no suministra un conjunto de operaciones sobre ristras. Para realizar operaciones elaboradas sobre ristras como calcular su longitud, concatenar dos ristras, etc. es necesario emplear funciones de la biblioteca de funciones. 4.5 Tipos struct y union Las estructuras en C son una coleccin de variables que forman una unidad. Cada una de las variables, denominadas campos, contenidas en la estructura pueden ser de distinto tipo y debe tener un identificador distinto. Formato: struct [Nombre_estructura] { ... /* Campos. Definidos de la misma forma que variables */ http://www.gedlc.ulpgc.es/docencia/mp_ii/SoloAlumnos/c.html/TiposConstruidos.html (3 of 6) [14/11/01 18:33:24] Tipos de datos construidos. Introduccin al Lenguaje de Programacin C } [Definicin_de_variables]; El nombre del tipo de estructura y la definicin de variables son opcionales, pero al menos debe existir una de ellas ya que si no la definicin no tendra efecto. El nombre de la estructura sirve para usarlo en posteriores declaraciones o definiciones de variables de este tipo. La parte de "definicin de variables" del formato nos permite definir variables de este tipo de forma inmediata e incluso sin necesidad de que la estructura tenga un nombre concreto. Ejemplo: Definicin de un vector Z, de estructuras, cada una de las cuales tiene dos campos: un entero largo, DNI, y una ristra Nombre de hasta 29 caracteres. struct InfoPersonal{ long DNI; char Nombre[30]; } Z[20],dato; /* vector de 20 estructuras ms una*/ El nombre InfoPersonal es el tipo de la estructura, permitiendo que se pueda utilizar en definiciones posteriores de variables de este tipo. Ejemplo: struct InfoPersonal *p; define un puntero p a una variable de tipoInfoPersonal. Operador ".". La forma de acceder a los campos de una variable de tipo struct o union es empleando el operador ".", Variable.campo. Ejemplo: dato.DNI=42999999; dato.Nombre[0]='A'; Operador "->" Cuando se emplea un puntero a una estructura para acceder a los campos de sta se pueden usar los operadores punto y asterisco como (*Puntero).Campo o bien emplear el operador ->. El operador -> tiene un formato ms simple y compacto para acceder a los campos, Puntero->Campo. Ejemplo de uso del operador "->". Para copiar en la variable n el valor del campo DNI de la estructura sealada por p se puede escribir de las dos formas siguientes: n = (*p).DNI n = p -> DNI Si utilizamos Z, la sentencia sera: n = Z[4].DNI La union tiene exactamente el mismo formato y funcionalidad que struct con la nica diferencia de que todos los campos comparten el mismo espacio de memoria. En un determinado momento slo se selecciona uno. Ejemplo: http://www.gedlc.ulpgc.es/docencia/mp_ii/SoloAlumnos/c.html/TiposConstruidos.html (4 of 6) [14/11/01 18:33:24] Tipos de datos construidos. Introduccin al Lenguaje de Programacin C union {int i; char c;} m; Significa que m puede contener el entero i o el carcter c. El uso es igual que el de un struct.. Ejemplo de unin y punteros: int main () { union { char mensaje [10]; short int cifrado [5]; } oculto, *p; p = &oculto; p -> cifrado [0] = 0x4C55; p -> cifrado [1] = 0x4750; p -> cifrado [2] = 0x2043; p -> cifrado [3] = 0x4944; p -> cifrado [4] = 0x53; printf("%s\n", p -> mensaje); return 0; } 4.6 Tipo enum Una enumeracin con formato similar a la estructura o a la unin. Sus miembros son constantes que estn escritas como identificadores, pero que toman valores enteros con signo. Estas constantes representan valores que pueden ser asignados a variables enumeradas. Formato: enum [NombreEnumeracin] {Elemento1, Elemento2, ...} [Variable1, Variable2, ...]; El nombre de la enumeracin y las variables son opcionales. Los nombres de los elementos deben ser todos distintos. Ejemplo: enum DiaSemana {lunes, martes miercoles, jueves, viernes, sabado , domingo}; int FinDeSemana; ... enum DiaSemana Hoy, Manana; FinDeSemana = (Hoy == sabado || Hoy == domingo); Manana = (Hoy == domingo)? lunes: Hoy+1; 4.7 Definicin de tipos En C es posible definir nuevos tipos de variables a partir de construcciones con los tipos ya definidos. Esto se hace igual que si fuese la definicin de una variable pero la precedemos de la palabra reservada typedef . El nombre que hayamos dado ser el del nuevo tipo y lo podremos utilizar a partir de este punto para definir nuevas variables. Ejemplos: typedef unsigned short int unshort define unshort como un unsigned short int y puede utilizarse posteriormente como tipo. Ejemplo: unshort n1, *n2, n3[5]; Define: n1 un entero corto sin signo, n2 un puntero a entero corto sin signo, n3 un vector de enteros cortos sin signo. http://www.gedlc.ulpgc.es/docencia/mp_ii/SoloAlumnos/c.html/TiposConstruidos.html (5 of 6) [14/11/01 18:33:24] Tipos de datos construidos. Introduccin al Lenguaje de Programacin C Ejemplos de typedef con registros: typedef struct { float real,imaginario; } complejo; complejo a,b; typedef struct Tnodoarbol { int info; struct Tnodoarbol *izq, *der; } TNodoArbol; TNodoArbol *raiz; D http://www.gedlc.ulpgc.es/docencia/mp_ii/SoloAlumnos/c.html/TiposConstruidos.html (6 of 6) [14/11/01 18:33:24] Estructuras de Control. Introduccin al Lenguaje de Programacin C 5. Estructuras de control C posee las sentencias de control tpicas de los lenguajes de alto nivel. Como caracterstica a destacar se encuentra la sintaxis de la instruccin "for", muy distinta a la de otros lenguajes. 5.1Inicializacin de variables Las variables, vectores y estructuras pueden inicializarse a la vez que se definen. La inicializacin se produce una nica vez, cuando la variable comienza su existencia. { int size = i/10; /* se calcula e inicializa cada vez que se entra en el bloque */ char c[]={'a',' ','d','z'}; /* implcitamente c toma el tamao 4 */ char *Lista[3]={"Uno","Dos","Tres"}; /* Se toman las direcciones de los literales */ chardiasemana1[6]={'l','u','n','e','s','\0'}; char diasemana2[7]="martes"; /* Se copian los caracteres del literal */ int M[2][2]={{1,2},{3,4}}; struct InfoPersonal ip={42000000,"Don nadie"}; 5.2 Bloques Las instrucciones en C pueden ser simples (expresiones o sentencias de control de flujo) o compuestas. Las instrucciones compuestas estn formadas por una secuencia de instrucciones terminadas en ";" y encerradas entre llaves. A esta forma de agrupar instrucciones se le denomina bloque. Los bloques, adems de formar una entidad de ejecucin, aaden la posibilidad de tener variables locales propias. En C, siempre que se abren llaves, es posible, en ese punto, definir variables locales que existirn mientras no se abandone el bloque en que se crearon. Ejemplo: { int i,j,k; ... { float c=3.5,i=0; /* i entera es ocultada por i real */ ... { char i='A'; /* i real es ocultada temporalmente por una nueva i */ ... /* i es un carcter */ } /* reaparece i real sin ninguna modificacin */ c=i; /* i real se asigna a c real */ ... } /* reaparece i entera sin ninguna modificacin */ j=i /* i entera se asigna a j */ } http://www.gedlc.ulpgc.es/docencia/mp_ii/SoloAlumnos/c.html/EstructurasControl.html (1 of 6) [14/11/01 18:33:27] Estructuras de Control. Introduccin al Lenguaje de Programacin C Como se muestra en el ejemplo anterior, en C, es posible definir variables que oculten a otras definidas en un mbito externo a estas. 5.3 Sentencia if La sentencia if tiene la forma: if( Condicin ) Instruccin1; [else Instruccin2;] Los parntesis asociados que delimitan la condicin no son opcionales. En caso de que la condicin sea verdadera se ejecuta la instruccin1; en caso contrario se ejecuta, si existe, la instruccin2. Ejemplo: if (j % 2 == 0) cambio = 0; /* una sentencia if simple */ if (v[j] > v[j+1]) /* sentencia if con un conjunto de instrucciones */ { maximo=v[j]; cambio=1; } else maximo=v[j+1]; 5.4 Sentencia while La sentencia while tiene la forma: while (Condicin) Instruccin; Los parntesis no son opcionales. Si se cumple la condicin se ejecuta la instruccin y se repite el proceso. Ejemplo: { int i, maximo, a[10]; ... i=1; maximo=a[0]; while(i<10) { if(maximo < a[i]) maximo=a[i]; i++; } http://www.gedlc.ulpgc.es/docencia/mp_ii/SoloAlumnos/c.html/EstructurasControl.html (2 of 6) [14/11/01 18:33:27] Estructuras de Control. Introduccin al Lenguaje de Programacin C } 5.5 Sentencia do-while La sentencia tiene la forma: do Instruccin; while(Condicin); Los parntesis no son opcionales. Se ejecuta la instruccin y si se cumple la condicin se repite el proceso. int f1=0, f2=1,i=1,f; do /* sentencia do-while parecida al repetir-hasta algortmico*/ { f=f1+f2; f1=f2; f2=f; i = i+1; } while (i<n); Ntese que aunque la sentencia do-while es similar al repetir-hasta, se diferencian en que la condicin del do-while debe cumplirse para seguir iterando y la del repetir-hasta debe ser falsa para iterar. 5.6 Sentencia for C tiene una sentencia for que difiere bastante de la de otros lenguajes. Su forma es: for ([inicializacin]; [condicin]; [expresin]) Instruccin; El equivalente de esta expresin con while es: inicializacin; while (condicin) { Instruccin; expresin; } Cada una de las partes del for se pueden omitir. En el caso de la condicin, su omisin equivale a una condicin siempre verdadera. Si se desea ejecutar ms de una instruccin en una de las expresiones, se puede emplear el operador ",". http://www.gedlc.ulpgc.es/docencia/mp_ii/SoloAlumnos/c.html/EstructurasControl.html (3 of 6) [14/11/01 18:33:27] Estructuras de Control. Introduccin al Lenguaje de Programacin C Ejemplo: Colocar los primeros n elementos de dos vectores b y c, a cero. for (i = 0; i<n; i++) { b[i] = 0; c[i] = 0; } 5.7 Sentencia break La sentencia break se puede colocar dentro de un bucle o bucles anidados. Cuando se ejecuta la sentencia break se abandona el bucle ms interno. Ejemplo: for(j=inicio;j<fin;j++) /* bsqueda del primer primo desde inicio hasta fin */ { int i=2; /* prueba si es divisible por i */ while( i < j) { if(j % i == 0) break; /* no es primo, abandona el bucle*/ i++; } if(i == j) { printf ("%d es primo\n",,j); break; } } A todos los efectos la sentencia break acta como un salto a la instruccin siguiente al bucle donde se ejecuta. 5.8 Sentencia continue La sentencia continue, no abandona el bucle si no hace que se ejecute la siguiente interaccin. Ejemplo: while( i < limite) { i++; if((i & 1) == 0) continue; /* continue vuelve a la condicin del bucle */ if(primo % i == 0) break; } En los bucles while y do-while la ejecucin del continue hace que el flujo del programa salte a http://www.gedlc.ulpgc.es/docencia/mp_ii/SoloAlumnos/c.html/EstructurasControl.html (4 of 6) [14/11/01 18:33:27] Estructuras de Control. Introduccin al Lenguaje de Programacin C la condicin. En el bucle for la ejecucin del continue hace que el flujo del programa salte a la expresin de incremento, para despus continuar normalmente con la condicin. Dicho de otra forma la ejecucin del continue evita que se ejecute el resto del cuerpo del bucle. 5.9 Sentencia switch La sentencia switch en C es la anloga a case en Pascal. Hace que se seleccione un grupo de sentencias entre varias disponibles. Tiene la forma: switch(Expresin) { case Valor1: ... [break;] case Valor2: ... [break;] case Valor3: ... [break;] [default:] ... } La expresin entre parntesis del switch debe ser entera. Su resultado se comparar con los distintos valores en los case. Si coincide con uno de ellos se pasara la ejecucin a la instruccin siguiente al case con dicho valor y se seguirn ejecutando las instrucciones consecutivas hasta encontrar una instruccin break o alcanzar el cierra llaves del switch. En caso de que el resultado de la expresin no coincida con ningn valor se pasar la ejecucin a la instruccin siguiente a la etiqueta default:, si la hubiera, y se continuar como en un case. Los valores en los case pueden ser una expresin constante. No puede haber dos case con el mismo valor. Ejemplo: switch(k) { case 10: i = 6; break; /* no continuar */ case 20-4: /* equivale a "case 16" */ case 18: case 20: j = 2; k = 4; break; default: http://www.gedlc.ulpgc.es/docencia/mp_ii/SoloAlumnos/c.html/EstructurasControl.html (5 of 6) [14/11/01 18:33:27] Estructuras de Control. Introduccin al Lenguaje de Programacin C j = 5; } Si k no coincide con ningn valor de case, se selecciona la opcin default; en caso que esta ltima no exista, contina con la siguiente sentencia despus de switch. Es necesario colocar break para que no ejecute las siguientes opciones case. D http://www.gedlc.ulpgc.es/docencia/mp_ii/SoloAlumnos/c.html/EstructurasControl.html (6 of 6) [14/11/01 18:33:27] Funciones. Introduccin al Lenguaje de Programacin C 6. Funciones 6.1Definicin de funciones En C no existen procedimientos, slo existen funciones. Una funcin es equivalente a un procedimiento cuando el tipo que devuelve es void . Tambin hay que tener en cuenta que por las caractersticas de C se puede despreciar el valor resultante de cualquier expresin lo que permite que se pueda ignorar el valor devuelto por una funcin. Las definiciones de funciones no pueden anidarse; todas las funciones se encuentran al mismo nivel de abstraccin. No es posible definir una funcin local a otra. Lo que no quiere decir que una funcin no pueda llamarse a s misma o a cualquier otra. Las funciones se definen indicando primero que tipo de valor devuelven, despus el nombre de la funcin y a continuacin los parmetros que acepta encerrados entre parntesis y separados por comas. El formato de la definicin de funciones es el siguiente: tipo_devuelto nombre_funcin(tipo1 param1,tipo2 param2, ...) { ... } 6.2 Paso de parmetros a una funcin Los parmetros en C se pasan siempre por valor; lo que quiere decir que se produce una copia del valor pasado al parmetro de la funcin, el cual no acta si no como una variable local a la funcin pero con una inicializacin externa. En C no est permitido pasar a una funcin parmetros que sean vectores, o funciones, si bien se pueden pasar punteros a estos. El nombre de un vector, cuando se escribe sin subndice, se interpreta como un puntero al primer elemento del vector. Ejemplos: void sv( int v[20], int n) { int i,s; for(i=0, s=0;i<n;i++) s+=v[i]; printf("Suma %d\n",s); } int v1[10]; void f() { int v2[30]; ... sv(v1,10); sv(v2,15); } http://www.gedlc.ulpgc.es/docencia/mp_ii/SoloAlumnos/c.html/Funciones.html (1 of 7) [14/11/01 18:33:30] Funciones. Introduccin al Lenguaje de Programacin C En el ejemplo anterior la definicin de un vector v[20] como parmetro de entrada tiene una interpretacin distinta a la aparente. En C, como no se pueden pasar vectores como parmetros se pasa un puntero a stos (en realidad un puntero al primer elemento) y esto es lo que siempre ocurre. La interpretacin de la definicin es la siguiente: La funcin tiene como parmetro un vector; este vector como no existe chequeo de rangos puede ser de cualquier tamao, el 20 no es sino una cifra informativa, incluso se puede sustituir la definicin por int v[]. Adems por la relacin existente entre vectores y punteros se puede definir como int *v, con la diferencia que ahora se puede modificar el puntero v. Parmetros de entrada/salida C, como ya se ha dicho previamente, no dispone de parmetros de entrada y salida. La forma de simular estos parmetros en C es la siguiente: el parmetro se define como un puntero al tipo de la variable de entrada/ salida y en la llamada a la funcin se pasa la direccin de la variable que se desea modificar; internamente, mediante el puntero, se accede y modifica el dato externo. En el siguiente ejemplo se muestra el uso de esta tcnica. Se tiene un procedimiento spmatriz que calcula la suma y el producto de los elementos almacenados en una matriz de enteros, para obtener estos dos datos se pasan como parmetros dos punteros a enteros. void spmatriz( int m[][10], int n, int *s, int *p) { int i, j; *s=0;*p=1; for(i=0;i<n;i++) for(j=0;j<10;j++) { *s += m[i][j]; *p *= m[i][j]; } } void Usa() { int m1[3][10], m2[5][10]; int r1, r2; ... spmatriz(m1,3,&r1,&r2); ... spmatriz(m2,4,&r1,&r2); } Funciones sin parmetros Una de las grandes fuentes de errores en el pre ANSI C era la relajacin en la comprobacin del tipo y nmero de parmetros pasados a una funcin. Cuando usamos una funcin antes de su definicin el compilador desconoce de que tipo son sus parmetros formales. Un problema para los redactores del estndar fue mantener la compatibilidad con lo anterior y aumentar los niveles http://www.gedlc.ulpgc.es/docencia/mp_ii/SoloAlumnos/c.html/Funciones.html (2 of 7) [14/11/01 18:33:30] Funciones. Introduccin al Lenguaje de Programacin C de comprobacin. La solucin dada es requerir que las funciones estn declaradas antes de usarse y establecer un mecanismo para definir funciones que no acepten parmetros. Este ltimo caso se establece poniendo como nico parmetro void. En caso de definir una funcin sin parmetros estaramos indicando que acepta cualquier nmero de parmetros. Ejemplo: int f(void) /* No acepta parmetros */ { ... } 6.3 Sentencia return La forma en que las funciones en C devuelven un valor es empleando la sentencia return. Esta sentencia puede aparecer en cualquier punto de la funcin y cuantas veces sea necesario. Su ejecucin implica el inmediato abandono de la funcin. El valor devuelto por la funcin se obtiene de la expresin que se aade al return. En el caso de los procedimientos, funciones que devuelven void, tambin es posible emplear return para abandonar la funcin en cualquier punto. Ejemplos: int sum(int i,int j) /* esta funcin devuelve un entero */ { return i+j; /* Suma los parmetros y devuelve el resultado */ } void vsuma( int v[],int n) { int i,s; if(n <= 1) return; for(i=0;i<(n-1);i++) v[i+1]+=v[i]; /* return implcito no es necesario ponerlo */ } 6.4 Prototipado de funciones Si deseamos usar una funcin antes de definirla o que se encuentra en las bibliotecas o en otro fichero del programa, la va de informar al compilador del tipo de parmetros su nmero y tipo que devuelve es haciendo una declaracin prototipo de la funcin. La forma de realizar el prototipado es similar a la definicin de la funcin pero omitiendo el cuerpo de esta y terminando en ";". Ejemplo: int sum(int i,int j); /* podemos usar sum sin haberla definido*/ 6.5 Otros ejemplos http://www.gedlc.ulpgc.es/docencia/mp_ii/SoloAlumnos/c.html/Funciones.html (3 of 7) [14/11/01 18:33:30] Funciones. Introduccin al Lenguaje de Programacin C Procedimiento recursivo que inserta al final de una lista de nodos. ( descargar) typedef struct Tnodo { int Info; struct Tnodo *Sig; } TNodo; void Inserta(TNodo **p, int i) { TNodo *aux=*p; if(aux == NULL) /*Condicin base, final de lista */ { aux = (TNodo *) malloc(sizeof(TNodo)); aux->Info = i; aux->Sig=NULL; *p=aux; } else Inserta(&(aux->Sig), i); } void Usa( void) { TNodo *f=NULL; Inserta(&f,1); Inserta(&f,2); Inserta(&f,3); ... } 6.6 Operaciones bsicas de entrada y salida C no tiene implementadas sentencias de E/ S. Las entradas y salidas se realizan usando funciones de la biblioteca. Como funciones bsicas se tienen "printf" y " scanf": printf tiene una declaracin prototipo como esta: int printf( char *format, ...); Ejemplo de uso: printf ("x = %d y = %0 z = %x\n", x, y, z); El primer parmetro es una ristra de caracteres, la cual especifica el formato de impresin y a continuacin una lista de parmetros de nmero variable, que sern los datos a mostrar. La funcin printf devuelve el nmero de parmetros mostrados. Los caracteres de la ristra se escriben tal cual a excepcin del %. El % indica que hay que mostrar un parmetro de la lista, el siguiente al ltimo mostrado, con un formato concreto el cual lo indica el carcter que sigue al http://www.gedlc.ulpgc.es/docencia/mp_ii/SoloAlumnos/c.html/Funciones.html (4 of 7) [14/11/01 18:33:30] Funciones. Introduccin al Lenguaje de Programacin C %. Los caracteres ms comunes y el tipo de datos que representa se muestra en la siguiente tabla: Carcter Formato d Entero decimal. i Entero decimal. o Entero en octal. u Entero decimal sin signo. x Entero en hexadecimal. s Ristra de caracteres. c Un nico carcter. ld Entero largo decimal. lu Entero largo decimal sin signo. lx Entero largo sin signo hex. e Coma flotante notacin cientfica. f Coma flotante. g, e f El ms corto. lf Real largo en coma flotante Hay que tener en cuenta que los literales de ristras permiten escribir caracteres especiales con lo que se denomina una secuencia de escape. La secuencia de escape comienza siempre con "\ " y a continuacin se escribe otro carcter que representa el cdigo especial o el nmero en octal o hexadecimal de su cdigo ASCII. Las secuencias de escape representan un nico carcter en la ristra donde aparecen. Carcter o secuencia Equivalencia a sonido b backspace f salto de pgina n nueva lnea r retorno de carro t tabulador horizontal v tabulador vertical \ \ ' comilla simple " comilla doble http://www.gedlc.ulpgc.es/docencia/mp_ii/SoloAlumnos/c.html/Funciones.html (5 of 7) [14/11/01 18:33:30] Funciones. Introduccin al Lenguaje de Programacin C ? Interrogacin 000 El carcter ASCII del nmero en octal xhhhh El carcter ASCII del nmero en hexadecimal La funcin scanf(), se utiliza para la entrada de datos; usa prcticamente el mismo formato que printf con la salvedad de que como parmetros no se pasan variables sino punteros a estas. Es necesario pasar las direcciones de las variables ya que es la nica forma de poderlas modificar desde una funcin. La ristra de formato pasada a scanf() define como es la entrada a procesar, en ningn caso establece texto a mostrar durante la ejecucin de la funcin. Ejemplo de uso: scanf("%d",&x); interpreta la ristra de caracteres de entrada como un decimal, y lo coloca en la direccin de x. Ejemplo de empleo de printf y scanf: ( descargar) int main() { char c1, c2, c3; int k; float x; double y; printf( "\nintroduzca lo siguiente: tres caracteres,"); printf("\n%s\n%s\n%s", " un int,", " un float,", " y un double: "); scanf("%c%c%c%d%f%lf", &c1, &c2, &c3, &k, &x, &y); printf("\nstos son los datos introducidos:\n"); printf(" %c %c %c %d %e %lf\n\n",c1,c2,c3,k,x,y); return 0; } Ejecucin: introduzca lo siguiente: tres caracteres, un int, un float, y un double: ABC 1 22 33.3 stos son los datos introducidos: A B C 1 2.2e+01 3.33e+01 http://www.gedlc.ulpgc.es/docencia/mp_ii/SoloAlumnos/c.html/Funciones.html (6 of 7) [14/11/01 18:33:30] Funciones. Introduccin al Lenguaje de Programacin C D http://www.gedlc.ulpgc.es/docencia/mp_ii/SoloAlumnos/c.html/Funciones.html (7 of 7) [14/11/01 18:33:30] Preprocesador. Introduccin al Lenguaje de Programacin C 7. Preprocesador de C El preprocesador es una parte del compilador que realiza una transformacin del cdigo fuente antes de pasar a la compilacin propiamente dicha. El procesador es el encargado de la inclusin de ficheros, compilacin condicional y definicin y expansin de macros. Para indicarle al preprocesador la realizacin de estas tareas este posee un lenguaje propio. Las directivas del preprocesador comienzan siempre con el smbolo # y emplean toda la lnea en la que se utilizan. A continuacin se tiene una tabla con las directivas del preprocesador junto a una breve descripcin. Directiva Descripcin #include #define #undef #if #ifdef #ifndef #elif #else #endif #line #error #pragma # Inclusin de ficheros. Definicin de macros. Deja de estar definida una macro. Compilacin condicional si se cumple condicin. Compilacin condicional si la macro esta definida. Compilacin condicional si la macro no esta definida. Compilacin condicional si no se cumple condicin anterior y si actual. Compilacin condicional si no se cumple condicin. Fin de compilacin condicional. Establece valor de macros __LINE__ y __FILE__. Error con mensaje. Establece opciones de compilacin. Directiva nula, sin efecto. 7.1Inclusin de ficheros. La inclusin de un fichero da como resultado la sustitucin de la instruccin por el contenido del fichero a incluir. El contenido incluido es tambin preprocesado. Formato: #include "NombreFichero"| <NombreFichero> Cuando el nombre de fichero va entre comillas, este se busca a partir del directorio de trabajo. Ejemplo: #include "file.h" Ordena al preprocesador que incluya todos las lneas del fichero " file.h" del directorio de trabajo. Cuando el nombre del fichero se encierra entre los signos de "menor que" y "mayor que", este se busca a partir del directorio especial include. Ejemplo: #include <stdio.h> http://www.gedlc.ulpgc.es/docencia/mp_ii/SoloAlumnos/c.html/Preprocesador.html (1 of 4) [14/11/01 18:33:32] Preprocesador. Introduccin al Lenguaje de Programacin C 7.2 Definicin y expansin de macros. Una macro no es sino una forma de sustitucin de una serie de caracteres por otros. Formato: # define NombreMacro[(parmetros)] CuerpoMacro Una vez definida una macro. Cuando se encuentra la secuencia de caracteres "NombreMacro" se sustituye por el cuerpo de la macro. En caso de que existan parmetros, estos sern reemplazados adecuadamente en el cuerpo de esta. Ejemplo: #define BLOCK_SIZE 1024 Define una macro BLOCK_SIZE y le da el valor 1024, cada ocurrencia de los diez caracteres BLOCK_SIZE en el fichero se sustituyen por los cuatro caracteres 1024. Las macros se escriben normalmente en maysculas, y pueden tener parmetros. Si es necesaria ms de una lnea para definir un macro se usa al final de la lnea el carcter "\ " Ejemplo de macro con parmetros: #define SQR(X) ((X)*(X)) ... i=SQR(j); /* la salida del preprocesador ser i=((j)*(j)); */ 7.3 Compilacin condicional. Permite decidir si una parte del programa va a ser compilada o no, dependiendo de una condicin. En la compilacin condicional se emplean diversas directivas, entre las que se pueden destacar las siguientes: #if Condicin La condicin debe ser una expresin calculable en tiempo de compilacin. Si la condicin es verdadera se incluir en el cdigo desde ese punto hasta encontrar un "else", "elif" o "endif". En caso de que la condicin sea falsa se procesara el "else"o el "elif". #ifdef Macro Funciona igual que el "if" pero la condicin a cumplir es que una macro este definida o no. #ifndef Macro Funciona como "ifdef" pero al contrario, la condicin se cumple si la macro no est definida. #elif Condicin http://www.gedlc.ulpgc.es/docencia/mp_ii/SoloAlumnos/c.html/Preprocesador.html (2 of 4) [14/11/01 18:33:32] Preprocesador. Introduccin al Lenguaje de Programacin C En caso de que se alcance esta directiva al no cumplirse la condicin de un "if" o "ifdef", se evala la condicin. Si la condicin es verdadera se incluye hasta el siguiente "elif" o "endif". En caso de que la condicin sea falsa se acta igual que en un "if". #else En caso de que no se cumpla las condiciones de un "if", "ifdef" o "elif" y exista un "else" se incluye el cdigo desde el "else" hasta el siguiente "endif". #endif Indica el final de una estructura "if" o "ifdef". Con las directivas anteriores se puede establecer como formato de estructuras condicionales el siguiente: #if Condicin|#ifdef Macro|#ifndef Macro Cdigo [#elif Condicin] Cdigo [#elif Condicin] ... [#else] Cdigo #endif Ejemplo de funcin que, segn este definida o no una macro, se compila para usar un vector auxiliar en memoria dinmica o en la pila int Ordena( int Vector[], int n) { ... #ifdef USAHEAP int *aux; aux= ( int *) malloc(n* sizeof( int)); #else int aux[MAXSIZE]; #endif< ... #ifdef USAHEAP free(aux); #endif } Por ejemplo, si "USAHEAP" estuviese definido se tendra como resultado del preproceso el siguiente cdigo: int Ordena( int Vector[], int n) { http://www.gedlc.ulpgc.es/docencia/mp_ii/SoloAlumnos/c.html/Preprocesador.html (3 of 4) [14/11/01 18:33:32] Preprocesador. Introduccin al Lenguaje de Programacin C ... int *aux; aux= ( int *) malloc(n* sizeof( int)); ... free(aux); } Si "USAHEAP" no estuviese definido y "MAXSIZE" valiese "100" se tendra este otro cdigo: int Ordena( int Vector[], int n) { ... int aux[100]; ... } D http://www.gedlc.ulpgc.es/docencia/mp_ii/SoloAlumnos/c.html/Preprocesador.html (4 of 4) [14/11/01 18:33:32] Estructura de un programa. Introduccin al Lenguaje de Programacin C 8. Estructura de un programa 8.1Introduccin Un programa en C consiste de uno o ms ficheros fuente. Cada fichero fuente se debe poder compilar por separado. Los ficheros fuentes contienen prototipado de funciones, definiciones de tipos, definiciones de variable, definiciones de funciones y variables, etc. En uno de estos ficheros y solo en uno debe existir una funcin denominada "main". La compilacin separada implica que cada fichero fuente debe contener toda la informacin necesaria para que el compilador pueda compilarlo y generar un fichero objeto. Es de destacar que los ficheros objetos contienen cdigo casi ejecutable a falta de resolver direcciones no conocidas por el compilador en tiempo de compilacin. El enlazador es el encargado de reunir los ficheros objeto y los elementos necesarios de la biblioteca de funciones para resolver esas referencias desconocidas y formar un programa ejecutable. 8.2 Modularidad Un mdulo se puede definir como una parte discreta y lgicamente autocontenida de un programa mayor. Un programa completo se puede considerar como un conjunto de mdulos. Un mdulo construido apropiadamente acepta entradas bien definidas y lleva a cabo un conjunto de acciones tambin bien definidas para producir una salida bien definida. El propsito de la programacin modular es dividir tareas ms complejas en otras ms pequeas y simples. Un programa que conste de mdulos con un mbito apropiadamente diseado es ms fcil de disear escribir y probar que el mismo programa cuando no se modulariza. Adems, las interacciones entre las partes de un programa o sistema pueden ser restringidas a las interacciones entre mdulos lo que simplifica enormemente la compresin del programa. El concepto de mdulo abarca los conceptos de encapsulamiento y ocultacin de informacin. Encapsulamiento es la tcnica para aislar algunas de las decisiones que se toman al escribir un programa. Para encapsular decisiones un mdulo se organiza como una interface y una parte interna, todos los accesos al mdulo se realizan a travs de la interface. Como resultado los otros mdulos no pueden referenciar variables internas o transferir directamente el control a las partes internas del mdulo. La ocultacin de informacin es el principio usado para dividir los programas en mdulos. El objetivo es producir software que acepte cambios y que ayude a manejar la complejidad durante los procesos de desarrollo y mantenimiento. El principio de ocultacin de informacin establece que la informacin que pueda cambiar debe ocultarse. Un ejemplo de informacin a ocultar son las estructuras de datos. Para alcanzar estos objetivos el software diseado usando la ocultacin de informacin se estructura en mdulos los cuales se intenta que sean independientemente reemplazables y comprensibles. Una buena modularizacin es esencial en el desarrollo de grandes sistemas de software si se desea que las distintas partes puedan integrarse en un perodo de tiempo razonable. Adems, una buena modularizacin ayuda a llevar a cabo ms rpido y mejor el proceso de mantenimiento y modificacin que requieren todos los programas. Implementacin del mdulo En C cada mdulo coincide con un fichero fuente. Este fichero fuente define las variables y funciones del modulo. A cada fichero fuente se le asocia un fichero que tiene el papel de declarar la interface del modulo. A estos ficheros se les denomina "ficheros cabecera". La forma de ocultar la informacin en el fichero fuente se realiza por medio del modificador static. Las http://www.gedlc.ulpgc.es/docencia/mp_ii/SoloAlumnos/c.html/EstructuraPrograma.html (1 of 7) [14/11/01 18:33:35] Estructura de un programa. Introduccin al Lenguaje de Programacin C variables globales y funciones con el modificador static no pueden ser accedidas desde otro modulo. Incluso, las variables definidas dentro de las funciones como static se comportan como variables globales, pero slo accesibles desde la funcin. Los ficheros cabecera tpicamente contienen las declaraciones de variables por medio de la palabra reservada extern, el prototipado de las funciones accesibles del modulo, la definicin de tipos y macros. El siguiente cuadro ilustra los tipos de variables en C, segn el tiempo de existencia y mbito de acceso a stas. Tipo Como se define mbito Existencia Global al programa Son todas aquellas variables definidas fuera de cualquier funcin sin ningn modificador de mbito. Accesible desde cualquier funcin en el fichero que se define u otro en el que se declare. Para declarar la variable se hace de la misma forma como se define, pero precedida de la palabra clave extern. La misma que el programa Global al fichero Son todas aquellas variables definidas fuera de cualquier funcin y precedidas de la palabra clave static. En cuanto al mbito tambin es aplicable a funciones definidas como static. Accesible desde las funciones definidas en su mismo fichero. La misma que el programa Global a una funcin Son todas aquellas variables definidas dentro de una funcin y precedidas de la palabra clave static. Accesible solamente desde la funcin dentro de la que se define, slo existe una copia para todos los mbitos de las posibles llamadas recursivas. La misma que el programa, no pierde su valor de llamada en llamada. Local a una funcin Son todas aquellas variables definidas dentro de una funcin sin modificador o precedidas de la palabras clave register o auto, ( auto es la opcin por defecto, por lo que normalmente no se utiliza). La palabra clave register indica al compilador que intente almacenar la variable en un registro de la CPU y no en la pila. Puede acceder a ellas slo la funcin donde se defini. Si se producen llamadas recursivas cada funcin tendr su propia variable. Mientras la ejecucin est dentro del bloque donde se cre. Variables en memoria dinmica Se crean con la funcin malloc y se destruyen con free. Puede usarlas todo aquel que posea un puntero a ellas. Mientras no se destruyan. http://www.gedlc.ulpgc.es/docencia/mp_ii/SoloAlumnos/c.html/EstructuraPrograma.html (2 of 7) [14/11/01 18:33:35] Estructura de un programa. Introduccin al Lenguaje de Programacin C Ejemplo: int Global; /*Global al programa, puede ser accedida desde cualquier funcin del programa */ static int Local; /*Global al fichero, puede ser accedida slo por las funciones del fichero */ int main() { int i ; /*Local a la funcin */ register short int Z1, Z2;/*Automticas, se intentan almacenar en un registro de CPU*/ auto double x; /*Local a la funcin, poner auto es opcional*/ static int NL; /*Global a la funcin, su valor no se pierde en cada ejecucin*/ extern long flag_pole; /*Externa, se encuentra definida en otro fichero del programa*/ int *Vector; /* Puntero a un entero o ms*/ Vector = ( int*) malloc(sizeof( int)); /*Creacin de variable en memoria dinmica */ ... free(Vector); /*Destruccin de variable en memoria dinmica */ } Ficheros cabecera En un programa lo normal es que a cada fichero fuente se le asocie otro que recoja declaraciones prototipo de sus funciones y extern de sus variables globales; de manera que si otro modulo desea hacer uso de este modulo no tiene sino que incluir su fichero asociado. Estos ficheros normalmente tienen la extensin ".h". Para un correcto uso de la biblioteca en C se deben incluir ficheros cabecera (.h) que se encuentran en un directorio denominado include. Estos ficheros cabecera contienen principalmente declaraciones prototipo de las funciones que se almacenan en la biblioteca. Si no se realizan estas inclusiones el compilador asignar a las funciones de la biblioteca, tipos de parmetros y de retorno de forma automtica con el peligro de que no sea correcta. Ejemplo de programa de un nico fichero El programa realiza las siguientes tareas: 1. Primero, imprime informacin sobre el programa. 2. Lee un valor para la variable int n. 3. Lee n nmeros reales de tipo double. 4. Calcula los valores mnimo y mximo. 5. Muestra el mnimo y mximo. Pulse aqu para descargar el fichero fuente. #include <stdio.h> int main () { int i, n; double min, max, x; double minimo( double, double), maximo( double, double); /* declaracin prototipo de las funciones */ printf("\n%s\n%s\n%s", "info: este programa lee un valor entero para n", " y despus procesa n nmeros reales para", " encontrar los valores mnimo y mximo."); http://www.gedlc.ulpgc.es/docencia/mp_ii/SoloAlumnos/c.html/EstructuraPrograma.html (3 of 7) [14/11/01 18:33:35] Estructura de un programa. Introduccin al Lenguaje de Programacin C printf("\n\nintroduzca n : "); scanf("%d", &n); printf("\n\nintroduzca %d nmeros reales: ", n); scanf("%lf", &x); min = max = x; for (i = 2; i < = n: ++i) { scanf("%lf", &x); min = minimo (min, x); max = maximo (max, x); } printf("\n\nvalor mn = %f\nvalor mx = %f\n\n", min, max); return 0; } double minimo ( double x, double y) { if (x < y) return (x); else return (y); } double maximo ( double x, double y) { if (x > y) return (x); else return (y); } 8.3 Obtencin del ejecutable de un programa En la figura siguiente se muestran los pasos a seguir para construir un ejecutable de un programa en C, partiendo de los ficheros fuente que lo componen.
Cada fichero fuente se compila por separado obteniendo su correspondiente fichero objeto. Una vez que se tienen todos los ficheros objetos necesarios se enlazan junto a las funciones de la biblioteca para http://www.gedlc.ulpgc.es/docencia/mp_ii/SoloAlumnos/c.html/EstructuraPrograma.html (4 of 7) [14/11/01 18:33:35] Estructura de un programa. Introduccin al Lenguaje de Programacin C obtener el programa ejecutable. En la figura anterior se muestran los detalles de la fase de compilacin. La compilacin de cada fichero fuente requiere de la inclusin de los ficheros cabecera de la biblioteca de funciones necesarios y del resto de los mdulos usados. Esta informacin es necesaria para que el compilador sea capaz de hacer correctamente su trabajo. Ejemplo de programa multi-fichero: Mdulo Vecutil El mdulo "Vecutil" suministra como servicios tres funciones "Ordena", "Maximo" y "Minimo" que ordenan un vector de enteros, devuelve el valor mximo y el valor mnimo respectivamente. Adems informa, por medio de una variable global, si se ha producido un error o no, en alguna de las llamadas a las funciones. Tambin define una macro con el tamao mximo de vector que admite. En la implementacin se ocultan dos elementos: la funcin "SelOrdena", funcin interna de la ordenacin, y la variable "Contador", tambin variable interna. Estos dos elementos no pueden ser accedidos desde otro mdulo. Fichero "Vecutil.c" #include <stdlib.h> #include "vecutil.h" int vecerror=0; void Ordena( int v[], int n) { static int aux[MAXVEC]; ... } static int Contador=0; static void SelOrdena( int v[], int n) { ... } http://www.gedlc.ulpgc.es/docencia/mp_ii/SoloAlumnos/c.html/EstructuraPrograma.html (5 of 7) [14/11/01 18:33:35] Estructura de un programa. Introduccin al Lenguaje de Programacin C int Maximo(int v[], int n) { ... } int Minimo(int v[], int n) { ... } Fichero "Vecutil.h" # ifndef INC_VECUTIL #define INC_VECUTIL #define MAXVEC 10000 extern int vecerror=0; void Ordena( int v[], int n); int Maximo(int v[], int n); int Minimo(int v[], int n); #endif Mdulo Principal El mdulo principal contiene la funcin "main", la cual llama a las funciones del mdulo "vectutil" y accede a la variable "vecerror". La funcin "main", lee en un vector un nmero de enteros muestra el mnimo, el mximo y ordena el vector. Fichero "principa.c" #include <stdio.h> #include "Vecutil.h" int main() { int n=MAXVEC, i; int vec[MAXVEC]; for (i=0; i<n; i++) { printf("leer el %d-simo elemento ", i);scanf("%d",&vec[i]); } printf("el elemento mximo del vector es %d", Maximo(vec, n)); printf("el elemento mnimo del vector es %d", Minimo(vec, n)); Ordena(vec, n); if(vecerror) printf("Error en la ordenacin\n"); return 0; } Es necesario, pero no imprescindible, reunir todas las partes de forma coherente para formar un programa. En UNIX se crea un fichero que describe las partes que componen el programa, y la utilidad make se encarga de llamar al compilador para los ficheros necesarios y llamar al enlazador para generar el ejecutable. En los entornos de desarrollo ms evolucionados se crea un project en el cual se especifica qu ficheros componen el programa. El entorno se encarga de detectar dependencias y compilar y enlazar de forma inteligente. http://www.gedlc.ulpgc.es/docencia/mp_ii/SoloAlumnos/c.html/EstructuraPrograma.html (6 of 7) [14/11/01 18:33:35] Estructura de un programa. Introduccin al Lenguaje de Programacin C D http://www.gedlc.ulpgc.es/docencia/mp_ii/SoloAlumnos/c.html/EstructuraPrograma.html (7 of 7) [14/11/01 18:33:35] Biblioteca de funciones. Introduccin al Lenguaje de Programacin C 9. Biblioteca de funciones C posee un gran nmero de conjuntos de funciones de biblioteca que esta asociados a diversos ficheros cabecera. En este apartado se muestra las funciones y macros ms usuales que se prototipan y definen en los diversos ficheros cabecera. 9.1<stdio.h> Declara funciones y define tipos y macros necesarios para el Paquete Estndar de E/ S definido por Kernighan and Ritchie y extendido bajo UNIX system V. Algunas de las funciones que define ya se han visto como "printf" y "scanf" y otras se vern en detalle en el apartado de manejo de ficheros. A continuacin se muestran otras funciones de entrada y salida por consola: Funcin Descripcin int getchar(void) devuelve un caracter leido del teclado int putchar(int c) muestra por pantalla un carcter char *gets(char *s) lee en s una ristra del teclado hasta el newline int puts(char *s) muestra por pantalla la ristra s y le aade newline 9.2 <stdlib.h> El fichero <stdlib.h> declara algunas rutinas y macros de uso general tales como: conversin, manejo bsico de memoria dinmica, etc. En el siguiente cuadro se muestra los elementos ms usados que contiene. Funcin Descripcin NULL define la macro del puntero nulo void * malloc(int n) devuelve un puntero a un bloque de memoria de n bytes. void free(void *p) libera el espacio previamente obtenido con malloc. int atoi(char *) devuelve un entero con el valor numrico de la ristra pasada. long atol(char *) devuelve un entero largo con el valor numrico de la ristra pasada. double atof(char *) devuelve un real con el valor numrico de la ristra pasada. int rand(void) devuelve un nmero pseudo aleatorio void srand(unsigned int s) establece un punto de inicio en la secuencia aleatoria int abs(int x) long labs(long x) devuelve el valor absoluto de un entero http://www.gedlc.ulpgc.es/docencia/mp_ii/SoloAlumnos/c.html/BibliotecaFunciones.html (1 of 3) [14/11/01 18:33:38] Biblioteca de funciones. Introduccin al Lenguaje de Programacin C 9.3 <string.h> Declara rutinas de manipulacin de string y memoria. Las principales funciones se muestran a continuacin: Funcin Descripcin char * strcpy(char *d, char *f) copia la ristra apuntada por f en la apuntada por d. y devuelve d actualizada char * strcat(char *d, char *f) concatena una copia de f al final de la ristra apuntada por d y devuelve d int strcmp(char *s1, char *s2) si s1 > s2 devuelve un valor positivo si s1 == s2 devuelve 0 si s1 < s2 devuelve un valor negativo int strlen(char *) devuelve la longitud de la ristra. char* strstr(char *s1, char *s2) Busca s2 en s1 y devuelve un puntero a la primera aparicin de s2 en s1, si no encuentra s2 devuelve un nulo. 9.4 <assert.h> Este fichero define la macro assert. A la macro "assert" se le pasa una condicin y la comprueba. En caso de que la condicin sea falsa se detiene la ejecucin del programa indicando el fichero y la lnea donde se produjo el incumplimiento de la condicin. En caso contrario continua la ejecucin normalmente. A continuacin se muestra el contenido del fichero cabecera "assert.h". Este fichero si no esta definida la macro "NDEBUG" define la macro "assert". Si esta definida la macro "NDEBUG", "assert" se define de forma que se expanda a una instruccin nula. void _assertfail(char *__msg, char *__cond, char *__file, int __line); #undef assert #ifdef NDEBUG #define assert(p) ((void)0) #else #define assert(p) ((p) ? (void)0 :(void) __assertfail( \ "Assertion failed: %s, file %s, line %d"_ENDL, \ #p, __FILE__, __LINE__ ) ) #endif Esta macro se usa para la depuracin de cdigo. Establece controles sobre condiciones que se deben cumplir en la ejecucin, con la ventaja de que en caso de que no deseemos realizar comprobaciones la definicin de NDEBUG provoca que no se evalen. 9.5 <math.h> Este fichero prototipa diversas funciones matemticas de las cuales algunas de ellas se muestran http://www.gedlc.ulpgc.es/docencia/mp_ii/SoloAlumnos/c.html/BibliotecaFunciones.html (2 of 3) [14/11/01 18:33:38] Biblioteca de funciones. Introduccin al Lenguaje de Programacin C en el siguiente cuadro: Funcin Descripcin double pow(double x,double y) devuelve x elevado a y double sqrt(double x) devuelve la raz cuadrada de x double ceil(double x) devuelve el redondeo superior de x double floor(double x) devuelve el redondeo inferior de x double fabs(double x) devuelve el valor absoluto de x double log(double x) devuelve el logaritmo neperiano de x double log10(double x) devuelve el logaritmo en base 10 de x double sin(double x) devuelve el seno de x (x en radianes) double cos(double x) devuelve el coseno de x (x en radianes) double tan(double x) devuelve la tangente de x (x en radianes) D http://www.gedlc.ulpgc.es/docencia/mp_ii/SoloAlumnos/c.html/BibliotecaFunciones.html (3 of 3) [14/11/01 18:33:38] Operaciones sobre ficheros. Introduccin al Lenguaje de Programacin C 10. Operaciones sobre ficheros En C las operaciones sobre ficheros se pueden clasificar en tres grupos: las operaciones generales, las de manipulacin de ficheros texto y las de ficheros de acceso directo. Las funciones de manejo de ficheros que se van a mostrar en esta seccin son las que se prototipan incluyendo el fichero cabecera "stdio.h", por lo que para usarlas es necesario incluir dicho fichero. Todas las funciones de acceso a ficheros tienen un parmetro que establece sobre qu fichero se debe realizar la operacin solicitada. A este parmetro se le denomina descriptor del fichero. Los descriptores de fichero se usan mediante punteros a la estructura FILE definida en "stdio.h". 10.1Operaciones generales La funcin fopen es la encargada de abrir el fichero, se le pasa el nombre del fichero a abrir y a continuacin una ristra que especifica el modo en que se desea abrir. La ristra de modo puede contener los siguientes caracteres: r (lectura), w (escritura), a (aadir), b (binario), t (texto) y +. La funcin devuelve un puntero al descriptor del fichero, el cual se debe emplear en las siguientes rutinas de manejo de ficheros. En caso de error en la apertura del fichero la funcin devuelve el puntero nulo, NULL. Ejemplo: { FILE *fd; fd=fopen("prueba.dat","r"); /* Apertura del fichero en modo lectura y texto */ fclose se encarga de cerrar un fichero abierto previamente con fopen, simplemente se le pasa el puntero al descriptor del fichero abierto. A continuacin se muestra una tabla con la mayora de los modos de apertura. Modos de apertura de ficheros Modo Tipo de fichero Lectura Escritura Creacin Truncamiento "r" "rb" "r+" "r+b" "rb+" "w" "wb" "w+" "w+b" "wb+" "a" "ab" "a+" "a+b" "ab+" texto binario texto binario binario texto binario texto binario binario texto binario texto binario binario si si si si si no no si si si no no si si si no no si si si si si si si si si si si si si no no no no no si si si si si si si si si si no no no no no si si si si si no no no no no http://www.gedlc.ulpgc.es/docencia/mp_ii/SoloAlumnos/c.html/Ficheros.html (1 of 5) [14/11/01 18:33:40] Operaciones sobre ficheros. Introduccin al Lenguaje de Programacin C La diferencia entre un fichero texto y uno binario est en que en los ficheros texto algunos caracteres son interpretados en la lectura y escritura, dando como resultado que si se almacenan datos binarios en este modo no se garantiza la lectura correcta. La columna de creacin indica si se crea el fichero en caso de que no exista. La columna de truncamiento indica si se borra la informacin almacenada previamente, en caso de que el fichero ya exista. En el siguiente cuadro se muestra el formato de las operaciones generales sobre ficheros: Operaciones generales Funcin (declaracin prototipo) Descripcin FILE *fopen( char *nombre, char *modo); Abre, crea y trunca un fichero segn el modo. int fclose(FILE *fichero); Cierra un fichero. int feof(FILE *fichero); Devuelve verdadero si el cursor del fichero se encuentra en el final, devuelve falso en otro caso. int fflush(FILE *fichero); Escribe en el fichero los datos que est pendiente de escribirse en el buffer. 10.2 Ficheros de texto Las funciones de manejo de ficheros texto son exactamente las mismas que las de entrada y salida por consola, solamente que aadiendo una f al nombre de la funcin (fprintf, fscanf, etc) y aadiendo como parmetro el puntero al descriptor del fichero. Operaciones en ficheros texto Funcin (declaracin prototipo) Descripcin int fprintf(FILE *fichero, char *formato, ...); Escribe el resultado de printf en el fichero especificado. int fscanf(FILE *fichero, char *formato, ...); Lee igual que scanf del fichero especificado. int fputc(int caracter, FILE *fichero); Escribe un carcter en el fichero especificado int fgetc(FILE *fichero); Lee un carcter del fichero especificado int *fputs(char *buf, FILE *fichero); Escribe una ristra buf en el fichero especificado char *fgets(char *buf, int maxlon, FILE *fichero); Lee una ristra en buf de hasta maxlon-1 caracteres desde fichero especificado Ejemplo: (descargar) #include <stdio.h> int main() { http://www.gedlc.ulpgc.es/docencia/mp_ii/SoloAlumnos/c.html/Ficheros.html (2 of 5) [14/11/01 18:33:40] Operaciones sobre ficheros. Introduccin al Lenguaje de Programacin C FILE *stream; int i = 100; char c = 'C'; float f = 1.234; /* abre el fichero para escritura*/ stream = fopen("prueba.dat","w+"); /* escribe algunos datos en el fichero*/ fprintf(stream, "%d %c %f", i, c,f); /* cierra el fichero*/ fclose(stream); return 0; } 10.3 Ficheros binarios. Las funciones de manejo de ficheros binarios ven a stos como una sucesin contigua de bytes lo que permite escribir o leer cualquier cantidad de bytes en cualquier posicin del fichero. Los ficheros comienzan en la posicin cero. Operaciones en ficheros binarios Funcin (declaracin prototipo) Descripcin size_t fwrite(void *buf, size_t tam, size_t num, FILE *fich); Escribe en el fichero los datos a los que apunta buf. tam representa el tamao de cada elemento de buf y num el nmero de elementos. Se escriben num*tam bytes. size_t fread(void *buf, size_t tam, size_t num, FILE *fich); Lee del fichero los datos y los sita en la zona a la que apunta buf. tam representa el tamao de cada elemento de buf y num el nmero de elementos ledos. Se leen num*tam bytes. long ftell(FILE *fich); Devuelve la posicin del cursor del fichero. Cero ndica el principio del fichero. int fseek(FILE *fich, long des, int modo); Establece la posicin del cursor del fichero. Se le pasa un desplazamiento y un modo de interpretar ese desplazamiento. El modo puede ser: SEEK_SET, en cuyo caso el desplazamiento se interpreta desde el principio del fichero. SEEK_CUR, el desplazamiento se considera con respecto a la posicin actual del cursor. El desplazamiento puede ser negativo. SEEK_END, el desplazamiento es con respecto al final del fichero, puede ser menor o igual que cero. En caso de que el desplazamiento valga cero nos situaramos en el final del fichero. Tambin se puede usar sobre ficheros binarios. Ejemplo:(descargar) http://www.gedlc.ulpgc.es/docencia/mp_ii/SoloAlumnos/c.html/Ficheros.html (3 of 5) [14/11/01 18:33:40] Operaciones sobre ficheros. Introduccin al Lenguaje de Programacin C #include <string.h> #include <stdio.h> int main(void) { FILE *stream; char msg[] = "esto es una prueba"; char buf[20]; if ((stream = fopen("prueba.dat", "wb+")) == NULL) { fprintf(stderr, "No se puede abrir el fichero de salida.\n"); return 1; } fwrite(msg, strlen(msg)+1, 1,stream); /* se escriben datos en el fichero */ /* se coloca en el principio del fichero*/ fseek(stream, 0,SEEK_SET); /*SEEK_SET, SEEK_CUR, SEEK_END*/ fread(buf, strlen(msg)+1, 1,stream);/* se leen los datos y se muestran */ printf("%s\n", buf); fclose(stream); return 0; } En el ejemplo anterior se ilustra el uso de fwrite que tiene como parmetros de entrada un puntero a la posicin donde se encuentran los datos a escribir, el tamao de cada uno de los elementos a escribir, el nmero de los elementos a escribir y finalmente el puntero al descriptor del fichero. La funcin fread tiene exactamente los mismos parmetros. Tambin aparece la funcin fseek que se usa para posicionar el cursor del fichero, sus parmetros son: puntero al descriptor del fichero, tipo de posicionamiento (con respecto al principio, final o posicin actual del fichero) y posicin. En el siguiente ejemplo escribimos y leemos una matriz de reales. ( descargar) #include <stdio.h> int main(void) { FILE *stream; float a[10][10], b[10][10]; ... stream = fopen("prueba.dat", "wb+"); fwrite(a, sizeof (float), 100,stream); fseek(stream, 0,SEEK_SET); fread(b, sizeof (float), 100,stream); fclose(stream); return 0; } En el siguiente ejemplo se muestra una funcin "filesize" que nos devuelve el tamao en bytes de un fichero. ( descargar) http://www.gedlc.ulpgc.es/docencia/mp_ii/SoloAlumnos/c.html/Ficheros.html (4 of 5) [14/11/01 18:33:40] Operaciones sobre ficheros. Introduccin al Lenguaje de Programacin C #include <stdio.h> long filesize(FILE *stream); int main() { FILE *stream; stream = fopen("FICHERO.TXT","wb+"); fprintf(stream, "Esto es una prueba"); printf("El tamao de mi fichero en bytes es %ld\n", filesize(stream)); fclose(stream); return 0; } long filesize(FILE *stream) { long curpos, length; curpos = ftell(stream); /* ftell devuelve la posicin del cursor del fichero */ fseek(stream, 0L, SEEK_END); length = ftell(stream); fseek(stream, curpos, SEEK_SET); return length; } D http://www.gedlc.ulpgc.es/docencia/mp_ii/SoloAlumnos/c.html/Ficheros.html (5 of 5) [14/11/01 18:33:40] http://www.gedlc.ulpgc.es/docencia/mp_ii/SoloAlumnos/c.html/ejemplo61.c /****************************************************/ /* Ejemplo 1 del tema 6 */ /* Introduccin al Lenguaje de Programacin C. */ /* http://www.gedlc.ulpgc.es/docencia/mp_ii/ */ /****************************************************/ #include <stdio.h> #include <stdlib.h> typedef struct Tnodo { int Info; struct Tnodo *Sig; } TNodo; void Inserta(TNodo **p, int i) { TNodo *aux=*p; if(aux == NULL) /*Condicin base, final de lista */ { aux = (TNodo *) malloc(sizeof(TNodo)); aux->Info = i; aux->Sig=NULL; *p=aux; } else Inserta(&(aux->Sig), i); } int main() { TNodo *f=NULL; Inserta(&f,1); Inserta(&f,2); Inserta(&f,3); /* falta borrar los datos */ return 0; } http://www.gedlc.ulpgc.es/docencia/mp_ii/SoloAlumnos/c.html/ejemplo61.c [14/11/01 18:33:43] http://www.gedlc.ulpgc.es/docencia/mp_ii/SoloAlumnos/c.html/ejemplo62.c /****************************************************/ /* Ejemplo 2 del tema 6 */ /* Introduccin al Lenguaje de Programacin C. */ /* http://www.gedlc.ulpgc.es/docencia/mp_ii/ */ /****************************************************/ #include <stdio.h> int main() { char c1, c2, c3; int k; float x; double y; printf( "\nintroduzca lo siguiente: tres caracteres,"); printf("\n%s\n%s\n%s", " un int,", " un float,", " y un double: "); scanf("%c%c%c%d%f%lf", &c1, &c2, &c3, &k, &x, &y); printf("\nstos son los datos introducidos:\n"); printf(" %c %c %c %d %e %lf\n\n",c1,c2,c3,k,x,y); return 0; } http://www.gedlc.ulpgc.es/docencia/mp_ii/SoloAlumnos/c.html/ejemplo62.c [14/11/01 18:33:44] http://www.gedlc.ulpgc.es/docencia/mp_ii/SoloAlumnos/c.html/ejemplo81.c /****************************************************/ /* Ejemplo 1 del tema 8 */ /* Introduccin al Lenguaje de Programacin C. */ /* http://www.gedlc.ulpgc.es/docencia/mp_ii/ */ /****************************************************/ #include <stdio.h> int main () { int i, n; double min, max, x; double minimo( double, double), maximo( double, double); /* declaracin prototipo de las funciones */ printf("\n%s\n%s\n%s", "info: este programa lee un valor entero para n", " y despus procesa n nmeros reales para", " encontrar los valores mnimo y mximo."); printf("\n\nintroduzca n : "); scanf("%d", &n); printf("\n\nintroduzca %d nmeros reales: ", n); scanf("%lf", &x); min = max = x; for (i = 2; i < = n: ++i) { scanf("%lf", &x); min = minimo (min, x); max = maximo (max, x); } printf("\n\nvalor mn = %f\nvalor mx = %f\n\n", min, max); return 0; } double minimo ( double x, double y) { if (x < y) return (x); else return (y); } double maximo ( double x, double y) { if (x > y) return (x); else return (y); } http://www.gedlc.ulpgc.es/docencia/mp_ii/SoloAlumnos/c.html/ejemplo81.c [14/11/01 18:33:46] http://www.gedlc.ulpgc.es/docencia/mp_ii/SoloAlumnos/c.html/ejemplo101.c /****************************************************/ /* Ejemplo 1 del tema 10 */ /* Introduccin al Lenguaje de Programacin C. */ /* http://www.gedlc.ulpgc.es/docencia/mp_ii/ */ /****************************************************/ #include <stdio.h> int main() { FILE *stream; int i = 100; char c = 'C'; float f = 1.234; /* abre el fichero para escritura*/ stream = fopen("prueba.dat","w+"); /* escribe algunos datos en el fichero*/ fprintf(stream, "%d %c %f", i, c,f); /* cierra el fichero*/ fclose(stream); return 0; } http://www.gedlc.ulpgc.es/docencia/mp_ii/SoloAlumnos/c.html/ejemplo101.c [14/11/01 18:33:47] http://www.gedlc.ulpgc.es/docencia/mp_ii/SoloAlumnos/c.html/ejemplo102.c /****************************************************/ /* Ejemplo 2 del tema 10 */ /* Introduccin al Lenguaje de Programacin C. */ /* http://www.gedlc.ulpgc.es/docencia/mp_ii/ */ /****************************************************/ #include <string.h> #include <stdio.h> int main(void) { FILE *stream; char msg[] = "esto es una prueba"; char buf[20]; if ((stream = fopen("prueba.dat", "wb+")) == NULL) { fprintf(stderr, "No se puede abrir el fichero de salida.\n"); return 1; } fwrite(msg, strlen(msg)+1, 1,stream); /* se escriben datos en el fichero */ /* se coloca en el principio del fichero*/ fseek(stream, 0,SEEK_SET); /*SEEK_SET, SEEK_CUR, SEEK_END*/ fread(buf, strlen(msg)+1, 1,stream);/* se leen los datos y se muestran */ printf("%s\n", buf); fclose(stream); return 0; } http://www.gedlc.ulpgc.es/docencia/mp_ii/SoloAlumnos/c.html/ejemplo102.c [14/11/01 18:33:48] http://www.gedlc.ulpgc.es/docencia/mp_ii/SoloAlumnos/c.html/ejemplo103.c /****************************************************/ /* Ejemplo 3 del tema 10 */ /* Introduccin al Lenguaje de Programacin C. */ /* http://www.gedlc.ulpgc.es/docencia/mp_ii/ */ /****************************************************/ #include <stdio.h> int main(void) { FILE *stream; float a[10][10], b[10][10]; int i,j; for(i=0; i<10 ; i++) for(j=0; j<10 ; j++) a[i][j]=i+j; stream = fopen("prueba.dat", "wb+"); fwrite(a, sizeof (float), 100,stream); fseek(stream, 0,SEEK_SET); fread(b, sizeof (float), 100,stream); fclose(stream); return 0; } http://www.gedlc.ulpgc.es/docencia/mp_ii/SoloAlumnos/c.html/ejemplo103.c [14/11/01 18:33:49] http://www.gedlc.ulpgc.es/docencia/mp_ii/SoloAlumnos/c.html/ejemplo104.c /****************************************************/ /* Ejemplo 4 del tema 10 */ /* Introduccin al Lenguaje de Programacin C. */ /* http://www.gedlc.ulpgc.es/docencia/mp_ii/ */ /****************************************************/ #include <stdio.h> long filesize(FILE *stream); int main() { FILE *stream; stream = fopen("FICHERO.TXT","wb+"); fprintf(stream, "Esto es una prueba"); printf("El tamao de mi fichero en bytes es %ld\n", filesize(stream)); fclose(stream); return 0; } long filesize(FILE *stream) { long curpos, length; curpos = ftell(stream); /* ftell devuelve la posicin del cursor del fichero */ fseek(stream, 0L, SEEK_END); length = ftell(stream); fseek(stream, curpos, SEEK_SET); return length; } http://www.gedlc.ulpgc.es/docencia/mp_ii/SoloAlumnos/c.html/ejemplo104.c [14/11/01 18:33:50]