You are on page 1of 30

Entrada y salida estndar en C++

1. 2. 3. 4.
Operaciones de salida. Operaciones de entrada Anexos Bibliografa

Cuando nos referimos a entrada/salida estndar (E/S estndar) queremos decir que los datos o bien se estn leyendo del teclado, bien se estn escribiendo en el monitor de video. Como se utilizan muy frecuentemente se consideran como los dispositivos de E/S por default y no necesitan ser nombrados en las instrucciones de E/S. En el lenguaje c++ tenemos varias alternativas para ingresar y/o mostrar datos, dependiendo de la librera que vamos a utilizar para desarrollar el programa, entre estas estn: iostream.h y sodio.h. < IOSTREAM.H> Las operaciones de entrada y salida no forman parte del conjunto de sentencias de C++, sino que pertenecen al conjunto de funciones y clases de la biblioteca estndar de C++. Ellas se incluyen en los archivos de cabecera iostream.h por lo que siempre que queramos utilizarlas deberemos introducir la lnea de cdigo #include <iostream.h> Esta biblioteca es una implementacin orientada a objetos y est basada en el concepto de flujos. A nivel abstracto un flujo es un medio de describir la secuencia de datos de una fuente a un destino o sumidero. As, por ejemplo, cuando se introducen caracteres desde el teclado, se puede pensar en caracteres que fluyen o se trasladan desde el teclado a las estructuras de datos del programa. Los objetos de flujo que vienen predefinidos sern: 1. cin, que toma caracteres de la entrada estndar (teclado); 2. cout, pone caracteres en la salida estndar (pantalla); 3. cerr y clog ponen mensajes de error en la salida estndar. Estos objetos se utilizan mediante los operadores << y >>. El operador << se denomina operador de insercin; y apunta al objeto donde tiene que enviar la informacin. Por lo tanto la sintaxis de cout ser: cout<<variable1<<variable2<<...<<variablen; No olvidemos que las cadenas de texto son variables y se ponen entre " " (comillas dobles). Por su parte >> se denomina operador de extraccin, lee informacin del flujo cin (a la izquierda del operador) y las almacena en las variables indicadas a la derecha). La sintaxis sera la siguiente: cin>>variable1>>...>>variablen; Un ejemplo de cdigo utilizando ambos objetos podra ser el siguiente: #include <iostream.h> ... main () { int i; cout<<"Introduce un nmero"; cin>>i; ... } ... Que mostrara por pantalla la frase "Introduce un nmero" y posteriormente almacenara el valor introducido por teclado en la variable i. <STDIO.H> Operaciones de salida.

Printf: Imprimir en pantalla Para utilizar la funcin printf en nuestros programas debemos incluir la directiva: #include <stdio.h> Si slo queremos imprimir una cadena basta con escribir la siguiente lnea de cdigo. printf( "Cadena" ); Como resultado muestra en pantalla: Cadena Lo que pongamos entre las comillas es lo que vamos a sacar por pantalla. Si volvemos a usar otro printf, por ejemplo: #include <stdio.h> void main() { printf( "Cadena" ); printf( "Segunda" ); } Obtendremos: CadenaSegunda Este ejemplo nos muestra cmo funciona printf. Para escribir en la pantalla se usa un cursor que no vemos. Cuando escribimos algo el cursor va al final del texto. Cuando el texto llega al final de la fila, lo siguiente que pongamos ir a la fila siguiente. Si lo que queremos es sacar cada una en una lnea deberemos usar "\n". Es el indicador de retorno de carro. Lo que hace es saltar el cursor de escritura a la lnea siguiente: #include <stdio.h> void main() { printf( "Cadena\n" ); printf( "Segunda" ); } y tendremos: Cadena Segunda Tambin podemos poner ms de una cadena dentro del printf: printf( "Primera cadena" "Segunda cadena" ); Lo que no podemos hacer es meter cosas entre las cadenas: printf( "Primera cadena" texto en medio "Segunda cadena" ); esto no es vlido. Cuando el compilador intenta interpretar esta sentencia se encuentra "Primera cadena" y luego texto en medio, no sabe qu hacer con ello y da un error. Pero qu pasa si queremos imprimir el smbolo " en pantalla? Por ejemplo imaginemos que queremos escribir: Esto es "extrao" Si para ello hacemos: printf( "Esto es "extrao"" ); obtendremos unos cuantos errores. El problema es que el smbolo " se usa para indicar al compilador el comienzo o el final de una cadena. As que en realidad le estaramos dando la cadena "Esto es", luego extrao y luego otra cadena vaca "". Pues resulta que printf no admite esto y de nuevo tenemos errores. La solucin es usar \". Veamos: printf( "Esto es \"extrao\"" ); Esta vez todo ir como la seda. Como vemos la contrabarra ' \' sirve para indicarle al compilador que escriba caracteres que de otra forma no podramos. Esta contrabarra se usa en C para indicar al compilador que queremos meter smbolos especiales. Pero Y si lo que queremos es usar '\' como un carcter normal y poner por ejemplo Hola\Adis? Pues muy fcil, volvemos a usar '\': printf( "Hola\\Adis" ); y esta doble '\' indica a C que lo que queremos es mostrar una '\'.

