Vous êtes sur la page 1sur 31

Curso de programacin en C.

Miquel A Garcies
Indice

Introduccin Programas El desarrollo de un programa Tipos bsicos y variables Funciones Expresiones y operadores Conversin de tipos Control del flujo Definicin de funciones y prototipos Construccin de tipos mbito de funciones y variables Punteros El preprocesador Funciones de entrada y salida por pantalla Funciones de asignacin de memoria Funciones matemticas !peraciones con fic"eros #ibliograf$a y referencias
Introduccin. C es un lenguaje de programacin de propsito general %ue ofrece econom$a sintctica& control de flujo y estructuras sencillas y un buen conjunto de operadores' (o es un lenguaje de muy alto nivel y ms bien un lenguaje pe%ue)o& sencillo y no est especiali*ado en ning+n tipo de aplicacin' Esto lo "ace un lenguaje potente& con un campo de aplicacin ilimitado y sobre todo& se aprende rpidamente' En poco tiempo& un programador puede utili*ar la totalidad del lenguaje'

Este lenguaje "a sido estrec"amente ligado al sistema operativo ,(I-& puesto %ue fueron desarrollados conjuntamente' .in embargo& este lenguaje no est ligado a ning+n sistema operativo ni a ninguna m%uina concreta' .e le suele llamar lenguaje de programacin de sistemas debido a su utilidad para escribir compiladores y sistemas operativos& aun%ue de igual forma se pueden desarrollar cual%uier tipo de aplicacin' /a base del C proviene del #CP/& escrito por 0artin 1ic"ards& y del # escrito por 2en T"ompson en 3456 para el primer sistema ,(I- en un DEC PDP75' Estos son lenguajes sin tipos& al contrario %ue el C %ue proporciona varios tipos de datos' /os tipos son caracteres& n+meros enteros y en coma flotante& de varios tama)os' dems se pueden crear tipos derivados mediante la utili*acin de punteros& vectores& registros y uniones' El primer compilador de C fue escrito por Dennis 1itc"ie para un DEC PDP733 y escribi el propio sistema operativo en C' C trabaja con tipos de datos %ue son directamente tratables por el "ard8are de la mayor$a de computadoras actuales& como son los caracteres& n+meros y direcciones' Estos tipos de datos pueden ser manipulados por las operaciones aritm9ticas %ue proporcionan las computadoras' (o proporciona mecanismos para tratar tipos de datos %ue no sean los bsicos& debiendo ser el programador el %ue los desarrolle' Esto permite %ue el cdigo generado sea muy eficiente y de a"$ el 9xito %ue "a tenido como lenguaje de desarrollo de sistemas' (o proporciona otros mecanismos de almacenamiento de datos %ue no sea el esttico y no proporciona mecanismos de entrada ni salida' Ello permite %ue el lenguaje sea reducido y los compiladores de fcil implementacin en distintos sistemas' Por contra& estas carencias se compensan mediante la inclusin de funciones de librer$a para reali*ar todas estas tareas& %ue normalmente dependen del sistema operativo' !riginariamente& el manual de referencia del lenguaje para el gran p+blico fue el libro :3; de 2ernig"an y 1itc"ie& escrito en 3455' Es un libro %ue explica y justifica totalmente el desarrollo de aplicaciones en C& aun%ue en 9l se utili*aban construcciones& en la definicin de funciones& %ue pod$an provocar confusin y errores de programacin %ue no eran detectados por el compilador' Como los tiempos cambian y las necesidades tambi9n& en 34<= (.I establece el comit9 -=>33 para %ue desarrolle una definicin moderna y comprensible del C' El estndar est basado en el manual de referencia original de 345? y se desarrolla con el mismo esp$ritu de sus creadores originales' /a primera versin de estndar se public en 34<< y actualmente todos los compiladores utili*an la nueva definicin' ,na aportacin muy importante de (.I consiste en la definicin de un conjunto de librer$as %ue acompa)an al compilador y de las funciones contenidas en ellas' 0uc"as de las operaciones comunes con el sistema operativo se reali*an a trav9s de estas funciones' ,na coleccin de fic"eros de encabe*amiento& headers& en los %ue se definen los tipos de datos y funciones incluidas en cada librer$a' /os programas %ue utili*an estas bibliotecas para interactuar con el sistema operativo obtendrn un comportamiento e%uivalente en otro sistema' Programas. /a mejor forma de aprender un lenguaje es programando con 9l' El programa ms sencillo %ue se puede escribir en C es el siguiente@ main() { }

Como nos podemos imaginar& este programa no "ace nada& pero contiene la parte ms importante de cual%uier programa C y adems& es el ms pe%ue)o %ue se puede escribir y %ue se compile correctamente' En el se define la funcin main& %ue es la %ue ejecuta el sistema operativo al llamar a un programa C' El nombre de una funcin C siempre va seguida de par9ntesis& tanto si tiene argumentos como si no' /a definicin de la funcin est formada por un blo%ue de sentencias& %ue esta encerrado entre llaves {}' ,n programa algo ms complicado pero %ue "ace algo& es el siguiente@

#include <stdio.h> main() { printf("Hola amigos!\n"); }

Con el visuali*amos el mensaje Hola amigos! en el terminal' En la primera l$nea indica %ue se tengan en cuenta las funciones y tipos definidos en la librer$a stdio Astandard input/outputB' Estas definiciones se encuentran en el fic"ero header stdio.h' "ora& en la funcin main se incluye una +nica sentencia %ue llama a la funcin printf' Esta toma como argumento una cadena de caracteres& %ue se imprimen van encerradas entre dobles comillas " "' El s$mbolo \n indica un cambio de l$nea' Cay un grupo de s$mbolos& %ue son tratados como caracteres individuales& %ue especifican algunos caracteres especiales del cdigo .CII' /os ms importantes son@ \a \b \f \n \r \t \v \\ \' \" \OOO \xHHH

alert backspace formfeed newline carriage return horizontal tab vertical tab backslash single quote double quote visuali*a un carcter cuyo cdigo octal' visuali*a un carcter cuyo cdigo "exadecimal'

.CII es !!! en .CII es CCC en

/as funciones de entrada y salida y los formatos utili*ados los explicaremos con ms detalle en otro cap$tulo' El desarrollo de un programa. ,n programa C puede estar formado por diferentes mdulos o fuentes' Es conveniente mantener los fuentes de un tama)o no muy grande& para %ue la compilacin sea rpida' Tambi9n& al dividirse un programa en partes& puede facilitar la legibilidad del programa y su estructuracin' /os diferentes fuentes son compilados de forma separada& +nicamente los fuentes %ue "an sido modificados desde la +ltima compilacin& y despu9s combinados con las librer$as necesarias para formar el programa en su versin ejecutable' /os comandos necesarios para compilar& linkar y ejecutar un programa dependen del sistema operativo y debemos dirigirnos a los manuales correspondientes para conocer la sintaxis exacta' Como forma ms com+n podemos dar la siguiente@

cc prog cc modulo ! modulo" lin# prog! modulo ! modulo" prog

