INGENIERIA INFORMATICA Lenguajes de Programación E.P.S. PRACTICAS de Lenguaje C Curso 02-03 Tema: Entrada y Salida Simple Lenguajes de Programación Entrada y Salida Simple ENTRADA / SALIDA SIMPLE, TIPOS DE DATOS SIMPLES Consideremos la estructura básica de un programa C: #include<stdio.h> int main() /* Programa prueba */ { printf(“hola mundo”); return 0; } Los símbolos que indican los comentarios son “/*” y “*/”. Los símbolos que indican el inicio y final de bloque de programa son las llaves “{“ y “}” . A partir de aquí vamos a ir completando este esqueleto poco a poco con nuevas funcionalidades. La primera de ellas son las variables. 1 Constantes y variables 1.1 Declaración de variables Dentro de cada programa siempre van a existir dos tipos de información bien diferenciados: los datos y las instrucciones. Ya conocemos la estructura básica de un programa, así que es el momento de conocer de qué datos se dispone para construir programas. Cuando necesitamos un dato para un programa es necesario definir una variable (una sola vez!). En lenguaje C, debemos definir una variable junto con su tipo: int main() { int num1, num2, total; num1=20; num2=37; total=num1+num2; printf(“ suma de num1 y num2 es %d”, total); return 0; } En el ejemplo anterior, para sumar dos enteros y guardar su resultado, hemos definido tres variables enteras (int). Veamos otro ejemplo(nos referiremos a este programa en el resto de la pr’actica como prac1_1.c): #define PI 3.141592 int main() { char caracter; /* declaramos un carácter */ int entero; /* definimos un entero */ float real; /* definimos un valor real */ caracter =’a’; entero = 15; real = PI; printf(“%c es un caracter \n”,caracter); printf(“%d es el entero y %f es el real”, entero, real); return 0; } Prácticas Pág. 2 Lenguajes de Programación Entrada y Salida Simple En el programa se han definido variables de tres tipos de datos: caracteres, enteros y reales (floats en C). Existen algunos tipos de datos más, pero éstos ya irán apareciendo a lo largo del curso. Los tipos de datos sencillos nos delimitan unos valores máximos y mínimos para cada variable que definamos. Por ejemplo, los tipos más sencillos tienen los siguientes límites: Identificador tipo de Significado Rango de valores (en un PC) int entero -32768 a 32767 unsigned entero sin signo 0 a 65535 char carácter -128 a 128 unsigned char carácter sin signo 0 a 255 float real 3’2 E+/– 38 División de los tipos de datos Es muy importante tener en cuenta estos límites ya que si queremos almacenar un valor mayor que el límite superior, en realidad, ¡estaremos guardando un valor negativo!. Para que los programas resulten claros al leerlos, todas las variables que se utilizan se suelen definir justo después de la 1ª llave del programa (main) al principio del programa. Todas las variables se van definiendo al inicio del código y se las va acompañando de un pequeño comentario que explica el uso que se va a hacer de la misma a lo largo del programa. Ejercicio 1: Define la variable “ char caracter” como “char Caracter” y compila el programa. ¿Qué ocurre?. ¿A qué crees que se debe? Otra de las novedades que introduce el programa anterior es el definir constantes con la directiva #define. Esta directiva define una serie de símbolos alfanuméricos que se sustituyen por otra cadena. En el ejemplo, antes de compilar el programa el propio compilador sustituirá la cadena “PI” por el valor “3’141592” en todos los lugares donde “PI” aparezca. La ventaja de utilizar constantes de este tipo es la mayor legibilidad de los programas. Si el programa utiliza la constante PI para implementar fórmulas como la de la superficie del círculo, siempre serán más claras si se lee la constante como una palabra. Existen otras ventajas que se irán viendo más adelante, ya que esta directiva permite cambiar cualquier cadena por otra. 1.2 Inicialización y asignación de variables. Al declarar una variable lo único que estamos haciendo es reservar memoria. Sin embargo, en principio, no tenemos ningún control sobre el valor que haya en esta posición de memoria. Aunque TurboC da unos valores por defecto, para evitar errores, es imprescindible asignar un valor inicial a las variables antes de utilizarlas. Ejercicio 2: Usa el watch del Debugger para averiguar los valores por defecto de las variables del programa prac1_1.c. Podemos inicializar las variables en la misma línea donde las hemos declarado: int entero=27; /* valor inicial del cálculo*/ O bien asignarles el valor de otra variable ya existente: int n1,n2; n1=2; Prácticas Pág. 3 Lenguajes de Programación Entrada y Salida Simple n2=n1; En este caso hay que procurar que los tipos coincidan, aunque TurboC admite algunas conversiones automáticas de tipos de datos. Ejercicio 3: Cambiad la inicialización de las variables entero y real del programa prac1_1.c por: a) entero = PI; real = 15; b) entero = 15; real = entero; compilad y depurad (debug) el programa para averiguar que valores tienen. 2. Entrada / Salida Simple 2.1 Salida: printf Para utilizar esta función hay que incluir la librería standard #include <stdio.h> Ya hemos visto un poco para qué sirve esta función. Pero veámosla con un poco más de detalle. Ya sabemos que sirve para enviar mensajes hacia la pantalla, como por ejemplo: printf(“ Esto es un mensaje”); También sirve para imprimir el valor de una variable con su correspondiente formato: printf(“ suma de num1 y num2 es %d”, total); Para imprimir el valor de la variable total (función printf) es necesario utilizar una fórmula del tipo “%d”. Ese “%” ya indica que la siguiente letra que venga se refiere al tipo de variable que se quiere imprimir. En este caso, se quiere imprimir la variable total que es un entero. Tenemos los siguientes formatos para enviar una variable a la pantalla: Carácter d i o u x X f e E g G c s % Argumento entero entero entero entero entero entero real real real real real carácter cadena de caracteres ninguno Salida resultante Entero con signo en base decimal Entero con signo en base decimal Entero con signo en base octal Entero sin signo en base decimal Entero con signo en base hexadecimal con letras mayúsculas Entero con signo en base hexadecimal con letras minúsculas Número real con signo Número real con signo usando notación e Número real con signo usando notación E Número real con signo en formato e ó f, de tamaño corto Número real con signo en formato E ó f, de tamaño corto Un cáracter individual Imprimir cadenas de caracteres Imprime el símbolo % Tabla de especificadores de formato de tipos para printf. Para borrar la pantalla de Salida podéis utilizar el comando clrscr (). Necesitaréis incluir la librería conio.h Prácticas Pág. 4 Lenguajes de Programación Entrada y Salida Simple Ejercicio 4: Probad el siguiente ejemplo y justificar los resultados #include <stdio.h> int main() { printf("El valor 92 usando el tipo de campo d es %d. \n", 92); printf("El valor 92 usando el tipo de campo i es %i. \n", 92); printf("El valor 92 usando el tipo de campo u es %u. \n", 92); printf("El valor 92 usando el tipo de campo o es %o. \n", 92); printf("El valor 92 usando el tipo de campo x es %x. \n", 92); printf("El valor 92 usando el tipo de campo X es %X. \n", 92); printf("El valor 92.0 usando el tipo de campo f es %f. \n", 92.0); printf("El valor 92.0 usando el tipo de campo e es %e. \n", 92.0); printf("El valor 92.0 usando el tipo de campo E es %E. \n", 92.0); printf("El valor 92.0 usando el tipo de campo g es %g. \n", 92.0); printf("El valor 92.0 usando el tipo de campo G es %G. \n", 92.0); printf("El valor 92 usando el tipo de campo c es %c. \n", 92); printf("El caracter '9' usando el tipo de campo c es %c. \n", ‘9’); printf("La cadena 92 usando el tipo de campo s es %s. \n"," 92"); return 0; } ¿Qué ocurre si el formato y la variable a imprimir no coinciden?. Probad: printf("El valor 92 usando el tipo de campo d es %d. \n", 92.0); printf("El valor 92.0 usando el tipo de campo f es %f. \n", 92); El símbolo al final del texto (“\n”) sirve para que la siguiente cadena que se imprima se escriba en una nueva línea. Ese carácter se conoce con el nombre de “newline”. Puede haber más de un especificador de formato por un mismo texto de printf. Sin embargo, no puede haber menos argumentos que especificadores de formato. printf (“ esto es un texto %c mas texto %d \n”, ‘a’, var2); especificadores argumentos El 1er "%" va a buscar a la 1ª variable después de cerrar comillas, el segundo “%”, la segunda y así sucesivamente: printf(“%d es el entero y %f es el real”, entero, real); 2.2 Entrada del usuario: scanf Para poder interaccionar con el usuario, existen una serie de funciones ya definidas: scanf, getch, getche... Ejemplo: #include <stdio.h> /* recogiendo la entrada del usuario */ int main() { float valor; /* un número introducido por el usuario */ printf(“introduzca un numero => “); scanf(“%f”, &valor); Prácticas Pág. 5 Lenguajes de Programación Entrada y Salida Simple printf(“El valor es => %f \n”, valor); return 0; } El formato de la función scanf es: scanf(“%f ”,&valor); - %f : especificador de formato como el de printf. No puede haber menos argumentos que especificadores de formato. A diferencia del printf no admite texto. - &valor: variable donde se guardará el valor entrado por el usuario. SIEMPRE ha de ir precedida del símbolo “&”. - Necesita la librería stdio.h Ejercicio 5: Modificad el programa prac1_1.c para que el numero entero y el float sean introducidos por el usuario. ¿Qué ocurriría si el usuario introdujese un float en lugar de un entero?. Ejercicio 6: Utilizad las funciones getch() y getche() para leer el carácter del programa prac1_1.c desde el teclado. Utilizad el Help del TurboC para averiguar el formato de estas dos funciones. Recordar incluir el código de este y todos los programas que realiceis en vuestra práctica. 3 Operadores 3.1 Operaciones aritméticas Los operadores representan las operaciones más simples que se pueden aplicar sobre las variables. Los más sencillos son los operadores aritméticos. Símbolo + – * / % Significado Suma Resta Multiplicación División Módulo Ejemplo r = 3 + 5 ( valdrá 8) r = 5 – 3 ( valdrá 2) r = 5 * 3 ( valdrá 15) r = 10 / 2 ( valdrá 5) r = 3 % 2 (valdrá 1) Tabla de operadores aritméticos Todas las operaciones pueden realizarse tanto sobre flotas como sobre enteros excepto la operación Modulo (resto de la división entera) que sólo puede realizarse entre dos enteros. Ejercicio 7: Probad este programa. (obviamente tendreis que añadir algunas líneas de código para que funcione) int num1=2, num2= 3, res_int; float numf1=2.0, numf2=3.0, res_float; res_int= num1/num2; rest_float=numf1/numf2; printf(“res1= %d \n”,res_int); printf(“res2= %f \n”,res_float); Prácticas Pág. 6 Lenguajes de Programación Entrada y Salida Simple ¿Qué diferencia se observa entre la división entre enteros y entre reales?. Modificad el código como sigue: res_int = numf1/numf2; rest_float = num1/num2; ¿Cuál es el resultado?. ¿A qué crees que es debido?. Probad ahora con: a) rest_float=num1/numf2; b) rest_float=numf1/num2; 3.2 Prioridades Si tenemos una expresión como: X=5+4/2 X= 9 / 2 = 4’5 X= 5 + 2 = 7 ¡¡Obtenemos dos posibles maneras de interpretar la misma expresión!!. Para evitar esta ambigüedad se define un orden a la hora de ejecutar las operaciones aritméticas. De forma que si tenemos en cuenta la tabla: Prioridad Operación Primera () Segunda Negación (asignar un número negativo) Tercera Multiplicación, división (*, / ) Cuarta Suma, resta (+, - ) Tabla de prioridades de los operadores en las expresiones. Sólo existe una manera de resolver la anterior expresión X= 5 + 4 / 2 = 5 + 2 = 7 Si nos interesaba la otra manera de resolver la operación deberemos utilizar los paréntesis: X= (5 + 4) / 2 = 9 / 2 = 4’5 Ejercicio 8: Realizad un programa que determine el resultado de las siguientes operaciones: a) Y = X + 12*( X * 2 ) – 1 c) Y 2 x4 b) Y = X + 12 / X * ( X – 1 ) d) Y x 3 x2 e) Y x4 x * ( x 3) Imprimid el resultado por pantalla. Probad con los valores de X= 1 y 2 para comprobar que la operación se está realizando correctamente. Cambiad el programa para recoger los valores de la fórmula desde el teclado. ¿Qué ocurre si introducimos el valor X= 2? En la siguiente práctica veremos como podemos evitar este tipo de errores. El resultado de una operación aritmética puede ser asignado a una de las variables que intervienen en el cálculo. Así en el programa anterior, la asignación X= X + 12 / X * ( X – 1 ) sería válida. Prácticas Pág. 7 Lenguajes de Programación Entrada y Salida Simple 3.3 Operadores de asignación compuestos El lenguaje C es bastante famoso por sus atajos a la hora de escribir programas. Veamos algunos ejemplos sencillos referidos a expresiones. respuesta = respuesta + 5; es una expresión bastante larga. En lenguaje C se puede expresar de una forma mucho más compacta: respuesta += 5; Desde luego, la operación es la misma de antes. Sólo tenemos que escribir mucho menos. En esta tabla, están el resto de operaciones al estilo: Símbolo += -= *= /= %= Ejemplo X += Y X-=Y X *= Y X /= Y X %= Y Significado X=X+Y X=X–Y X=X*Y X=X/Y X=X%Y Tabla operadores de asignación compuestos. Ejercicio 9: Teniendo en cuenta la fórmula F = (9 / 5) C + 32 Definid la variable C como un entero y también como un real (float C2) e implementad el programa que convierte de grados Celsius a Farenheit utilizando la fórmula anterior. Los datos serán introducidos por el usuario. Hemos de responder a las siguientes preguntas: Prácticas - ¿Qué variables necesitamos? - ¿Qué valores iniciales se les va a dar? - ¿Cómo pedimos los datos al usuario? - ¿Cómo implementar la expresión? - ¿Dónde guardamos el resultado? - ¿Cómo hay que imprimir el resultado? Pág. 8 Lenguajes de Programación Entrada y Salida Simple Agradecimientos: Esta práctica está basada en las prácticas de Ingeniería informática realizadas por el Dept. Informàtica, Escola Tècnica Superior d'Enginyeria, Universitat Autònoma de Barcelona Prácticas Pág. 9