Operaciones de entrada Algo muy usual en un programa es esperar que el usuario introduzca datos por el teclado. Para ello contamos con varias posibilidades: Usar las funciones de la biblioteca estndar, crear nuestras propias interrupciones de teclado (MS-Dos) o usar funciones de alguna biblioteca diferente (como por ejemplo Allegro). En este trabajo topare solo la primera opcin, usando las funciones de la biblioteca estndar. Pero veamos por encima las otras posibilidades. Las funciones estndar estn bien para un programa sencillito. Pero cuando queremos hacer juegos por ejemplo, no suelen ser suficiente. Demasiado lentas o no nos dan todas las posibilidades que buscamos, como comprobar si hay varias teclas pulsadas. Para solucionar esto tenemos dos posibilidades: La ms complicada es crear nuestras propias interrupciones de teclado. Qu es una interrupcin de teclado? Es un pequeo programa en memoria que se ejecuta continuamente y comprueba el estado del teclado. Podemos crear uno nuestro y hacer que el ordenador use el que hemos creado en vez del suyo. Otra posibilidad ms sencilla es usar una biblioteca que tenga funciones para controlar el teclado. Por ejemplo si usamos la biblioteca Allegro, ella misma hace todo el trabajo y nosotros no tenemos ms que recoger sus frutos con un par de sencillas instrucciones. Esto soluciona mucho el trabajo y nos libra de tener que aprender cmo funcionan los aspectos ms oscuros del control del teclado. Vamos ahora con las funciones de la biblioteca estndar antes mencionada. Scanf El uso de scanf es muy similar al de printf con una diferencia, nos da la posibilidad de que el usuario introduzca datos en vez de mostrarlos. No nos permite mostrar texto en la pantalla, por eso si queremos mostrar un mensaje usamos un printf delante. Un ejemplo: #include <stdio.h> void main() { int num; printf( "Introduce un nmero " ); scanf( "%i", &num ); printf( "Has tecleado el nmero %i\n", num ); } Primero vamos a ver unas nota de esttica, para hacer los programas un poco ms elegantes. Parece una tontera, pero los pequeos detalles hacen que un programa gane mucho. El scanf no mueve el cursor de su posicin actual, as que en nuestro ejemplo queda: Introduce un nmero _ /* La barra horizontal indica dnde esta el cursor */ Esto es porque en el printf no hemos puesto al final el smbolo de salto de lnea '\n'. Adems hemos dejado un espacio al final de Introduce un nmero: para que as cuando tecleemos el nmero no salga pegado al mensaje. Si no hubisemos dejado el espacio quedara as al introducir el nmero 120 (es un ejemplo): Introduce un nmero120 Veamos cmo funciona el scanf. Lo primero nos fijamos que hay una cadena entre comillas. Esta es similar a la de printf, nos sirve para indicarle al compilador qu tipo de datos estamos pidiendo. Como en este caso es un integer usamos %i. Despus de la coma tenemos la variable donde almacenamos el dato, en este caso 'num'. Fjate que en el scanf la variable 'num' lleva delante el smbolo &, este es muy importante, sirve para indicar al compilador cual es la direccin (o posicin en la memoria) de la variable. Podemos preguntar por ms de una variable a la vez en un slo scanf, hay que poner un %i por cada variable: #include <stdio.h> void main()

{ int a, b, c; printf( "Introduce tres nmeros: " ); scanf( "%i %i %i", &a, &b, &c ); printf( "Has tecleado los nmeros %i %i %i\n", a, b, c ); } De esta forma cuando el usuario ejecuta el programa debe introducir los tres datos separados por un espacio. Tambin podemos pedir en un mismo scanf variables de distinto tipo: #include <stdio.h> void main() { int a; float b; printf( "Introduce dos nmeros: " ); scanf( "%i %f", &a, &b ); printf( "Has tecleado los nmeros %i %f\n", a, b ); } A cada modificador (%i, %f) le debe corresponder una variable de su mismo tipo. Es decir, al poner un %i el compilador espera que su variable correspondiente sea de tipo int. Si ponemos %f espera una variable tipo float.

Getch y getche Si lo que queremos es que el usuario introduzca un carcter por el teclado usamos las funciones getch y getche. Estas esperan a que el usuario introduzca un carcter por el teclado. La diferencia entre getche y getch es que la primera saca por pantalla la tecla que hemos pulsado y la segunda no (la e del final se refiere a echo=eco). Ejemplos: #include <stdio.h> void main() { char letra; printf( "Introduce una letra: " ); fflush( stdout ); letra = getche(); printf( "\nHas introducido la letra: %c", letra ); } Resultado: Introduce una letra: a Has introducido la letra: a Qu es el fflush( stdout )?. Pues bien, cuando usamos la funcin printf, no escribimos directamente en la pantalla, sino en una memoria intermedia (lo que llaman un bufer). Cuando este bufer se llena o cuando metemos un carcter '\n' es cuando se enva el texto a la pantalla. En este ejemplo yo quera que apareciera el mensaje Introduce una letra: y el cursor se quedara justo despus, es decir, sin usar '\n'. Si se hace esto, en algunos compiladores el mensaje no se muestra en pantalla hasta que se pulsa una tecla (probar). Y la funcin fflush( stdout ) lo que hace es enviar a la pantalla lo que hay en ese bufer. Y ahora un ejemplo con getch: #include <stdio.h> void main() { char letra; printf( "Introduce una letra: " ); fflush( stdout ); letra = getch(); printf("\n has introducido la letra :%c", letra ); }

Resultado: Introduce una letra: Has introducido la letra: a Como vemos la nica diferencia es que en el primer ejemplo se muestra en pantalla lo que escribimos y en el segundo no. ANEXOS

Usos de printf y scanf printf("Mensaje"); printf("Mensaje %d",Variable); printf("Mensaje %d",Variable:2:3); cprintf("Mensaje"); Escribe Mensaje en la pantalla Escribe Mensaje y el valor de la Variable en pantalla Escribe Mensaje y el valor de la Variable con 2 enteros y 3 decimales Escribe Mensaje en color especificado

scanf("%d",&Variable); Asigna valor entero a Variable scanf("%d %f",&Variable1,&Variable2); Asigna valor entero a Variable1 y valor real a Variable2

Nota C++ ofrece una alternativa a las llamadas de funcion printf y scanf para manejar la entrada/salida de los tipos y cadenas de datos estandar. As en lugar de printf usamos el flujo estandar de salida cout y el operador << ("colocar en"); y en lugar de scanf usamos el flujo de entrada estandar cin y el operador >>("obtener de"). Estos operadores de insercin y extraccin de flujo, a diferencia de printf y scanf, no requieren de cadenas de formato y de formato y de especificadotes de conversin para indicar los tipos de datos que son extraidos o introducidos. Las siguientes funciones nos resultan indispensable para poder brindar una mejor presentacin de los datos en pantalla. Gotoxy: Posicionando el cursor (DOS) Esta funcin slo est disponible en compiladores de C que dispongan de la biblioteca <conio.h> Hemos visto que cuando usamos printf se escribe en la posicin actual del cursor y se mueve el cursor al final de la cadena que hemos escrito. Vale, pero qu pasa cuando queremos escribir en una posicin determinada de la pantalla? La solucin est en la funcin gotoxy. Supongamos que queremos escribir 'Hola' en la fila 10, columna 20 de la pantalla: #include <stdio.h> #include <conio.h> void main() { gotoxy( 20, 10 ); printf( "Hola" ); } (Nota: para usar gotoxy hay que incluir la biblioteca conio.h). Fjate que primero se pone la columna (x) y luego la fila (y). La esquina superior izquierda es la posicin (1, 1).

Clrscr: Borrar la pantalla (DOS) Ahora ya slo nos falta saber cmo se borra la pantalla. Pues es tan fcil como usar: clrscr() (clear screen, borrar pantalla). Esta funcin n solo borra la pantalla, sino que adems sita el cursor en la posicin (1, 1), en la esquina superior izquierda. #include <stdio.h> #include <conio.h> void main() { clrscr(); printf( "Hola" ); } Este mtodo slo vale para compiladores que incluyan el fichero stdio.h. BIBLIOGRAFA Como programar en C/C++. H.M. Deitel / P.J. Deitel. Prentice may, 2da ed. 1995. Programacin orientada a objetos con C++. Fco. Javier Ceballos. Ed. ra-ma 1993. Programacion en C++. Enrique hernandez / Jose hernandez. Ed. Paraninfo 1993. EN INTERNET www.lawebdelprogramador.com http://www.publispain.com/supertutoriales/programacion Autor: Palate Gaibor Alex Fernando Datos personales: palatito@yahoo.com apalate@espol.edu.ec.