Creacin de un programa en C' Tipos bsicos y variables. /os tipos de datos bsicos definidos por C son caracteres& n+meros enteros y n+meros en coma flotante' /os caracteres son representados por char& los enteros por short& int&
long y los n+meros en coma flotante por float y double' /os tipos bsicos disponibles y su tama)o son@ char short int unsigned long float double

Carcter Entero corto con signo Entero con signo Entero sin signo Entero largo con signo Flotante simple Flotante doble

Anormalmente < bitsB Anormalmente 3D bitsB Adepende de la implementacinB Adepende de la implementacinB Anormalmente =? bitsB Anormalmente =? bitsB Anormalmente DE bitsB

/a palabra unsigned en realidad es un modificador aplicable a tipos enteros& aun%ue si no se


especifica un tipo se supone int' ,n modificador es una palabra clave de C %ue indica %ue una variable& o funcin& no se comporta de la forma normal' Cay tambi9n un modificador signed& pero como los tipos son por defecto con signo& casi no se utili*a' /as variables son definidas utili*ando un identificador de tipo seguido del nombre de la variable' Feamos el siguiente programa' #include <stdio.h> main() { float cels! farh;

farh $ %&.'; cels $ &.' ( ( farh ) %".' ) * +.'; printf(">>> ,f - son ,f .\n"! farh! cels ); }

En el programa anterior se definen dos variables float& se asigna un valor a la primera y se calcula la segunda mediante una expresin aritm9tica' /as asignaciones en C tambi9n son una expresin& por lo %ue se pueden utili*ar como parte de otra expresin& pero seg+n %ue prcticas de este tipo no son muy recomendables ya %ue reducen la legibilidad del programa' En la instruccin printf& el s$mbolo %f indica %ue se imprime un n+mero en coma flotante' Cay un tipo muy importante %ue se representa por void %ue puede significar dos cosas distintas& seg+n su utili*acin' Puede significar nada& o sea %ue si una funcin devuelve un valor de tipo void no devuelve ning+n resultado& o puede significar cual%uier cosa& como puede ser un puntero a void es un puntero gen9rico a cual%uier tipo de dato' 0s adelante veremos su utili*acin' unciones. ,n programa C est formado por un conjunto de funciones %ue al menos contiene la funcin main' ,na funcin se declara con el nombre de la funcin precedido del tipo de valor %ue retorna y una lista de argumentos encerrados entre par9ntesis' El cuerpo de la funcin est formado por un conjunto de declaraciones y de sentencias comprendidas entre llaves' Feamos un ejemplo de utili*acin de funciones@ #include <stdio.h> #define /0123 #define -0.4 & "'

int fact5i ( int 6 ) { int r $ ! i $ ';

7hile ( i <$ 6 ) { r $ r ( i; i $ i 8 } return r; } ;

int fact5r ( int 6 ) { if ( 6 $$ ' ) return ;

else return 6 ( fact5r(6) ); }

main() { int r! 6alor $ /0123;

if ( (r $ fact5i(6alor)) !$ fact5r(6alor) ) printf(".odificaci9n err9nea!!.\n"); else if ( r $$ -0.4 ) printf(".odificaci9n correcta.\n"); else printf("0lgo falla!!.\n"); }

.e definen dos funciones& fact_i y fact_r& adems de la funcin main' mbas toman como parmetro un valor entero y devuelven otro entero' /a primera calcula el factorial de un n+mero de forma iterativa& mientras %ue la segunda "ace lo mismo de forma recursiva' Todas las l$neas %ue comien*an con el s$mbolo # indican una directiva del precompilador' ntes de reali*ar la compilacin en C se llama a un precompilador cuya misin es procesar el texto y reali*ar ciertas sustituciones textuales' Cemos visto %ue la directiva #include incluye el texto contenido en un fic"ero en el fuente %ue estamos compilando' De forma parecida& #define nombre texto sustituye todas las apariciones de nombre por texto' s$& en el fuente& la palabra F /!1 se sustituye por el n+mero G' El valor %ue debe devolver una funcin se indica con la palabra return' /a evaluacin de la expresin debe dar una valor del mismo tipo de dato %ue el %ue se "a definido como resultado' /a declaracin de una variable puede incluir una iniciali*acin en la misma declaracin' .e debe tener muy en cuenta %ue en C todos los argumentos son pasados Hpor valorH' (o existe el concepto de paso de parmetros Hpor variableH o Hpor referenciaH' Feamos un ejemplo@ int incr ( int 6 ) { return 6 8 } ;

main() { int a! :;

: $ %; a $ incr(:); *( a $ ; mientras <ue : $ %. =o ha cam:iado despu>s de la llamada. (* }

En el ejemplo anterior el valor del parmetro de la funcin incr& aun%ue se modifi%ue dentro de la funcin& no cambia el valor de la variable b de la funcin main' Todo el texto comprendido entre los caracteres /* y */ son comentarios al programa y son ignorados por el compilador' En un fuente C los comentarios no se pueden anidar' E!presiones y operadores. /os distintos operadores permiten formar expresiones tanto aritm9ticas como lgicas' /os operadores aritm9ticos y lgicos son@ +& ++& -*& /& % >>& << & | ^ ~ ! ==& != &&& || <& <= >& >=

suma& resta incremento& decremento multiplicacin& divisin& mdulo rotacin de bits a la derec"a& i*%uierda' (D booleano !1 booleano E-!1 booleano complemento a 3 complemento a ?& (!T lgico igualdad& desigualdad (D& !1 lgico menor& menor o igual mayor& mayor o igual

En estos operadores deben tenerse en cuenta la precedencia de operadores y las reglas de asociatividad& %ue son las normales en la mayor$a de lenguajes' .e debe consultar el manual de referencia para obtener una explicacin de tallada' dems "ay toda una serie de operadores aritm9ticos con asignacin& como pueden ser += y ^='
En la evaluacin de expresiones lgicas& los compiladores normalmente utili*an t9cnicas de evaluacin rpida' Para decidir si una expresin lgica es cierta o falsa muc"as veces no es necesario evaluarla

completamente' Por ejemplo una expresin formada Iexp3J || Iexp?J& el compilador eval+a primero Iexp3J y si es cierta& no eval+a Iexp?J' Por ello se deben evitar construcciones en las %ue se modifi%uen valores de datos en la propia expresin& pues su comportamiento puede depender de la implementacin del compilador o de la optimi*acin utili*ada en una compilacin o en otra' Estos son errores %ue se pueden cometer fcilmente en C ya %ue una asignacin es tambi9n una expresin' Debemos evitar@ if (( ?88 > % ) @@ ( ? < A ))

y escribir en su lugar@ ?88; if (( ? > % ) @@ ( ? < A ))

Cay un tipo especial de expresin en C %ue se denomina expresin condicional y est representada por los operadores ? : ' .u utili*acin es como sigue@ IeJ ? IxJ : IyJ' .e eval+a si e entonces xK si no& y' int maAor ( int a! int : ) { return ( a > : ) B 43CD E -01FD; }

7aste5time () { float a! : $ '.';

( : > '.' ) B sin(G5HI * J) E cos(G5HI * ;); }

Conversin de tipos. Cuando escribimos una expresin aritm9tica aLb& en la cual "ay variables o valores de distintos tipos& el compilador reali*a determinadas conversiones antes de %ue eval+e la expresin' Estas conversiones pueden ser para HaumentarH o HdisminuirH la precisin del tipo al %ue se convierten los elementos de la expresin' ,n ejemplo claro& es la comparacin de una variable de tipo int con una variable de tipo double' En este caso& la de tipo int es convertida a double para poder reali*ar la comparacin' /os tipos pe%ue)os son convertidos de la forma siguiente@ un tipo char se convierte a int& con el modificador signed si los caracteres son con signo& o unsigned si los caracteres son sin signo' ,n unsigned char es convertido a int con los bits ms altos puestos a cero' ,n signed char es convertido a int con los bits ms altos puestos a uno o cero& dependiendo del valor de la variable'

Para los tipos de mayor tama)o@ si un operando es de tipo double& el otro es convertido a double' .i un operando es de tipo float& el otro es convertido a float' .i un operando es de tipo unsigned long& el otro es convertido a unsigned long' .i un operando es de tipo long& el otro es convertido a long' .i un operando es de tipo unsigned& el otro es convertido a unsigned' .i no& los operandos son te tipo int' ,na variable o expresin de un tipo se puede convertir expl$citamente a otro tipo& anteponi9ndole el tipo entre par9ntesis' cam:io5tipo () { float int a; :;

: $

';

a $ '.&;

if ( a <$ (float) : ) menor(); }

Control de "lu#o. /a sentencia de control bsica es if (IeJ) then IsJ else ItJ' En ella se eval+a una expresin condicional y si se cumple& se ejecuta la sentencia sK si no& se ejecuta la sentencia t' /a segunda parte de la condicin& else ItJ& es opcional' int cero ( dou:le a ) { if ( a $$ '.' ) return (43CD); else return (-01FD); }

En el caso %ue IeJ no sea una expresin condicional y sea aritm9tica& se considera falso si vale 6K y si no& verdadero' Cay casos en los %ue se deben evaluar m+ltiples condiciones y +nicamente se debe evaluar una de ellas' .e puede programar con un grupo de sentencias if then else anidadas& aun%ue ello puede ser farragoso y de complicada lectura' Para evitarlo nos puede ayudar la sentencia switch' .u utili*acin es@

s7itch (6alor) { case case ... defaultE } <sentencias> 6alor E <sentencias> 6alor"E <sentencias>

Cuando se encuentra una sentencia case %ue concuerda con el valor del switch se ejecutan las sentencias %ue le siguen y todas las dems a partir de a"$& a no ser %ue se introdu*ca una sentencia break para salir de la sentencia switch' Por ejemplo& 6er5opcion ( char c ) { s7itch(c){ case KaKE case K:KE case KcKE case KdKE defaultE } } printf("2p . o M\n"); printf("2p B\n"); :rea#; printf("2p 0\n"); printf("2p L\n"); :rea#; :rea#;

!tras sentencias de control de flujo son las %ue nos permiten reali*ar iteraciones sobre un conjunto de sentencias' En C tenemos tres formas principales de reali*ar iteraciones' /a sentencia while (IeJ) IsJ es seguramente la ms utili*ada' /a sentencia& o grupo de sentencias IsJ se ejecuta mientras la evaluacin de la expresin IeJ sea verdadera' long raiN ( long 6alor ) { long r $ ;

7hile ( r ( r <$ 6alor ) r88;

return r; }

!tra sentencia iterativa& %ue permite iniciali*ar los controles del bucle se la sentencia for ( IiJ; IeJ; IpJ ) IsJ' /a sentencia for se puede escribir tambi9n como@ <i>; 7hile ( <e> ) { <s>; <p>; }

El ejemplo anterior se podr$a escribir como@ long raiN ( long 6alor ) { long r;

for ( r $ ;

; r ( r <$ 6alor; r88 )

return r; }

,na variacin de la sentencia while es@ do IsJ while ( IeJ ); En ella la sentencia se ejecuta al menos una ve*& antes de %ue se eval+e la expresin condicional' !tras sentencias interesantes& aun%ue menos utili*adas son break y continue' break provoca %ue se termine la ejecucin de una iteracin o para salir de la sentencia switch& como ya "emos visto' En cambio& continue provoca %ue se comience una nueva iteracin& evalundose la expresin de control' Feamos dos ejemplos@ final5countdo7n () { int count $ ';

7hile ( count)) >

) {

if ( count $$ ; ) start5engines(); if ( status() $$ O03=I=P ) :rea#; printf(",d "! count ); } if ( count $$ ' ) { launch(); printf("Fhuttle launched\n"); } else { printf("O03=I=P condition recei6ed.\n"); printf(".ount held at 4 ) ,d\n"! count ); } }

d" () { int f;

for ( f $

; f <$ &'; f88 ) {

if ( f , " $$ ' ) continue; printf(",d"! f ); } }

$e"inicin y prototipos de "unciones. /os programas sencillos& como los ejemplo planteados "asta a"ora& normalmente no necesitan un nivel de estructuracin elevado' Pero cuando 9stos crecen un poco necesitamos estructurarlos adecuadamente para mantenerlos legibles& facilitar su mantenimiento y para poder reutili*ar ciertas porciones de cdigo' El mecanismo C %ue nos permite esto son las funciones' Con los compiladores& los fabricantes nos proporcionan un conjunto importante de funciones de librer$a' veces& nos puede interesar construir nuestras propias librer$as' Ma "emos utili*ado funciones& pero veamos cmo debemos definirlas'

/os prototipos de funciones son una caracter$stica clave de la recomendacin es una declaracin %ue toma la forma@ tipo_resultado nombre_funcin ( tipo_parmetro nombre_parmetro ''' ); %u$ tenemos varios ejemplos@ int fact5i ( int 6 ); int maAor ( int a! int : ); int cero ( dou:le a ); long raiN ( long 6alor ); 6oid final5countdo7n ( 6oid ); int main ( int argc! char ((arg6 );

(.I del C' ,n prototipo

!bservando el prototipo de una funcin podemos decir exactamente %ue tipo de parmetros necesita y %ue resultado devuelve' .i una funcin tiene como argumento void& %uiere decir %ue no tiene argumentos& al igual %ue si el resultado es void& no devuelve ning+n valor' En la vieja definicin de 2ernig"an y 1itc"ie el tipo %ue devolv$a una funcin se declaraba +nicamente si era distinto de int' .imilarmente& los parmetros eran declarados en el cuerpo de la funcin& en lugar de utili*ar la lista de parmetros' Por ejemplo@ maAor ( a! : ) int a; int :; { ... }

/as funciones al viejo estilo se compilan correctamente en muc"os compiladores actuales' Por contra& proporcionan menos informacin sobre sus parmetros y errores %ue afecten al tipo de parmetros de llamada a las funciones no pueden ser detectados automticamente' Por tanto& la declaracin de una funcin debe escribirse igual %ue su prototipo pero sin el punto y coma final' El cuerpo de la funcin le sigue encerrado entre llaves' En un programa %ue est9 formado por distintas partes bien diferenciadas es conveniente utili*ar m+ltiples fic"eros fuente' Cada fuente agrupa las funciones semejantes& como por ejemplo en un compilador podr$amos tener un fuente para el anlisis l9xico& otro para el sintctico y otro para la generacin de cdigo' Pero en un fuente necesitaremos funciones %ue se "an definido en otro' Para ello& escribiremos un fic"ero de cabecera AheaderB& %ue contendr las declaraciones %ue podemos necesitar en otros fuente' s$& en el fuente %ue implementa el anali*ador sintctico pondremos una l$nea #include "lexic.h"' De esta forma al compilar el mdulo sintctico tendremos todos los prototipos de las funciones del l9xico y el compilador podr detectar malas utili*aciones de las funciones all$ definidas' Construccin de tipos.

/os datos del mundo real& normalmente no estn formados por variables escalares de tipos los tipos bsicos' Por ejemplo& nos puede interesar cuntos mdulos en C "emos escrito cada semana& a lo largo del a)o' ! tambi9n nos interesa tener los datos de cada planeta del .istema .olar& masa& posicin& velocidad y aceleracin& para un programa de simulacin de la ley de gravitacin de (e8ton' Para resolver el primer caso& C nos permite declarar una variable %ue sea de tipo vector' Para el segundo& podemos definir un registro para cada elemento' ,n vector es una porcin de memoria %ue es utili*ada para almacenar un grupo de elementos del mismo tipo ,n vector se declara@ tipo nombre [tama o];' Por ejemplo& int modulo[52];' %u$ HmoduloH es un vector de G? elementos enteros' main() { int f! moduloQ&"R;

for ( f $ '; f < &"; f88 ) moduloQfR $ '; ... }

Cada elemento de un vector es accedido mediante un n+mero de $ndice y se comporta como una variable del tipo base del vector' /os elementos de un vector son accedidos por $ndices %ue van desde 6 "asta (73 para un vector de ( elementos' /os elementos de un vector pueden ser iniciali*ados en la misma declaracin@ char 6ocalQ&R $ { KaK! KeK! KiK! KoK! KuK }; float n5LodeQ&R $ { '.;! '.S! ! .T! ".J };

Tambi9n podemos definir vectores multidimensionales' C no impone ninguna limitacin al n+mero de dimensiones de un vector' Existe& en cambio& la limitacin del tama)o de memoria %ue podamos utili*ar en nuestro ordenador' Por ejemplo& para la declaracin de un vector multidimensional podemos escribir@ int 6ideoQ"&RQJ'RQ"R;

El tama)o de la variable video es proporcional al tama)o del tipo int y al tama)o de cada dimensin' Existe un operador C %ue nos permite obtener el tama)o de un tipo o de una variable' Este es sizeof() y nos proporciona el tama)o en bytes' if ( siNeof(6ideo) $$ J' ( "& ( " ( siNeof(int) ) printf("2U!\n"); else printf("0lgo no funciona.\n");

,n tipo vector muy utili*ado es la cadena de caracteres A stringB' .i %ueremos asignar espacio para un string podemos "acer@ char nom:reQT'R! direccionQJ'R;

Es un vector C pero con la particularidad %ue de el propio lenguaje utili*a un carcter especial como marca de final de string' s$ en un vector de caracteres de tama)o ( podremos almacenar una cadena de (73 caracteres& cuyo +ltimo carcter estar en la posicin (7? y la marca de final de string en la (73' Feamos un ejemplo@ char ser6eiQTR $ "F.I";

/a posicin 6 contiene el carcter H.HK la 3 el HCHK la ? el HIHK la = el HN6H& marca de final de string y el resto de componentes no estn definidas' En la iniciali*acin de strings no se debe indicar el finalK ya lo "ace el compilador' Para la manipulacin de cadenas de caracteres (.I proporciona el fic"ero string.h %ue contiene las declaraciones de un conjunto de funciones proporcionadas con la librer$a del compilador' ,n registro agrupa distintos tipos de datos en una misma estructura' /os registros son definidos de la forma@ struct nombre { lista de declaraciones };

/os campos de cada registro pueden ser tipos bsicos u otros registros' Por ejemplo@ struct planeta { struct co dou:le char }; masa; nomQ 'R; r! 6! a;

struct co { dou:le ?!A!N; };

/os campos de cada registro son accesibles mediante el nombre del registro seguido de punto y el nombre del campo& como por ejemplo venus.r.x = 1.0;' Cada campo se comporta como lo "ace su tipo bsico' C no proporciona mecanismos de iniciali*acin ni copia de registros& por lo %ue debe ser el programador el %ue los implemente' veces los datos se ajustan a series ordenadas en las cuales un elemento sigue& o precede& a otro' ,n caso t$pico son los d$as de la semana' .i se desea reali*ar iteraciones con los d$as de la semana una forma es& por ejemplo& asignar un n+mero a cada d$a con #define' C proporciona un mecanismo compacto para reali*ar estoK son las enumeraciones' ,na enumeracin toma la forma@ enum nombre { lista de elementos };' Feamos un ejemplo@ 6oid planning ( 6oid )

{ enum diasemana { lunes! martes! miercoles! Vue6es! 6iernes! sa:ado! domingo }; int dia;

for ( dia $ lunes; dia <$ 6iernes; dia88 ) tra:aVar(dia); if ( dia $$ sa:ado ) salir(); }

cada elemento de la enumeracin se le asigna un valor consecutivo& comen*ando por 6' .i se desea %ue el valor asignado sea distinto se puede "acer de la siguiente forma@ enum puntos { t5T5"& $ %! t5Nona $ "! t5li:re $ };

0uc"as veces es conveniente renombrar tipos de datos para %ue la escritura del programa se nos "aga ms sencilla y la lectura tambi9n' Esto se puede conseguir con la palabra typedef' Con ella damos un nombre a cierto tipo& o combinacin de ellos' tApedef struct planeta H10=D40;

H10=D40 mercurio! 6enus! tierra! marte;

l igual %ue podemos iniciali*ar las variables de tipos bsicos en la misma declaracin& tambi9n lo podemos "acer con los registros' /os valores de cada campo de un registro van separados por comas y encerrados entre llaves' H10=D40 mercurio $ { { '.%&'! '! ' }! { '! '! ' }! { '! '! ' }! ''! "Gercurio" };

Ambito de "unciones y variables. El mbito& o visibilidad& de una variable nos indica en %ue lugares del programa est activa esa variable' Casta a"ora& en los ejemplos %ue "emos visto& se "an utili*ado variables definidas en el cuerpo de funciones' Estas variables se crean en la memoria del ordenador cuando se llama a la funcin y se destruyen cuando se sale' Es necesario a veces& %ue una variable tenga un valor %ue pueda ser accesible desde todas las funciones de un mismo fuente& e incluso desde otros fuentes'

En C& el mbito de las variables depende de dnde "an sido declaradas y si se les "a aplicado alg+n modificador' ,na variable definida en una funcin es& por defecto& una variable local' Esto es& %ue slo existe y puede ser accedida dentro de la funcin' Para %ue una variable sea visible desde una funcin cual%uiera del mismo fuente debe declararse fuera de cual%uier funcin' Esta variable slo ser visible en las funciones definidas despu9s de su declaracin' Por esto& el lugar ms com+n para definir las variables globales es antes de la definicin de ninguna funcin' Por defecto& una variable global es visible desde otro fuente' Para definir %ue existe una variable global %ue est definida en otro fuente tenemos %ue anteponer la palabra extern a su declaracin' Esta declaracin +nicamente indica al compilador %ue se "ar referencia a una variable externa al mdulo %ue se compila' /as variables locales llevan impl$cito el modificador auto' Esto es %ue se crean al inicio de la ejecucin de la funcin y se destruyen al final' En un programa ser$a muy ineficiente en t9rminos de almacenamiento %ue se crearan todas las variables al inicio de la ejecucin' Por contra& en algunos casos es deseable' Esto se consigue anteponiendo el modificador static a una variable local' .i una funcin necesita una variable %ue +nicamente sea accedida por la misma funcin y %ue conserve su valor a trav9s de sucesivas llamadas& es el caso adecuado para %ue sea declarada local a la funcin con el modificador static' El modificador static se puede aplicar tambi9n a variables globales' ,na variable global es por defecto accesible desde cual%uier fuente del programa' .i& por cual%uier motivo& se desea %ue una de estas variables no se visible desde otro fuente se le debe aplicar el modificador static' /o mismo ocurre con las funciones' /as funciones definidas en un fuente son utili*ables desde cual%uier otro' En este caso conviene incluir los prototipos de las funciones del otro fuente' .i no se desea %ue alguna funcin pueda ser llamada desde fuera del fuente en la %ue est definida se le debe anteponer el modificador static' 6oid contar ( 6oid ) { static long cuenta $ ';

cuenta88; printf("1lamada ,ld 6eces\n"! cuenta ); }

!tro modificador muy importante es const' Con 9l se pueden definir variables cuyo valor debe permanecer constante durante toda la ejecucin del programa' Tambi9n se puede utili*ar con argumentos de funciones' En esta caso se indica %ue el argumento en cuestin es un parmetro y su valor no debe ser modificado' En el caso %ue por error modifi%uemos ese parmetro& el compilador nos indicar el error' #define DC1D3 const dou:le ".S J"J pi $ %. ; &+;

dou:le lcercle ( const dou:le r ) { return " ( pi ( r; }

dou:le DWH ( const dou:le ? ) { return po7 ( DC1D3! ? ); }

dou:le sinh ( const dou:le ? ) { return (e?p(?) ) e?p()?)) * "; }

Debemos fijarnos %ue en el ejemplo anterior pi es una variable& la cual no podemos modificar' Por ello pi slo puede aparecer en un +nico fuente' .i la definimos en varios& al linOar el programa se nos generar un error por tener una variable duplicada' !tro modificador utili*ado algunas veces es el register' Este modificador es aplicable +nicamente a variables locales e indica al compilador %ue esta debe ser almacenada permanentemente en un registro del procesador del ordenador' Este modificador es "erencia de los viejos tiempos& cuando las tecnolog$as de optimi*acin de cdigo no estaban muy desarrolladas y se deb$a decir %u9 variable era muy utili*ada en la funcin' Coy en d$a casi todos los compiladores reali*an un estudio de %u9 variables locales son las ms adecuadas para ser almacenadas en registros& y las asignan automticamente' Con los compiladores modernos se puede dar el caso de %ue una declaracin register inadecuada disminuya la velocidad de ejecucin de la funcin& en lugar de aumentarla' Por ello& "oy en d$a& la utili*acin de este modificador est en desuso& "asta el punto de %ue algunos compiladores lo ignoran' .e debe tener en cuenta %ue de una variable declarada como register no se puede obtener su direccin& ya %ue est almacenada en un registro y no en memoria' Punteros. Cada variable de un programa tiene una direccin en la memoria del ordenador' Esta direccin indica la posicin del primer byte %ue la variable ocupa' En el caso de una estructura es la suma del tama)o de cada uno de sus campos' Como en cual%uier caso las variables son almacenadas ordenadamente y de una forma predecible& es posible acceder a estas y manipularlas mediante otra variables %ue contenga su direccin' este tipo de variables se les denomina punteros' /os punteros C son el tipo ms potente y seguramente la otra clave del 9xito del lenguaje' /a primera ventaja %ue obtenemos de los punteros es la posibilidad %ue nos dan de poder tratar con datos de un tama)o arbitrario sin tener %ue moverlos por la memoria' Esto puede a"orrar un tiempo de computacin muy importante en algunos tipos de aplicaciones' Tambi9n permiten %ue una funcin reciba y cambie el valor de una variable' 1ecordemos %ue todas las funciones C +nicamente aceptan parmetros por valor' 0ediante un puntero a una variable podemos modificarla indirectamente desde una funcin cual%uiera' ,n puntero se declara de la forma@ tipo *nombre; float (pf;

H10=D40 (pp; char (pc;

Para manipular un puntero& como variable %ue es& se utili*a su nombreK pero para acceder a la variable a la %ue apunta se le debe preceder de *' este proceso se le llama indireccin' ccedemos indirectamente a una variable' Para trabajar con punteros existe un operador& && %ue indica Hdireccin deH' Con 9l se puede asignar a un puntero la direccin de una variable& o pasar como parmetro a una funcin' 6oid pro6a5punter ( 6oid ) { long long edat; (p;

p $ Xedat; edad $ &'; printf("1a edat es ,ld\n"! edat ); (p $ (p * "; printf("1a edat es ,ld\n"! edat ); }

6oid imprimir5string ( char stringQR ) { char (p;

for ( p $ string; (p !$ K\'K; p88 ) imprimir5char((p); }

/os punteros tambi9n se pueden utili*ar con los registros' Para ello se utili*a la notacin -> en lugar del punto %ue utili*bamos anteriormente' .i p es un puntero a PLANETA& y %ueremos conocer su masa& debemos escribir p->masa' ,n puntero se puede utili*ar para almacenar la direccin de cual%uier tipo de datos& tanto simple como un vector& como un registro' De cmo lo definimos y lo utili*amos depende su comportamiento' /as componentes de un vector& por ejemplo pueden ser referenciadas por un puntero al tipo de cada componente' Feamos un ejemplo@ #define =5H10 +

static H10=D40 FFolarQ=5H10R;

6oid init5FistemaFolar ( 6oid )

{ H10=D40 (p;

for ( p $ FFolar; p < FFolarQ=5H10R; p88 ) init5planeta(p); }

6oid init5planeta ( H10=D40 (p ) { p)>masa $ '; p)>nom $ ""; init5co(X(p)>r)); init5co(X(p)>6)); init5co(X(p)>a)); }

6oid init5co ( struct co (c ) { c)>? $ c)>A $ c)>N $ '; }

Definimos un vector de N_PLA componentes de tipo PLANETA' Este tipo est formado por un registro' Femos %ue en la funcin de iniciali*acin del vector el puntero a la primera componente se iniciali*a con el nombre del vector' Esto es una caracter$stica importante de C' /a direccin de la primera componente de un vector se puede direccionar con el nombre del vector' Esto es debido a %ue en la memoria del ordenador& los distintos elementos estn ordenados de forma ascendente' s$& SSolar se puede utili*ar como &SSolar[0]' cada iteracin llamamos a una funcin %ue nos iniciali*ar los datos de cada planeta' esta funcin le pasamos como argumento el puntero a la componente en curso para %ue& utili*ando la notacin ->& pueda asignar los valores adecuados a cada campo del registro' Debemos fijarnos en el incremento del puntero de control de la iteracin& p++' Con los punteros se pueden reali*ar determinadas operaciones aritm9ticas aun%ue& a parte del incremento y decremento& no son muy frecuentes' Cuando incrementamos un puntero el compilador le suma la cantidad necesaria para %ue apunte al siguiente elemento de la memoria' Debemos fijarnos %ue esto es aplicable slo siempre %ue "aya distintas variables o elementos situados consecutivamente en la memoria& como ocurre con los vectores' De forma similar se pueden utili*ar funciones %ue tengan como parmetros punteros& para cambiar el valor de una variable' Feamos@

6oid intercam:io ( 6oid ) { int a! :;

a $

: $ "; s7ap( Xa! X: ); printf(" a $ ,d : $ ,d\n"! a! : ); }

6oid s7ap ( int (?! int (A ) { int tmp;

tmp $ (?; (? $ (A; (A $ tmp; }

/a sintaxis de C puede& a veces& provocar confusin' .e debe distinguir lo %ue es un prototipo de una funcin de lo %ue es una declaracin de una variable' s$ mismo& un puntero a un vector de punteros& etc''' int f (); int (p ; int (f"(); int ((pf)(int); int ((pf")(int (pi); int aQ%R; int (apQ%R; int ((apQ%R); funci9n <ue de6uel6e un entero puntero a entero funci9n <ue de6uel6e un puntero a entero puntero a funci9n <ue toma A de6uel6e un entero puntero a funci9n <ue toma un puntero a entero A de6uel6e un entero 6ector de tres enteros 6ector de tres punteros a entero 6ector de tres punteros a entero

int ((pa)Q%R; int ((apfQ&R)(int (pi);

puntero a 6ector de tres enteros 6ector de & punteros a funci9n <ue toman un puntero a entero A de6uel6en un entero

En los programas %ue se escriban se debe intentar evitar declaraciones complejas %ue dificulten la legibilidad del programa' ,na forma de conseguirlo es utili*ando typedef
para redefinirPrenombrar tipos' tApedef int (intptr; tApedef intptr ((fptr) ( intptr ); fptr f ! f";

El preprocesador. El preprocesador es una parte del compilador %ue se ejecuta en primer lugar& cuando se compila un fuente C y %ue reali*a unas determinadas operaciones& independientes del propio lenguaje C' Estas operaciones se reali*an a nivel l9xico y son la inclusin de otros textos en un punto del fuente& reali*ar sustituciones o eliminar ciertas partes del fuente' Debemos tener en cuenta %ue el preprocesador trabaja +nicamente con el texto del fuente y no tiene en cuenta ning+n aspecto sintctico ni semntico del lenguaje' El control del preprocesador se reali*a mediante determinadas directivas incluidas en el fuente' ,na directiva es una palabra %ue interpreta el preprocesador& %ue siempre va precedida por el s$mbolo # y %ue est situada a principio de l$nea' /a directiva #define se utili*a para definir una macro' /as macros proporcionan principalmente un mecanismo para la sustitucin l9xica' ,na macro se define de la forma #define id secuencia' Cada ocurrencia de id en el fuente es sustituida por secuencia' Puede definirse una macro sin una secuencia de caracteres' ,na macro se puede QindefinirR mediante la directiva #undef' #define GFP' #define GFP'" "F.I)I)F4034E Ftarting sAstem #ernel\n" "F.I)I)F42HE Ftopping sAstem #ernel\n"

6oid print5msg ( 6oid ) { if ( chec#5state() $$ F4034 ) printf(GFP' ); else printf(GFP'"); }

El estado de una macro& si est definida o no& se puede comprobar mediante las directivas #ifdef y #ifndef' Estas dos directivas se deben completar con una #endif y& el texto comprendido entre

ambas es procesado si la macro est definida' Todas las directivas deben ser completadas en el mismo fuente y pueden ser anidadas' #ifndef G5HI #define G5HI %. ; &+"S #endif

El preprocesador nos permite tambi9n incluir tambi9n otros fic"eros en un fuente C' Esto se consigue con la directiva #include' Esta puede tomar tres formas@ #include <fichero>& #include "fichero" y #include macro' /a diferencia entre la primera y la segunda est en el lugar dnde se buscar el fic"ero en cuestin' (ormalmente se utili*a la primera para fic"eros proporcionados por la librer$a del compilador& y la segunda& para fic"eros creados por el programador' unciones de entrada y salida por pantalla. En este apartado y los siguientes vamos a ver algunas de las funciones ms importantes %ue nos proporcionan las librer$as definidas por (.I y su utili*acin' Como "emos visto "asta a"ora& el lenguaje C no proporciona ning+n mecanismo de comunicacin ni con el usuario ni con el sistema operativo' Ello es reali*ado a trav9s de las librer$as' El fic"ero de declaraciones %ue normalmente ms se utili*a es el stdio.h' Famos a ver algunas funciones definidas en 9l' ,na funcin %ue ya "emos utili*ado y %ue& ella y sus variantes& es la ms utili*adas para la salida de informacin es printf' Esta permite formatear en enviar datos a la salida estndar del sistema operativo' #include <stdio.h> int printf ( const char (format Q! argumentos! ...R );

cepta un string de formato y cual%uier n+mero de argumentos' Estos argumentos se aplican a cada uno de los especificadores de formato contenidos en format' ,n especificador de formato toma la forma S :flags;:width;:'prec;:"Tl; type' El tipo puede ser@ d& i o u x X f e g E G c s % p

entero decimal con signo entero octal sin signo entero decimal sin signo entero "exadecimal sin signo Aen min+sculasB entero "exadecimal sin signo Aen may+sculasB coma flotante en la forma :7;dddd'dddd coma flotante en la forma :7;d'dddd e:LP7;ddd coma flotante seg+n el valor como e pero en may+sculas como g pero en may+sculas un carcter cadena de caracteres terminada en '\0' imprime el carcter S puntero

/os flags pueden ser los caracteres@


+ -

blank
#

siempre se imprime el signo& tanto L como 7 justifica a la i*%uierda el resultado& a)adiendo espacios al final si es positivo& imprime un espacio en lugar de un signo L especifica la forma alternativa

En el campo width se especifica la anc"ura m$nima de la forma@


n 0n *

se imprimen al menos n caracteres' se imprimen al menos n caracteres y si la salida es menor& se anteponen ceros la lista de parmetros proporciona el valor

Cay dos modificadores de tama)o& para los tipos enteros@


l h

imprime un entero long imprime un entero short

!tra funcin similar a printf pero para la entrada de datos es scanf' Esta toma los datos de la
entrada estndar del sistema operativo' En este caso& la lista de argumentos debe estar formada por punteros& %ue indican dnde depositar los valores' #include <stdio.h> int scanf ( const char (format Q! argumentos! ...R );

Cay dos funciones %ue trabajan con strings' /a primera lee un string de la entrada estndar y la segunda lo imprime en el dispositivo de salida estndar' #include <stdio.h> char (gets ( char (s ); int puts ( char (s );

Tambi9n "ay funciones de lectura y escritura de caracteres individuales' #include <stdio.h> int getchar ( 6oid ); int putchar ( int c );

Feamos& por ejemplo& un programa %ue copia la entrada estndar a la salida' #include <stdio.h>

main() { int c;

7hile ( (c $ getchar()) !$ D2- ) putchar(c); }

unciones de asignacin de memoria. Cemos visto %ue en C& las variables estticas pueden estar creadas al inicio de la ejecucin del programa& o bien son variables locales automticas %ue se crean al iniciarse la ejecucin de una funcin' En muc"as aplicaciones en necesario la utili*acin de estructuras de datos dinmicas' Para asignar memoria dinmica C utili*a varias funciones definidas en stdlib.h' Feamos la utili*acin de estas funciones' /a funcin de este tipo ms utili*ada es malloc' Esta toma como parmetro un tama)o en bytes y devuelve un puntero al blo%ue de memoria asignado' .i no "ay memoria suficiente para asignar el blo%ue devuelve NULL' #include <stdli:.h> 6oid (malloc ( siNe5t siNe );

El tipo size_t est definido normalmente como unsigned y se utili*a en todas las funciones %ue necesitan un tama)o en bytes' !tra funcin similar es@ #include <stdli:.h> 6oid (calloc ( siNe5t nitems! siNe5t siNe );

En este caso se le pasa como parmetro el n+mero de elementos consecutivos %ue se desean' diferencia de malloc& calloc iniciali*a el contenido de la memoria asignada a 6' /a funcin %ue se utili*a para devolver memoria dinmica previamente asignada es free' Esta toma como parmetro un puntero previamente obtenido con malloc o calloc #include <stdli:.h> 6oid free ( 6oid (:loc# );

Cay %ue tener en cuenta& %ue la funciUn free no cambia el valor del parVmetro' El puntero al cual se "abWa asignado memoria y a"ora se "a liberado sigue almacenando la direcciUn de memoria& pero esta ya no existe despuXs de llamar a free' Es misiUn del programador actuali*ar el valor del puntero& si es necesario' Como ejemplo mostraremos una funcin %ue asigna memoria para un vector& lo iniciali*a y lo libera' 6oid alloc5arraA ( 6oid ) {

int

(6! f;

if ((6 $ (int () calloc (

'! siNeof(int) )) $$ =C11)

printf("=o haA memoria\n"); else { for ( f $ '; f < 6QfR $ '; '; f88 )

free(6); 6 $ =C11; } }

Debemos observar la conversin de tipo reali*ada al valor %ue devuelve calloc' Todas las funciones devuelven punteros a void& por lo %ue se deben convertir al tipo de nuestra variable' unciones matemticas. /a utili*acin de las funciones matemticas definidas en el (.I C re%uieren la inclusin del fic"ero math.h' Todas ellas trabajan con el tipo double& por lo %ue si los argumentos o resultados son del tipo float el propio compilador se encarga de convertirlos al formato adecuado' En (.I se est trabajando para proporcionar funciones con argumentos de tipo float e introducir el tipo long float' Casi todas la funciones tienen la forma double nombre ( double x );'

atan2 exp acos asin atan cos cosh sin sinh tan tanh log log10 pow sqrt

toma dos argumentos x e y y devuelve la arcotangente de yPx en radianes' devuelve el valor e elevado a x' retorna el arco coseno del parmetro x' retorna el arco seno del parmetro x' retorna el valor de la arco tangente del parmetro x' retorna el coseno del ngulo x' retorna el coseno "iperblico del parmetro x' retorna el seno del ngulo x' retorna el seno "iperblico del parmetro x' retorna la tangente del ngulo x' retorna la tangente "iperblica del parmetro x' retorna el logaritmo natural del parmetro x' retorna el logaritmo en base 36 del parmetro x' toma dos parmetros x e y y devuelve el valor xy retorna la rai* cuadrada del parmetro x'

%peraciones con "ic&eros. /a entrada y salida a fic"eros es uno de los aspectos ms delicados de cual%uier lenguaje de programacin& pues suelen estar estrec"amente integradas con el sistema operativo' /os servicios ofrecidos por los sistemas operativos var$an enormemente de un sistema a otro' /as librer$as del C proporcionan un gran conjunto de funciones& muc"as de ellas descritas en el libro de 2ernig"an y 1itc"ie y otras derivadas de los servicios %ue ofrece el ,nix' En C "ay dos tipos de funciones de entradaPsalida a fic"eros' /as primeras son derivadas del .! ,nix y trabajan sin buffer' /as segundas son las %ue fueron estandari*adas por (.I y utili*an un buffer intermedio' dems& "acen distinciones si trabajan con fic"eros binarios o de texto' Feremos las segundas& %ue son las ms utili*adas' /as funciones del C no "acen distincin si trabajan con un terminal& cinta o fic"eros situados en un disco' Todas las operaciones se reali*an a trav9s de streams' ,n stream est formado por una serie ordenada de bytes' /eer o escribir de un fic"ero implica leer o escribir del stream' Para reali*ar operaciones se debe asociar un stream con un fic"ero& mediante la declaracin de un puntero a una estructura FILE' En esta estructura se
almacena toda la informacin para interactuar con el .!' Este puntero es iniciali*ado mediante la llamada a la funcin fopen()& para abrir un fic"ero' Cuando se ejecuta todo programa desarrollado en C "ay tres streams abiertos automticamente' Estos son stdin& stdout y stderr' (ormalmente estos streams trabajan con el terminal& aun%ue el sistema operativo permite redireccionarlos' /as funciones printf() y scanf() %ue "emos visto& utili*an stdout y stdin respectivamente' /os datos de los fic"eros pueden ser accedidos en uno de los dos formatos@ texto o binario' ,n text stream consiste en una serie de lineas de texto acabadas con un carcter newline' En modo binario un fic"ero es una coleccin de bytes sin ninguna estructura especial' 1especto a la velocidad de la memoria y de la CP,& los dispositivos de entrada y salida con muy lentos' Puede "aber tres& cuatro y "asta cinco rdenes de magnitud entre la velocidad de la CP, y la de un disco duro' dems una operacin de entrada y salida puede consumir una cantidad importante de recursos del sistema' Por ello& conviene reducir en n+mero de lecturas y escrituras a disco' /a mejor forma de reali*ar esto es mediante un buffer' ,n buffer es una rea de memoria en la cual los datos son almacenados temporalmente& antes de ser enviados a su destino' Por ejemplo& las operaciones de escritura de caracteres a un fic"ero se reali*an sobre el buffer del stream' ,nicamente cuando se llena el buffer se escriben todos los caracteres sobre el disco de una ve*' Esto a"orra un buen n+mero de operaciones sobre el disco' /as funciones del C nos permiten modificar el tama)o y comportamiento del buffer de un stream' Para utili*ar las funciones de fic"eros se debe incluir el fic"ero stdio.h' Este define los prototipos de todas las funciones& la declaracin de la estructura FILE y algunas macros' ,na macro importante es EOF& %ue es el valor devuelto por muc"as funciones cuando se llega al final de fic"ero' /os pasos a seguir para operar con un fic"ero son@ abrir& reali*ar el tratamiento y cerrar' Para abrir un fic"ero se utili*a la funcin fopen' Esta toma dos strings como parmetros' El primero indica el nombre del fic"ero %ue deseamos abrir y el segundo indica el modo de acceso' #include <stdio.h> -I1D (fopen ( const char (filename! const char (mode );

/os modos de acceso para streams de texto son los siguientes@ "r" "w" "a" "r+" "w+" "a+"

bre un fic"ero %ue ya existe para lectura' /a lectura se reali*a al inicio del fic"ero' .e crea un nuevo fic"ero para escribir' .i el fic"ero existe se iniciali*a y sobreescribe' bre un fic"ero %ue ya existe para a)adir informacin por el final' .lo se puede escribir a partir del final' bre un fic"ero %ue ya existe para actuali*arlo Atanto para lectura como para escrituraB' Crea un nuevo fic"ero para actuali*arlo Alectura y escrituraB si existe& lo sobreescribe' bre un fic"ero para a)adir informacin al final' .i no existe lo crea'

.i se desea especificar un fic"ero binario& se a)ade una b al modo@ "wb+"' .i el fic"ero se


abre correctamente& la funcin devuelve un puntero a una estructura FILE' .i no& devuelve NULL' /a funcin fprintf se comporta exactamente a printf& excepto en %ue toma una argumento ms %ue indica el stream por el %ue se debe reali*ar la salida' De "ec"o& la llamada printf("x") es e%uivalente a fprintf ( stdout, "x")' -I1D (f;

if ((f $ fopen( "login.com"! "r" )) $$ =C11 ) printf("D3323E no puedo a:rir el fichero\n");

Para cerrar un fic"ero se utili*a la funcin fclose' Esta toma como argumento el puntero %ue nos proporcion la funcin fopen' #include <stdio.h> int fclose ( -I1D (stream );

Devuelve 6 si el fic"ero se cierra correctamente& EOF si se produce alg+n error' ,na ve* conocemos como abrir y cerrar fic"eros& vamos a ver cmo leer y escribir en ellos' Cay funciones para trabajar con caracteres& lineas y blo%ues' /as funciones %ue trabajan con caracteres son fgetc y fputc' /a primera lee un carcter de un stream y la segunda lo estribe' #include <stdio.h> int fgetc ( -I1D (stream ); int fputc ( int c! -I1D (stream );

/a primera lee el siguiente carcter del stream y los devuelve convertido a entero sin signo' .i no "ay carcter& devuelve EOF' /a segunda& fputc& devuelve el propio carcter si no "ay error' .i lo "ay&

devuelve el carcter EOF' Cay una tercera funcin& feof %ue devuelve cero si no se "a llegado al final del stream' Feamos un ejemplo de cmo se copia un fic"ero carcter a carcter' 7hile ( !feof(infile)) fputc ( fgetc ( infile )! outfile );

.uponemos %ue infile y outfile son los streams asociados al fic"ero de entrada y al de salida& %ue estn abiertos y luego los cerramos para completar los cambios reali*ados' !tras funciones nos permiten reali*ar operaciones con fic"eros de texto trabajando l$nea a l$nea' #include <stdio.h> char (fgets ( char (s! int n! -I1D (stream ); int fputs ( const char (s! -I1D (stream );

/a funcin fgets lee caracteres del stream "asta %ue encuentra un final de l$nea o se lee el carcter n73' 0antiene el carcter \n en el string y a)ade el carcter \0' Devuelve la direccin del string o (,// si se produce alg+n error' /a funcin fputs copia el string al stream& no a)ade ni elimina caracteres \n y no copia la marca de final de string \0' Cay dos funciones %ue nos permiten trabajan en blo%ues' Podemos considerar un blo%ue como un array' Debemos especificar el tama)o de cada elemento y el n+mero de elementos' #include <stdio.h> siNe5t fread ( 6oid (p! siNe5t s! siNe5t n! -I1D (f ); siNe5t f7rite ( 6oid (p! siNe5t s! siNe5t n! -I1D (f );

las anteriores funciones se les pasa un puntero gen9rico p con la direccin del rea de datos %ue se desea leer o escribir& el tama)o de cada elemento s& y el n+mero de elementos n& adems del stream' mbas devuelven el n+mero de elementos le$dos o escritos& %ue debe ser el mismo %ue le "emos indicado& en el caso en %ue no se "aya producido ning+n error' Casta a"ora "emos visto funciones de tratamiento de fic"eros %ue nos van bien para reali*ar un tratamiento secuencial de 9stos' Debemos tener en cuenta %ue cuando debemos reali*ar operaciones de entrada y de salida alternadas& se deben vaciar los buffers de los streams para %ue las operaciones se realicen correctamente sobre los fic"eros' Esto se consigue con las funciones fflush y flushall' /a primera es aplicable al stream %ue deseemos y la segunda vac$a los buffers de todos los streams abiertos' #include <stdio.h> int fflush ( -I1D (stream ); int flushall ( 6oid );

.i deseamos "acer un acceso aleatorio a un fic"ero disponemos de las funciones fseek y ftell' /a primera mueve el cursor& indicador de posicin& a un lugar determinado dentro del fic"ero' Este lugar viene determinado por whence' Este puede ser SEEK_SET& si es desde el inicio del fic"eroK SEEK_CUR

si es desde la posicin actual y SEEK_END si es desde el final del fic"ero' Devuelve 6 si la operacin se reali*a correctamente' #include <stdio.h> int fsee# ( -I1D (stream! long offset! int 7hence ); long ftell ( -I1D (stream );

/a segunda funcin devuelve la posicin del cursor dentro del fic"ero' Este valor indica el n+mero de bytes desde el inicio del fic"ero& si el fic"ero es binario' int escri:ir5planetas ( char (nom:re ) { H10=D40 (p; -I1D (f;

if ( ( f $ fopen ( "78"! nom:re )) $$ =C11 ) return D3323;

if (=5H10 !$ f7rite ( p! siNeof(H10=D40)! =5H10! f )) return D3323;

if ( fclose(f) !$ ' ) return D3323; else return 2U; }

'ibliogra"(a y re"erencias. :3; El lenguaje de programacin C' #rian Y' 2ernig"an& Dennis 0' 1itc"ie' Prentice7Call Cispanoamericana& 34<G' I.#( 4D<7<<676?E7E :?; merican (ational .tandard for Information .ystems 77 Programming /anguage C' merican (ational .tandards Institute' 3E=6 #road8ay (e8 MorO& (M 3663<

:=; El lenguaje de programacin C& segunda edicin' #rian Y' 2ernig"an& Dennis 0' 1itc"ie' Prentice7Call Cispanoamericana& 3443' I.#( 4D<7<<67?6G76 :E; C' soft8are engineering approac"' Peter Darnell& P"ilip E' 0argolis' .pringer7Ferlag& 3443 I.#( =7GE6745=<47=

0i%uel

Zarcies

Vous aimerez peut-être aussi