Lenguaje C
Introduccin C es un lenguaje de programacin de propsito general que ofrece economa sintctica, control de flujo y estructuras sencillas y un buen conjunto de operadores. No es un lenguaje de muy alto nivel y ms bien un lenguaje pequeo, sencillo y no est especializado en ningn tipo de aplicacin. Esto lo hace un lenguaje potente, con un campo de aplicacin ilimitado y sobre todo, se aprende rpidamente. En poco tiempo, un programador puede utilizar la totalidad del lenguaje. Este lenguaje ha sido estrechamente ligado al sistema operativo UNIX, puesto que fueron desarrollados conjuntamente. Sin embargo, este lenguaje no est ligado a ningn sistema operativo ni a ninguna mquina concreta. Se le suele llamar lenguaje de programacin de sistemas debido a su utilidad para escribir compiladores y sistemas operativos, aunque de igual forma se puede desarrollar cualquier tipo de aplicacin. La base del C proviene del BCPL, escrito por Martin Richards, y del B escrito por Ken Thompson en 1970 para el primer sistema UNIX en un DEC PDP-7. Estos son lenguajes sin tipos, al contrario que el C que proporciona varios tipos de datos. Los tipos que ofrece son caracteres, nmeros enteros y en coma flotante, de varios tamaos. Adems se pueden crear tipos derivados mediante la utilizacin de punteros, vectores, registros y uniones. El primer compilador de C fue escrito por Dennis Ritchie para un DEC PDP-11 y escribi el propio sistema operativo en C.Introduccin al lenguaje C (2). La base del C proviene del BCPL, escrito por Martin Richards, y del B escrito por Ken Thompson en 1970 para el primer sistema UNIX en un DEC PDP-7. Estos son lenguajes sin tipos, al contrario que el C que proporciona varios tipos de datos. Los tipos que ofrece son caracteres, nmeros enteros y en coma flotante, de varios tamaos. Adems se pueden crear tipos derivados mediante la utilizacin de punteros, vectores, registros y uniones. El primer compilador de C fue escrito por Dennis Ritchie para un DEC PDP-11 y escribi el propio sistema operativo en C. C trabaja con tipos de datos que son directamente tratables por el hardware de la mayora de computadoras actuales, como son los caracteres, nmeros y direcciones. Estos tipos de datos pueden ser manipulados por las operaciones aritmticas que proporcionan las computadoras. No proporciona mecanismos para tratar tipos de datos que no sean los bsicos, debiendo ser el programador el que los desarrolle. Esto permite que el cdigo generado sea muy eficiente y de ah el xito que ha tenido como lenguaje de desarrollo de sistemas. No proporciona otros mecanismos de almacenamiento de datos que no sea el esttico y no proporciona mecanismos de entrada ni salida. Ello permite que 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 librera para realizar todas estas tareas, que normalmente dependen del sistema operativo. Originariamente, el manual de referencia del lenguaje para el gran pblico fue el libro de Kernighan y Ritchie, escrito en 1977. Es un libro que explica y justifica totalmente el desarrollo de aplicaciones en C, aunque en l se utilizaban construcciones, en la definicin de funciones, que podan provocar confusin y errores de programacin que no eran detectados por el compilador. Como los tiempos cambian y las necesidades tambin, en 1983 ANSI establece el comit X3J11 para que desarrolle una definicin moderna y comprensible del C. El estndar est basado en el manual de referencia original de 1972 y se desarrolla con el mismo espritu de sus creadores originales. La primera versin de estndar se public en 1988 y actualmente todos los compiladores utilizan la nueva definicin. Una aportacin muy importante de ANSI consiste en la definicin de un conjunto de libreras que acompaan al compilador y de las funciones contenidas en ellas. Muchas de las operaciones comunes con el sistema operativo se realizan a travs de estas funciones. Una coleccin de ficheros de encabezamiento, headers, en los que se definen los tipos de datos y funciones incluidas en cada librera. Los programas que utilizan estas bibliotecas para interactuar con el sistema operativo obtendrn un comportamiento equivalente en otro sistema.

Captulo 1.

Estructura bsica de un programa en C

La mejor forma de aprender un lenguaje es programando con l. El programa ms sencillo que se puede escribir en C es el siguiente: main( ) { } Como nos podemos imaginar, este programa no hace nada, pero contiene la parte ms importante de cualquier programa C y adems, es el ms pequeo que se puede escribir y que se compile correctamente. En el se define la funcin main, que es la que ejecuta el sistema operativo al llamar a un programa C. El nombre de una funcin C siempre va seguida de parntesis, tanto si tiene argumentos como si no. La definicin de la funcin est formada por un bloque de sentencias, que esta encerrado entre llaves {}. Un programa algo ms complicado es el siguiente: #include <stdio.h> main( ) { printf("Hola amigos!\n"); } Con el visualizamos el mensaje Hola amigos! en el terminal. En la primera lnea indica que se tengan en cuenta las funciones y tipos definidos en la librera stdio (standard input/output). Estas definiciones se encuentran en el fichero header stdio.h. Ahora, en la funcin main se incluye una nica sentencia que llama a la funcin printf. Esta toma como argumento una cadena de caracteres, que se imprimen van encerradas entre dobles comillas " ". El smbolo \n indica un cambio de lnea. Hay un grupo de smbolos, que son tratados como caracteres individuales, que especifican algunos caracteres especiales del cdigo ASCII. Los ms importantes son:

\a \b \f \n \r \t

Alerta Espacio atrs Salto de pgina Salto de lnea Retorno de carro Tabulacin horizontal

\v \\ \' \" \OOO \xHHH

Tabulacin vertical Barra invertida Comilla simple Comillas dobles Visualiza un carcter cuyo cdigo ASCII es OOO en octal Visualiza un carcter cuyo cdigo ASCII es HHH en hexadecimal

Un programa C puede estar formado por diferentes mdulos o fuentes. Es conveniente mantener los fuentes de un tamao no muy grande, para que la compilacin sea rpida. Tambin, al dividirse un programa en partes, puede facilitar la legibilidad del programa y su estructuracin. Los diferentes fuentes son compilados de forma separada, nicamente los fuentes que han sido modificados desde la ltima compilacin, y despus combinados con las libreras necesarias para formar el programa en su versin ejecutable.

Captulo 2.

Tipos bsicos y variables Los tipos de datos bsicos definidos por C son caracteres, nmeros enteros y nmeros en coma flotante. Los caracteres son representados por char, los enteros por short, int, long y los nmeros en coma flotante por float y double. Los tipos bsicos disponibles y su tamao 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

(normalmente 8 bits) (normalmente 16 bits) (depende de la implementacin) (depende de la implementacin) (normalmente 32 bits) (normalmente 32 bits) (normalmente 64 bits)

La palabra unsigned en realidad es un modificador aplicable a tipos enteros, aunque si no se especifica un tipo se supone int. Un modificador es una palabra clave de C que indica que una variable, o funcin, no se comporta de la forma normal. Hay tambin un modificador signed, pero como los tipos son por defecto con signo, casi no se utiliza. Las variables son definidas utilizando un identificador de tipo seguido del nombre de la variable. Veamos el siguiente programa: #include <stdio.h> main() { float cels, farh; farh = 35.0; cels = 5.0 * ( farh - 32.0 ) / 9.0; printf("-> %f F son %f C\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 aritmtica. Las asignaciones en C tambin son una expresin, por lo que se pueden utilizar como parte de otra expresin, pero segn que prcticas de este tipo no son muy recomendables ya que reducen la legibilidad del programa. En la instruccin printf, el smbolo %f indica que se imprime un nmero en coma flotante. Hay un tipo muy importante que se representa por void que puede significar dos cosas distintas, segn su utilizacin. Puede significar nada, o sea que si una funcin devuelve un valor de tipo void no devuelve ningn resultado, o puede significar cualquier cosa, como puede ser un puntero a void es un puntero genrico a cualquier tipo de dato. Ms adelante veremos su utilizacin.

Captulo 3.

Funciones Un programa C est formado por un conjunto de funciones que al menos contiene la funcin main. Una funcin se declara con el nombre de la funcin precedido del tipo de valor que retorna y una lista de argumentos encerrados entre parntesis. El cuerpo de la funcin est formado por un conjunto de declaraciones y de sentencias comprendidas entre llaves. Veamos un ejemplo de utilizacin de funciones: #include <stdio.h> #define VALOR 5 #define FACT 120 int fact_i ( int v ) { int r = 1, i = 0;

while ( i <= v ) { r = r * i; i = i + 1; } return r; } int fact_r ( int v ) { if ( v == 0 ) return 1; else return v * fact_r(v-1); } main() { int r, valor = VALOR; if ( (r = fact_i(valor)) != fact_r(valor) ) printf("Codificacin errnea!!.\n"); else if ( r == FACT ) printf("Codificacin correcta.\n"); else printf("Algo falla!!.\n"); } Se definen dos funciones, fact_i y fact_r, adems de la funcin main. Ambas toman como parmetro un valor entero y devuelven otro entero. La primera calcula el factorial de un nmero de forma iterativa, mientras que la segunda hace lo mismo de forma recursiva. Todas las lneas que comienzan con el smbolo # indican una directiva del precompilador. Antes de realizar la compilacin en C se llama a un precompilador cuya misin es procesar el texto y realizar ciertas sustituciones textuales. Hemos visto que la directiva #include incluye el texto contenido en un fichero en el fuente que estamos compilando. De forma parecida, #define nombre texto sustituye todas las apariciones de nombre por texto. As, en el fuente, la palabra VALOR se sustituye por el nmero 5. El valor que debe devolver una funcin se indica con la palabra return. La evaluacin de la expresin debe dar una valor del mismo tipo de dato que el que se ha definido como resultado. La declaracin de una variable puede incluir una inicializacin en la misma declaracin. Se debe tener muy en cuenta que en C todos los argumentos son pasados 'por valor'. No existe el concepto de paso de parmetros 'por variable' o 'por referencia'. Veamos un ejemplo: int incr ( int v ) { return v + 1; } main() { int a, b; b = 3;

a = incr(b); /* a = 4 mientras que b = 3. No ha cambiado despus de la llamada. */ } En el ejemplo anterior el valor del parmetro de la funcin incr, aunque se modifique 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. Captulo 4.

Expresiones y operadores Los distintos operadores permiten formar expresiones tanto aritmticas como lgicas. Los operadores aritmticos y lgicos son:

+, ++, -*, /, % >>, << & | ^ ~ ! ==, != &&, || <, <= >, >=

suma, resta incremento, decremento multiplicacin, divisin, mdulo rotacin de bits a la derecha, izquierda. AND booleano OR booleano EXOR booleano complemento a 1 complemento a 2, NOT lgico igualdad, desigualdad AND, OR 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, que son las normales en la mayora de lenguajes. Se debe consultar el manual de referencia para obtener una

explicacin detallada. Adems hay toda una serie de operadores aritmticos con asignacin, como pueden ser += y ^=. En la evaluacin de expresiones lgicas, los compiladores normalmente utilizan tcnicas de evaluacin rpida. Para decidir si una expresin lgica es cierta o falsa muchas veces no es necesario evaluarla completamente. Por ejemplo una expresin formada <exp1> || <exp2>, el compilador evala primero <exp1> y si es cierta, no evala <exp2>. Por ello se deben evitar construcciones en las que se modifiquen valores de datos en la propia expresin, pues su comportamiento puede depender de la implementacin del compilador o de la optimizacin utilizada en una compilacin o en otra. Estos son errores que se pueden cometer fcilmente en C ya que una asignacin es tambin una expresin. Debemos evitar: if (( x++ > 3 ) || ( x < y )) y escribir en su lugar: x++; if (( x > 3 ) || ( x < y )) Hay un tipo especial de expresin en C que se denomina expresin condicional y est representada por los operadores ? : . Su utilizacin es como sigue: <e> ? <x> : <y>. Se evala si e entonces x; si no, y. int mayor ( int a, int b ) { return ( a > b ) ? TRUE : FALSE; } waste_time () { float a, b = 0.0; ( b > 0.0 ) ? sin(M_PI / 8) : cos(M_PI / 4); } Captulo 5.

Conversin de tipos Cuando escribimos una expresin aritmtica a+b, en la cual hay variables o valores de distintos tipos, el compilador realiza determinadas conversiones antes de que evale la expresin. Estas conversiones pueden ser para 'aumentar' o 'disminuir' la precisin del tipo al que se convierten los elementos de la expresin. Un 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 realizar la comparacin. Los tipos pequeos 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. Un unsigned char es convertido a int con los bits ms altos puestos a cero. Un 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 tamao: Si un operando es de tipo double, el otro es convertido a double. Si un operando es de tipo float, el otro es convertido a float. Si un operando es de tipo unsigned long, el otro es convertido a unsigned long. Si un operando es de tipo long, el otro es convertido a long. Si un operando es de tipo unsigned, el otro es convertido a unsigned. Si no, los operandos son de tipo int.

Una variable o expresin de un tipo se puede convertir explcitamente a otro tipo, anteponindole el tipo entre parntesis. void cambio_tipo (void) { float a; int b; b = 10; a = 0.5; if ( a <=(float) b ) menor(); } Captulo 6.

Control de flujo Sentencia if La sentencia de control bsica es if (<e>) then <s> else <t>. En ella se evala una expresin condicional y si se cumple, se ejecuta la sentencia s; si no, se ejecuta la sentencia t. La segunda parte de la condicin, else <t>, es opcional. int cero ( double a ) { if ( a == 0.0 ) return (TRUE); else return (FALSE); } En el caso que <e> no sea una expresin condicional y sea aritmtica, se considera falso si vale 0; y si no, verdadero. Hay casos en los que se deben evaluar mltiples condiciones y nicamente se debe evaluar una de ellas. Setencia switch Se puede programar con un grupo de sentencias if then else anidadas, aunque ello puede ser farragoso y de complicada lectura. Para evitarlo nos puede ayudar la sentencia switch. Su utilizacin es: switch (valor) {

case valor1: <sentencias> case valor2: <sentencias> ... default: <sentencias> }

Cuando se encuentra una sentencia case que concuerda con el valor del switch se ejecutan las sentencias que le siguen y todas las dems a partir de ah, a no ser que se introduzca una sentencia break para salir de la sentencia switch. Por ejemplo: ver_opcion ( char c ) { switch(c){ case 'a': printf("Op A\n"); break; case 'b': printf("Op B\n"); break; case 'c': case 'd': printf("Op C o D\n"); break; default: printf("Op ?\n"); } }

Setencia while Otras sentencias de control de flujo son las que nos permiten realizar iteraciones sobre un conjunto de sentencias. En C tenemos tres formas principales de realizar iteraciones. La sentencia while (<e>) <s> es seguramente la ms utilizada. La sentencia, o grupo de sentencias <s> se ejecuta mientras la evaluacin de la expresin <e> sea verdadera. long raiz ( long valor ) { long r = 1; while ( r * r <= valor )

r++; return r; } Una variacin de la sentencia while es: do <s> while ( <e> ); En ella la sentencia se ejecuta al menos una vez, antes de que se evale la expresin condicional. Setencia for Otra sentencia iterativa, que permite inicializar los controles del bucle es la sentencia for ( <i>; <e>; <p> ) <s>. La sentencia for se puede escribir tambin como: <i>; while ( <e> ) { <s>; <p>; }

El ejemplo anterior se podra escribir como: long raiz ( long valor ) { long r; for ( r = 1; r * r <= valor; r++ ) ; return r; } Break y Continue Otras sentencias interesantes, aunque menos utilizadas son break y continue. break provoca que se termine la ejecucin de una iteracin o para salir de la sentencia switch, como ya hemos visto. En cambio, continue provoca que se comience una nueva iteracin, evalundose la expresin de control. Veamos dos ejemplos: void final_countdown (void) { int count = 10; while ( count--> 1 ) { if ( count == 4 )

start_engines(); if ( status() == WARNING ) break; printf("%d ", count ); } if ( count == 0 ){ launch(); printf("Shuttle launched\n"); } else { printf("WARNING condition received.\n"); printf("Count held at T - %d\n", count ); } } d2 () { int f; for ( f = 1; f <= 50; f++ ) { if ( f % 2 == 0 ) continue; printf("%d",f ); } } Captulo 7.

Definicin y prototipos de funciones Los programas sencillos, como los ejemplo planteados hasta ahora, normalmente no necesitan un nivel de estructuracin elevado. Pero cuando stos crecen un poco necesitamos estructurarlos adecuadamente para mantenerlos legibles, facilitar su mantenimiento y para poder reutilizar ciertas porciones de cdigo. El mecanismo C que nos permite esto son las funciones. Con los compiladores, los fabricantes nos proporcionan

un conjunto importante de funciones de librera. A veces, nos puede interesar construir nuestras propias libreras. Ya hemos utilizado funciones, pero veamos cmo debemos definirlas. Los prototipos de funciones son una caracterstica clave de la recomendacin ANSI del C. Un prototipo es una declaracin que toma la forma: tipo_resultado nombre_funcin ( tipo_parmetro nombre_parmetro ... ); int fact_i ( int v ); int mayor ( int a, int b ); int cero ( double a ); long raiz ( long valor ); void final_countdown ( void ); int main ( int argc, char **argv ); Observando el prototipo de una funcin podemos decir exactamente que tipo de parmetros necesita y que resultado devuelve. Si una funcin tiene como argumento void, quiere decir que no tiene argumentos, al igual que si el resultado es void, no devuelve ningn valor. En la vieja definicin de Kernighan y Ritchie el tipo que devolva una funcin se declaraba nicamente si era distinto de int. Similarmente, los parmetros eran declarados en el cuerpo de la funcin, en lugar de utilizar la lista de parmetros. Por ejemplo: mayor ( a, b ) int a; int b; { ... } Las funciones al viejo estilo se compilan correctamente en muchos compiladores actuales. Por contra, proporcionan menos informacin sobre sus parmetros y errores que 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 que su prototipo pero sin el punto y coma final. El cuerpo de la funcin le sigue encerrado entre llaves. En un programa que est formado por distintas partes bien diferenciadas es conveniente utilizar mltiples ficheros fuente. Cada fuente agrupa las funciones semejantes, como por ejemplo en un compilador podramos tener un fuente para el anlisis lxico, otro para el sintctico y otro para la generacin de cdigo. Pero en un fuente necesitaremos funciones que se han definido en otro. Para ello, escribiremos, un fichero de cabecera (header), que contendr las declaraciones que podemos necesitar en otros fuente. As, en el fuente que implementa el analizador sintctico pondremos una lnea #include "lexic.h". De esta forma al compilar el mdulo sintctico tendremos todos los prototipos de las funciones del lxico y el compilador podr detectar malas utilizaciones de las funciones all definidas.

Captulo 8.

Construccin de tipos Los datos del mundo real, normalmente no estn formados por variables escalares de tipos los tipos bsicos. Por ejemplo, nos puede interesar saber cuntos mdulos en C hemos escrito cada semana, a lo largo del ao. O tambin nos interesa tener los datos de cada planeta del Sistema Solar, masa, posicin, velocidad y

aceleracin, para un programa de simulacin de la ley de gravitacin de Newton. Para resolver el primer caso, C nos permite declarar una variable que sea de tipo vector. Para el segundo, podemos definir un registro para cada elemento. Un vector es una porcin de memoria que es utilizada para almacenar un grupo de elementos del mismo tipo Un vector se declara: tipo nombre [tamao];. Por ejemplo, int modulo[52];. Aqu 'modulo' es un vector de 52 elementos enteros. main() { int f, modulo[52]; for ( f = 0; f< 52; f++ ) modulo[f] = 0; ... }

Cada elemento de un vector es accedido mediante un nmero de ndice y se comporta como una variable del tipo base del vector. Los elementos de un vector son accedidos por ndices que van desde 0 hasta N-1 para un vector de N elementos. Los elementos de un vector pueden ser inicializados en la misma declaracin: char vocal[5] = {'a', 'e', 'i', 'o', 'u' }; float n_Bode[5] = { 0.4, 0.7, 1, 1.6, 2.8 }; Tambin podemos definir vectores multidimensionales. C no impone ninguna limitacin al nmero de dimensiones de un vector. Existe, en cambio, la limitacin del tamao de memoria que podamos utilizar en nuestro ordenador. Por ejemplo, para la declaracin de un vector multidimensional podemos escribir: int video[25][80][2]; El tamao de la variable video es proporcional al tamao del tipo int y al tamao de cada dimensin. Existe un operador C que nos permite obtener el tamao de un tipo o de una variable. Este es sizeof() y nos proporciona el tamao en bytes.

if ( sizeof(video) == 80 * 25 * 2 * sizeof(int) ) printf("OK!\n"); else printf("Algo no funciona.\n");

Un tipo vector muy utilizado es la cadena de caracteres (string). Si queremos asignar espacio para un string podemos hacer: char nombre[60], direccion[80];

Es un vector C pero con la particularidad de que el propio lenguaje utiliza un carcter especial como marca de final de string. As en un vector de caracteres de tamao N podremos almacenar una cadena de N-1 caracteres, cuyo ltimo carcter estar en la posicin N-2 y la marca de final de string en la N-1. Veamos un ejemplo: char servei[6] = "SCI"; La posicin 0 contiene el carcter 'S'; la 1 el 'C'; la 2 el 'I'; la 3 el '\0', marca de final de string. El resto de componentes no estn definidas. En la inicializacin de strings no se debe indicar el final; ya lo hace el compilador. Para la manipulacin de cadenas de caracteres ANSI proporciona el fichero string.h que contiene las declaraciones de un conjunto de funciones proporcionadas con la librera del compilador. Un registro agrupa distintos tipos de datos en una misma estructura. Los registros son definidos de la forma: struct nombre{ lista de declaraciones }; Los campos de cada registro pueden ser tipos bsicos u otros registros. Por ejemplo: struct planeta { struct 3D r, v, a; double masa; char nom[10]; }; struct 3D { double x,y,z; }; Los 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 hace su tipo bsico. C no proporciona mecanismos de inicializacin, ni copia de registros, por lo que debe ser el programador el que los implemente. A veces los datos se ajustan a series ordenadas en las cuales un elemento sigue, o precede, a otro. Un caso tpico son los das de la semana. Si se desea realizar iteraciones con los das de la semana una forma es, por ejemplo, asignar un nmero a cada da con #define. C proporciona un mecanismo compacto para realizar esto; son las enumeraciones. Una enumeracin toma la forma: enum nombre { lista de elementos };. Veamos un ejemplo: void planning ( void ) { enum diasemana {lunes, martes, miercoles, jueves, viernes, sabado, domingo }; int dia; for ( dia = lunes; dia <= viernes; dia++ ) trabajar(dia); if ( dia == sabado )

salir(); } A cada elemento de la enumeracin se le asigna un valor consecutivo, comenzando por 0. Si se desea que el valor asignado sea distinto se puede hacer de la siguiente forma: enum puntos { t_6_25 = 3, t_zona = 2, t_libre = 1 }; Muchas veces es conveniente renombrar tipos de datos para que la escritura del programa se nos haga ms sencilla y la lectura tambin. Esto se puede conseguir con la palabra typedef. Con ella damos un nombre a cierto tipo, o combinacin de ellos. typedef struct planeta PLANETA; PLANETA mercurio, venus, tierra, marte; Al igual que podemos inicializar las variables de tipos bsicos en la misma declaracin, tambin lo podemos hacer con los registros. Los valores de cada campo de un registro van separados por comas y encerrados entre llaves. PLANETA mercurio = {{ 0.350, 0, 0 }, { 0, 0, 0 }, { 0, 0, 0 }, 100,"Mercurio" };

Captulo 9. Ambito de funciones y variables. El mbito, o visibilidad, de una variable nos indica en que lugares del programa est activa esa variable. Hasta ahora, en los ejemplos que hemos visto, se han utilizado 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 la funcin termina de ejecutarse. Es necesario a veces, que una variable tenga un valor que 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 han sido declaradas y si se les ha aplicado algn modificador. Una variable definida en una funcin es, por defecto, una variable local. Esto es, que slo existe y puede ser accedida dentro de la funcin. Para que una variable sea visible desde una funcin cualquiera del mismo fuente debe declararse fuera de cualquier funcin. Esta variable slo ser visible en las funciones definidas despus de su declaracin. Por esto, el lugar ms comn 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 que existe una variable global que est definida en otro fuente tenemos que anteponer la palabra extern a su declaracin. Esta declaracin nicamente indica al compilador que se har referencia a una variable declarada en un mdulo distinto al que se compila. Las variables locales llevan implcito el modificador auto. Este indica que se crean al inicio de la ejecucin de la funcin y se destruyen al final. En un programa sera muy ineficiente en trminos de almacenamiento que 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. Si una funcin necesita una variable que nicamente sea accedida por la misma funcin y que conserve su valor a travs de sucesivas llamadas, es el caso adecuado para que sea declarada local a la funcin con el modificador static. El modificador static se puede aplicar tambin a variables globales. Una variable global es por defecto accesible desde cualquier fuente del programa. Si, por cualquier motivo, se desea que una de estas variables no se visible desde otro fuente se le debe aplicar el modificador static. Lo mismo ocurre con las funciones. Las funciones definidas en un fuente son utilizables desde cualquier otro. En este caso conviene incluir los prototipos de las funciones del otro

fuente. Si no se desea que alguna funcin pueda ser llamada desde fuera del fuente en la que est definida se le debe anteponer el modificador static.z void contar ( void ) { static long cuenta = 0; cuenta++; printf("Llamada%ld veces\n", cuenta ); } Un modificador muy importante es const. Con l se pueden definir variables cuyo valor debe permanecer constante durante toda la ejecucin del programa. Tambin se puede utilizar con argumentos de funciones. En esta caso se indica que el argumento en cuestin es un parmetro y su valor no debe ser modificado. Si al programar la funcin, modificamos ese parmetro, el compilador nos indicar el error. #define EULER 2.71828 const double pi = 3.14159; double lcercle (const double r ) { return 2.0 * pi * r; } double EXP ( const double x ) { return pow (EULER, x ); } double sinh (const double x ) { return (exp(x) - exp(-x)) / 2.0; } Debemos fijarnos que en el ejemplo anterior pi es una variable, la cual no podemos modificar. Por ello pi slo puede aparecer en un nico fuente. Si la definimos en varios, al linkar el programa se nos generar un error por tener una variable duplicada. En el caso en que queramos acceder a ella desde otro fuente, debemos declararla con el modificador extern. Otro modificador utilizado algunas veces es el register. Este modificador es aplicable nicamente a variables locales e indica al compilador que esta variable debe ser almacenada permanentemente en un registro del procesador del ordenador. Este modificador es herencia de los viejos tiempos, cuando las tecnologas de optimizacin de cdigo no estaban muy desarrolladas y se deba indicar qu variable era muy utilizada en la funcin. Hoy en da casi todos los compiladores realizan un estudio de qu 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 que una declaracin register inadecuada disminuya la velocidad de

ejecucin de la funcin, en lugar de aumentarla. Por ello, hoy en da, la utilizacin de este modificador est en desuso, hasta el punto de que algunos compiladores lo ignoran. Se debe tener en cuenta que de una variable declarada como register no se puede obtener su direccin, ya que est almacenada en un registro y no en memoria.

Captulo 10. Punteros Cada variable de un programa tiene una direccin en la memoria del ordenador. Esta direccin indica la posicin del primer byte que la variable ocupa. En el caso de una estructura es la direccin del primer campo. En los ordenadores actuales la direccin de inicio se considera la direccin baja de memoria. Como en cualquier caso las variables son almacenadas ordenadamente y de una forma predecible, es posible acceder a estas y manipularlas mediante otra variables que contenga su direccin. A este tipo de variables se les denomina punteros. Los punteros C son el tipo ms potente y seguramente la otra clave del xito del lenguaje. La primera ventaja que obtenemos de los punteros es la posibilidad que nos dan de poder tratar con datos de un tamao arbitrario sin tener que moverlos por la memoria. Esto puede ahorrar un tiempo de computacin muy importante en algunos tipos de aplicaciones. Tambin permiten que una funcin reciba y cambie el valor de una variable. Recordemos que todas las funciones C nicamente aceptan parmetros por valor. Mediante un puntero a una variable podemos modificarla indirectamente desde una funcin cualquiera. Un puntero se declara de la forma: tipo *nombre; float *pf; PLANETA *pp; char *pc; Para manipular un puntero, como variable que es, se utiliza su nombre; pero para acceder a la variable a la que apunta se le debe preceder de *. A este proceso se le llama indireccin. Accedemos indirectamente a una variable. Para trabajar con punteros existe un operador, &, que indica 'direccin de'. Con l se puede asignar a un puntero la direccin de una variable, o pasar como parmetro a una funcin. void prueba_puntero ( void ) { long edad; long *p; p = &edad; edad = 50; printf("La edad es %ld\n", edad ); *p = *p / 2; printf("La edad es %ld\n", edad ); } void imprimir_string ( char string[] ) { char *p; for ( p = string; *p != '\0'; p++ )

imprimir_char(*p); } Definimos un vector de N_PLA componentes de tipo PLANETA. Este tipo est formado por un registro. Vemos que en la funcin de inicializacin del vector el puntero a la primera componente se inicializa con el nombre del vector. Esto es una caracterstica importante de C. La direccin de la primera componente de un vector se puede direccionar con el nombre del vector. Esto es debido a que en la memoria del ordenador, los distintos elementos estn ordenados de forma ascendente. As, SSolar se puede utilizar como &SSolar[0]. A cada iteracin llamamos a una funcin que nos inicializar los datos de cada planeta. A esta funcin le pasamos como argumento el puntero a la componente en curso para que, utilizando 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 realizar determinadas operaciones aritmticas aunque, a parte del incremento y decremento, no son muy frecuentes. Cuando incrementamos un puntero el compilador le suma la cantidad necesaria para que apunte al siguiente elemento de la memoria. Debemos fijarnos que esto es aplicable slo siempre que haya distintas variables o elementos situados consecutivamente en la memoria, como ocurre con los vectores. De forma similar se pueden utilizar funciones que tengan como parmetros punteros, para cambiar el valor de una variable. Veamos: void intercambio ( void ) { int a, b; a = 1; b = 2; swap( &a, &b ); printf(" a = %d b = %d\n", a, b ); } void swap ( int *x, int *y ) { int tmp; tmp = *x; *x = *y; *y = tmp; } La sintaxis de C puede, a veces, provocar confusin. Se debe distinguir lo que es un prototipo de una funcin de lo que es una declaracin de una variable. As mismo, un puntero a un vector de punteros, etc... int f1(); funcin que devuelve un entero int *p1; puntero a entero int *f2(); funcin que devuelve un puntero a entero int (*pf)(int); puntero a funcin que toma y devuelve un entero int (*pf2)(int *pi); puntero a funcin que toma un puntero a entero y devuelve un entero int a[3]; vector de tres enteros int *ap[3]; vector de tres punteros a entero int *(ap[3]); vector de tres punteros a entero int (*pa)[3]; puntero a vector de tres enteros

entero.

int (*apf[5])(int *pi); vector de 5 punteros a funcin que toman un puntero a entero y devuelven un

En los programas que se escriban se debe intentar evitar declaraciones complejas que dificulten la legibilidad del programa. Una forma de conseguirlo es utilizando typedef para redefinir/renombrar tipos. typedef int *intptr; typedef intptr (*fptr) ( intptr ); fptr f1, f2;

Captulo 11. El Preprocesador. El preprocesador es una parte del compilador que se ejecuta en primer lugar, cuando se compila un fuente C y que realiza unas determinadas operaciones, independientes del propio lenguaje C. Estas operaciones se realizan a nivel lxico y son la inclusin de otros textos en un punto del fuente, realizar sustituciones o eliminar ciertas partes del fuente. Debemos tener en cuenta que el preprocesador trabaja nicamente con el texto del fuente y no tiene en cuenta ningn aspecto sintctico ni semntico del lenguaje. El control del preprocesador se realiza mediante determinadas directivas incluidas en el fuente. Una directiva es una palabra que interpreta el preprocesador, que siempre va precedida por el smbolo # y que est situada a principio de lnea. La directiva #define se utiliza para definir una macro. Las macros proporcionan principalmente un mecanismo para la sustitucin lxica. Una 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. Una macro se puede "indefinir" mediante la directiva #undef.

#define MSG01 "SCI-I-START: Starting system kernel\n" #define MSG02 "SCI-I-STOP: Stopping system kernel\n" void print_msg ( void ) { if ( check_state() == START ) printf(MSG01); else printf(MSG02); } 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 M_PI #define M_PI 3.1415927 #endif El preprocesador nos permite tambin incluir tambin otros ficheros en un fuente C. Esto se consigue con la directiva #include. Esta puede tomar tres formas: #include , #include "fichero" y #include macro. La diferencia entre la primera y la segunda est en el lugar dnde se buscar el fichero en cuestin. Normalmente se utiliza

la primera para ficheros proporcionados por la librera del compilador y la segunda para ficheros creados por el programador. Captulo 12. Funciones de entrada/salida. En este apartado y los siguientes vamos a ver algunas de las funciones ms importantes que nos proporcionan las libreras definidas por ANSI y su utilizacin. Como hemos visto hasta ahora, el lenguaje C no proporciona ningn mecanismo de comunicacin ni con el usuario ni con el sistema operativo. Ello es realizado a travs de las funciones de librera proporcionadas por el compilador. El fichero de declaraciones que normalmente ms se utiliza es el stdio.h. Vamos a ver algunas funciones definidas en l. Una funcin que ya hemos utilizado y que, ella y sus variantes, es la ms utilizadas para la salida de informacin es printf. Esta permite dar formato y enviar datos a la salida estndar del sistema operativo. #include <stdio.h> int printf ( const char *format [, argumentos, ...] ); Acepta un string de formato y cualquier nmero de argumentos. Estos argumentos se aplican a cada uno de los especificadores de formato contenidos en format. Un especificador de formato toma la forma %[flags][width] [.prec][h|l] type. El tipo puede ser:

d, i o u x X f e g E G c s

entero decimal con signo entero octal sin signo entero decimal sin signo entero hexadecimal sin signo (en minsculas) entero hexadecimal sin signo (en maysculas) coma flotante en la forma [-]dddd.dddd coma flotante en la forma [-]d.dddd e[+/-]ddd coma flotante segn el valor como e pero en maysculas como g pero en maysculas un carcter cadena de caracteres terminada en '\0'

% p

imprime el carcter % puntero

Los flags pueden ser los caracteres:

+ blank #

siempre se imprime el signo, tanto + como justifica a la izquierda el resultado, aadiendo espacios al final si es positivo, imprime un espacio en lugar de un signo + especifica la forma alternativa

En el campo width se especifica la anchura mnima 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

Hay dos modificadores de tamao, para los tipos enteros:

l h

imprime un entero long imprime un entero short

Otra 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, que indican dnde depositar los valores. #include <stdio.h> int scanf ( const char *format [, argumentos, ...] ); Hay dos funciones que trabajan con strings. La 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 ); Tambin hay funciones de lectura y escritura de caracteres individuales. #include <stdio.h> int getchar ( void ); int putchar ( int c ); Veamos, por ejemplo, un programa que copia la entrada estndar a la salida estndar del sistema operativo, carcter a carcter. #include <stdio.h> main() { int c; while ( (c = getchar()) != EOF ) putchar(c); } Trabajo enviado por: Richard A. Sequera A. rsequera20@hotmail.com

2. El Modelo Entidad Relacin. (Modelo E-R) Tal como se ha destacado anteriormente, los dos elementos fundamentales de este Modelo de Datos, se encuentran inmersos en su propio nombre: la Entidad o Conjunto de Entidades y la Relacin o Conjunto de Relaciones. Una entidad se distingue de otra por medio de sus atributos, o caractersticas de la misma. Por propia definicin, no pueden existir dos entidades iguales. El contenido o valor de los atributos se encuentra limitado por un determinado Rango. Una entidad se puede agrupar con otras del mismo tipo (es decir, que posean los mismos atributos, pero, evidentemente, con contenido diferente). Es decir, una entidad Persona, puede pertenecer al conjunto de entidades Ciudadanos. Una entidad puede pertenecer a varios conjuntos de entidades, o sea, la misma entidad Persona puede pertenecer al conjunto de entidades Clientes de una determinada empresa. Al conjunto de atributos que sirve para identificar una entidad de otra, se le conoce como Superclave, y a la superclave mnima (es decir, al mnimo conjunto de atributos vlido para efectuar la distincin entre dos entidades), se le denomina Clave Primaria. La Clave Primaria de una entidad, es tambin la clave primaria del conjunto de entidades del mismo tipo. Cuando una entidad precise por razones de existencia, de la existencia previa de otra entidad de distinto tipo (es el tpico caso de un apunte en una cuenta corriente: no puede existir el apunte si no existe la cuenta), podemos decir que la primera entidad es una entidad dependiente por existencia de la segunda. En este caso, la entidad dependiente se considera que es de naturaleza dbil, frente a la otra que se considera de naturaleza fuerte. Una entidad dbil, carece de clave primaria, por lo que para distinguirla de otra se hace necesario recurrir a la entidad fuerte de la cual depende. Un Modelo de Datos E-R puede trasladarse a un Modelo de Datos Relacional, donde la visin del sistema de informacin se realiza por medio de tablas (Relaciones). Para ello, se siguen una serie de reglas apropiadas al caso, que explicaremos en el apartado 7

Diseo de El Modelo El modelo Entidad-Relacin

bases

de

datos: conceptual

En este captulo, y en los siguientes, explicaremos algo de teora sobre el diseo bases de datos para que sean seguras, fiables y para que tengan un buen rendimiento. La teora siempre es algo tedioso, aunque intentaremos que resulte amena, ya que es necesaria. Aconsejo leer con atencin estos captulos. En ellos aprenderemos tcnicas como el "modelado" y la "normalizacin" que nos ayudarn a disear bases de datos, mediante la aplicacin de ciertas reglas muy sencillas. Aprenderemos a identificar claves y a elegir claves principales, a establecer interrelaciones, a seleccionar los tipos de datos adecuados y a crear ndices. Ilustraremos estos captulos usando ejemplos sencillos para cada caso, en prximos captulos desarrollaremos el diseo de algunas bases de datos completas. Como siempre que emprendamos un nuevo proyecto, grande o pequeo, antes de lanzarnos a escribir cdigo, crear tablas o bases de datos, hay que analizar el problema sobre el papel. En el caso de las bases de datos, pensaremos sobre qu tipo de informacin necesitamos guardar, o lo que es ms importante: qu tipo de informacin necesitaremos obtener de la base de datos. En esto consiste el modelado de bases de datos.