practica 3. condiciones

Transcripción

practica 3. condiciones
ESCUELA POLITÉCNICA SUPERIOR.
1º GRADO DE ELECTRÓNICA. INFORMÁTICA
PRACTICA 3. CONDICIONES.
RESUMEN TEORICO
printf
Se usa para imprimir texto y expresiones por la pantalla.
printf (“He nacido el dia %d de %d de %d. Tengo %d años. Mido %.2f metros. Mi grupo sanguíneo es %c\n”, dia, mes, anno, 2010‐anno, medida, grupo); Variables
Espacio de memoria al que se le asigna un nombre, y que guarda un valor. Cada variable pertenece a un “tipo”. Este tipo indica qué
tipo de valor puede guardar la variable. Los tipos más comunes son:

int: entero de 32 bits, con signo, complemento a 2.

float y double: números reales de simple y doble precisión, respectivamente, conforme al estándar IEEE754.
Han de definirse antes de poder usarse. La definición de las variables se realiza al principio del bloque main, y antes de cualquier
orden. Así:
#include <stdio.h> int main() { int a,b=3,contador; /* tres variables enteras, una de ellas con un valor inicial de 3 */ float x; /* una variable real de simple precision */ /* aquí vendría el código que usa estas variables */ } Expresiones
Cualquier cosa que devuelva un valor. Si una expresión está compuesta únicamente de valores enteros, el resultado de dicha expresión
será un entero. Si dentro de ella hay al menos un valor real, el resultado de la expresión, será real. Dentro de una expresión, las
operaciones se realizan con una cierta prioridad: las multiplicaciones y divisiones antes que las sumas y restas.
(‐b+sqrt(b*b‐4*a*c))/(2*a) Funciones
Forma de encapsular código para poderlo usar tantas veces como queramos. Para crear una función en un programa debemos colocar
su prototipo al comienzo de éste, y su cuerpo, después de main(). Para usar nuestra función recién creada, la llamaremos con los
parámetros que queramos, dentro de una expresión.
#include <stdio.h> #include <math.h> float distancia_euclidea (float, float, float, float); int main() { float a,b,c,d; a=3.2; b=‐4.1; c=0; d=8.5; printf (“La distancia entre el punto (%f,%f) y el punto (%f,%f) es %f\n”, a, b, c, d, distancia_euclidea (a,b,c,d)); return 0; } float distancia_euclidea (float x1, float y1, float x2, float y2) { float d; d=sqrt((x2‐x1)*(x2‐x1)+(y2‐y1)*(y2‐y1)); return d; } 1
ENTRADA DE DATOS POR TECLADO
Para poder usar el teclado dentro de un programa en C, con intención de dar un valor a una variable durante la ejecución del mismo,
usaremos esta secuencia de instrucciones en el punto del programa donde queramos hacerlo:
printf (“Dame un valor para (aquí pondremos qué dato estamos esperando): “); fflush (stdin); scanf (“(aquí ponemos la secuencia de sustitución que corresponda al tipo de variable para el cual pedimos el dato)”, &(aquí ponemos el
nombre de la variable que recibirá el dato por teclado) ); El printf que aparece en la secuencia se le llama “mensaje de cortesía” y sirve para que la persona que usa el programa (a la que se le
denomina normalmente el “operador”) sepa qué dato es el que espera el ordenador que se le suministre, e invita a teclearlo.
La función fflush está normalmente asociada a ficheros (ver práctica 8). Aquí la usamos para asegurarnos de que el teclado no tiene
pulsaciones de caracteres residuales (teclas que se pulsaron pero que no fueron leídas por el programa). Esas teclas pulsadas pero no
leídas se guardan en una memoria gestionada por el propio teclado. La función fflush borra esa memoria. Así, cuando se ejecute scanf,
no leerá teclas “antes de tiempo”.
La función scanf es la que realmente lee el teclado y asigna los valores leídos a las variables que aparezcan en la llamada a esta
función.
scanf tiene en primer lugar un texto entrecomillado, en donde aparecerán las secuencias de sustitución que correspondan a los tipos de
variable que se quieran leer de teclado. Según el tipo de variable a leer, se usará una secuencia de sustitución u otra, según la siguiente
tabla (hay más secuencias en la ayuda accesible desde C-Free):
Secuencia de
sustitución
Qué lee
Tipos
admitidos para
la variable
Observaciones
%d Un número entero en formato decimal
char, short, No se hacen comprobaciones sobre si el valor introducido
puede caber dentro de la variable. Así por ejemplo, es posible
int, long pedir un valor para una variable de tipo char, pero si el
número tecleado es mayor de 127 o menor que -128, el valor
guardado en la variable será erróneo.
%f Un número real, en formato de simple
precisión
float Es posible que el valor almacenado tenga menos decimales
que aquellos que se han introducido. Para poner decimales se
usa el punto decimal, en lugar de la coma.
%lf Un número real, en formato de doble
precisión
double Misma observación que para el caso de float, si bien aquí al
haber más precisión es menos probable que haya errores en
los decimales guardados.
%c Una letra, símbolo, o carácter en general
char, short, Es necesario que, antes de pedir datos usando esta secuencia,
se haya usado la función fflush() de la forma descrita.
int, long %x Un número entero en formato hexadecimal
int, long Se pueden usar mayúsculas o minúsculas para los dígitos
A,B,C,D,E y F. No se teclea el 0x al principio.
Por ejemplo: para pedir un número entero por teclado que representa un año, y guardarlo en la variable anno, haremos algo así:
printf (“Introduce por teclado un año y pulsa Intro: “); fflush (stdin); scanf (“%d”, &anno); Se pueden pedir varios valores en un mismo scanf. Por ejemplo, para pedir tres valores que representan las longitudes de los tres lados
de un triángulo, y guardarlos en tres variables enteras llamadas a, b y c, podemos hacer esto:
printf (“Introduce los valores de los tres lados de un triangulo, separados por espacios: “); fflush (stdin); scanf (“%d%d%d”, &a, &b, &c); Hay que recordar una cosa: cuando se use la tecla F7 para ejecutar paso a paso un programa, en el momento en que se llegue a un
scanf y se pulse de nuevo F7, se verá que la línea celeste no avanza. Esto pasa porque el programa está ahora esperando a que se
tecleen los datos que se han pedido, así que hay que hacer clic en la ventana de salida (la consola de salida) donde se está ejecutando
nuestro programa, teclear los datos pedidos y pulsar Intro. En ese momento, si se tiene en pantalla las dos cosas: consola y C-Free, se
verá que la línea celeste avanza a la siguiente instrucción. Entonces es cuando se puede volver a minimizar la consola y seguir
ejecutando desde C-Free con F7 como siempre.
2
EJERCICIOS A REALIZAR EN LABORATORIO
EJERCICIO 1. Escribe un programa que pida un año por teclado e imprima un mensaje indicando si el año introducido es bisiesto o
no. Un año se dice que es bisiesto si es múltiplo de 4 y no es múltiplo de 100, o bien si es múltiplo de 400. Usa el operador % que
calcula el resto de una división entera. Por ejemplo, la expresión a%4 da como resultado el resto de la división entera del valor de la
variable a entre 4 (la variable debe ser int, no puede ser float).
EJERCICIO 2. Escribe un programa que pida por teclado un número de día (1 a 31) y un número de mes (1 a 12), e indique por
pantalla a qué estación del año corresponde esa fecha. Usa la siguiente tabla para recordar el comienzo y fin de cada estación:
Estación
Comienza
Termina
Primavera
21 de Marzo (21/3)
20 de Junio (20/6)
Verano
21 de Junio (21/6)
20 de Septiembre (20/9)
Otoño
21 de Septiembre (21/9)
20 de Diciembre (20/12)
Invierno
21 de Diciembre (21/12)
20 de Marzo (20/3)
EJERCICIO 3. Tres segmentos de longitudes a,b y c pueden formar un triángulo si se cumple que la suma de las longitudes de dos
segmentos cualesquiera es mayor o igual que la del tercero, es decir, si se cumplen estas tres condiciones: a+b≥c, b+c≥a y c+a≥b.
Escribe un programa que pida por teclado las longitudes de tres segmentos e imprima por pantalla si dichos segmentos pueden o no
formar un triángulo.
EJERCICIO 4. Usa como plantilla el fichero p3ej4.c. Escribe una función que calcule la nota final de un alumno en la asignatura de
Informática usando la evaluación continua. La función, a la que llamaremos “calificar”, toma como argumentos las calificaciones de
teoría en los tres controles WebCT (tres valores de tipo float), la calificación de prácticas en el primer y segundo control WebCT
(otros dos valores float), y la calificación en el examen práctico (también float). En total, nuestra función tendrá 6 argumentos de tipo
float.
La función sumará por una parte las calificaciones obtenidas en la parte teórica de la asignatura (ver TEMA 0 de teoría) y por otra, las
de la parte práctica. Si alguna de las sumas no supera el mínimo establecido, la función devolverá el valor -1. Si ambas sumas superan
el mínimo, se sumarán para obtener la nota final y se devolverá dicha nota como resultado de la función.
Para probar esta función, completa el programa que se suministra con la plantilla para que lea por teclado las diferentes notas
parciales. En total, tendrá que leer 6 notas por teclado. El programa usará la función calificar pasando como parámetros todos los
valores leídos desde teclado, para hallar la nota final. Si el resultado de la función es -1, el programa mostrará un mensaje en pantalla
diciendo “NO APTO PARA LA EVALUACION CONTINUA”. En otro caso, mostrará el valor devuelto, correspondiente a la nota
obtenida en la evaluación continua.
EJERCICIO 5. Modifica el programa p3ej4.c del ejercicio anterior para que además de mostrar la nota final, muestre la calificación
en formato texto: SUSPENSO para calificaciones menores que 5, APROBADO para calificaciones entre 5 y 7 (sin llegar a 7),
NOTABLE para calificaciones entre 7 y 9 (sin llegar a 9), y SOBRESALIENTE para calificaciones entre 9 y 10.
Además, si la calificación del alumno es mayor o igual que 9.5 puntos, se imprimirá el mensaje “EL ALUMNO OPTA A
MATRÍCULA DE HONOR”.
3
EJERCICIOS PARA RESOLVER EN CASA
EJERCICIO 6. Usaremos una condición booleana para mejorar el ejercicio de resolución de ecuaciones de segundo grado escrito en
la práctica 1. En este caso, necesitamos discernir si la ecuación tendrá soluciones reales o no. Para ello se emplea el discriminante. El
discriminante es el radicando de la raíz cuadrada de la fórmula para las soluciones de la ecuación de segundo grado, es decir, la
expresión b2-4ac. Llamemos d a la variable de tipo float que guarda el valor calculado de este discriminante.
Si d es mayor o igual que 0, eso significa que la raíz cuadrada de d es un valor real, con lo que las soluciones de la ecuación son reales
y se pueden calcular con la fórmula conocida.
En cambio, si d es menor que 0, la raíz cuadrada de d es un número imaginario, con lo que las soluciones de la ecuación serán
números complejos. El lenguaje C no puede operar directamente con números complejos, así que terminamos el programa con un
mensaje indicando que no es posible resolver la ecuación dada.
Así, para que el programa funcione bien en todos los casos, habrá que discernir entre las dos posibilidades para el valor de d, y hacer
una cosa u otra en función de ese valor.
Modifica el programa p1ecuacion.c que hiciste en la práctica 1 de la siguiente forma: escribe una función a la que llamaremos “disc”.
Esta función se encargará de calcular el discriminante. Tomará como parámetros los valores de a,b y c (todos de tipo float), y
devolverá como resultado el valor del discriminante (también float). Incorpora esta función al programa de cálculo de las raíces de
una ecuación de segundo grado de la práctica 1, concretamente en la línea en la que se calcula el valor de la variable raiz.
EJERCICIO 7. Partimos del ejercicio anterior: usa la construcción if para que el cálculo de la raíz del discriminante, de las dos
soluciones, y la posterior impresión en pantalla de éstas, sólo se efectúe si el valor del discriminante es igual o mayor que 0, y en caso
contrario, en lugar de calcularse e imprimirse, aparezca un mensaje de error en pantalla. Recuerda que si el discriminante de la
fórmula de la ecuación de segundo grado es menor que 0, su raíz cuadrada no existe (en el conjunto de los números reales) y por tanto
decimos que la ecuación no tiene soluciones reales. El lenguaje C no puede operar con números complejos, sólo con números reales.
Prueba la nueva versión con estos valores: a=1, b=2, c=4.
EJERCICIO 8. Nos han encargado piratear “educar” el nuevo sistema de TV por satélite Pijital Mús. Este servicio consta de un
decodificador y una tarjeta de abonado. El decodificador envía a la tarjeta una serie de comandos. Para cada comando (un valor
numérico de 8 bits) que envía el decodificador, la tarjeta debe contestar con una respuesta, que también es un valor numérico de 8
bits. Si la tarjeta responde correctamente a una serie de comandos que el decodificador le envía, se dice que la tarjeta está autorizada,
y el decodificador comienza a descodificar todos los canales. Si alguna de las respuestas que da la tarjeta no es la esperada, la tarjeta
se dice que está no autorizada, y el decodificador sólo podrá mostrar los canales libres (FTA).
Después de realizar una difícil labor de ingeniería inversa, se ha llegado a determinar la relación entre comando enviado por el
decodificador, y respuesta que debe enviar la tarjeta. Esta tabla la resume:
Comando desde el decodificador
Respuesta de la tarjeta
0 1 2 5 8 Resto de comandos 3 3 4 9 7
0
La tabla se interpreta de la siguiente forma: si el comando enviado por el decodificador es 0 ó 1, la tarjeta debe responder con 3. Si es
2, responde con 4; si es 5, responde con 9; si es 8, responde con 7; y si no es ninguno de los comandos anteriores, responde con 0.
Nuestra labor consiste en crear un clon de la tarjeta que se comporte igual que la tarjeta de abonado original, es decir, que responda
correctamente a cada uno de los comandos del decodificador según lo expuesto en la tabla.
Desarrollo del ejercicio:
Descomprime el fichero pijital_mus.zip . Aparecerá una carpeta llamada pijital_mus con varios
ficheros dentro de ella. Uno de ellos se llama pijital_mus.cfp . Es un fichero C-Free Project File. Haz
doble clic y se abrirá automáticamente dentro de C-Free.
En la parte derecha de la pantalla debe aparecer una columna con una lista de los ficheros de este
proyecto. Algo parecido a la figura de la derecha:
Si no aparece ninguna columna ni ventana, usa el menú View, opción File Tree Window para mostrar
la lista de ficheros.
Dentro de esa ventana, haz doble clic en tarjeta.c y se abrirá el editor de código C en la ventana principal de C-Free. Sigue las
instrucciones que verás escritas en ese fichero para escribir el código del ejercicio.
Para comprobar que el ejercicio es correcto, pon un punto de ruptura en la primera línea de código de la función tarjeta() y
ejecútalo con F9. Si no hay errores, el programa comenzará a ejecutarse. Preguntará si se está probando este ejercicio (el 8) o el
siguiente (el 9). Elegimos 8 y veremos cómo el decodificador envía una serie de comandos numéricos a nuestra función tarjeta. Es
decir, el decodificador llamará a la función tarjeta unas cuantas veces, cada vez con un comando distinto (o no), y cada vez que esto
ocurra, podremos examinar la ejecución paso a paso con F7, comprobando si para el comando recibido se está generando la respuesta
adecuada. El programa además mostrará por pantalla si la respuesta recibida desde la tarjeta es la esperada o no. Se pueden ver los
mensajes que el decodificador genera si se hace clic en la ventana de la consola de salida. Después de que se termine de ejecutar la
función tarjeta por última vez no volverá a aparecer la línea celeste, así que la forma de terminar el programa es irse a la consola, leer
la respuesta final del decodificador, y pulsar una tecla.
4
NOTA: si en alguna de las ocasiones en las que se comienza a ejecutar paso a paso la función tarjeta() no nos interesa hacer la
ejecución paso a paso, sino que queremos “hacer avance rápido” hasta la próxima vez que se llama a la función, pulsad F9. Esto es
útil si sabemos que nuestra función falla solamente en un comando concreto, y es solamente ese el que queremos ejecutar paso a paso
para averiguar por qué falla.
EJERCICIO 9. Los responsables de Pijital Mús se han percatado de nuestra maniobra, y han modificado la forma en la que los
decodificadores se comunican con las tarjetas. Ahora para que la tarjeta envíe una respuesta no basta con saber qué comando se ha
enviado, sino que hay que saber además cuál fue el comando que se envió justo antes.
La nueva tabla, recopilada por nuestros expertos en ingeniería inversa, es la siguiente:
Primer comando desde el decodificador
Segundo comando desde el decodificador
Respuesta de la tarjeta
El contenido de esta tabla se interpreta ahora de la siguiente forma:
3
4
2
9
6
3
4
8
4
5
10
Resto de comandos 1
0 
Los comandos 3, 4 y 10 se comportan como en el ejercicio anterior: si el decodificador envía alguno de estos comandos, la
tarjeta debe responder de la forma adecuada (devolviendo 2, 9 ó 1, respectivamente). No hay que esperar a un segundo
comando.

Los comandos 6 y 8 son los problemáticos. Después del primer comando de la serie, la tarjeta debe responder con 0. Si el
siguiente comando recibido es el segundo de la serie, entonces la tarjeta responde con el valor adecuado según la tabla. Por
ejemplo: si el decodificador envía el comando 6, la tarjeta en principio responde con 0, pero si justo después del comando 6
se envía el 3, la tarjeta debe responder con 4. Es decir, cuando se recibe un 3 esta vez no se devuelve un 2, ya el anterior fue
un 6. Análogamente se procederá con el mensaje 8.

Fíjate que si el decodificador envía un 6, y después envía un 4, la tarjeta debe responder con 0 al primer comando (el 6) y 9
al segundo (el 4). Otro ejemplo: si el decodificador envía un 6, después otro 6, y después un 3, debe responder con 0, 0, y 4.
Otro más: si envía un 6, un 3, y un 3, la tarjeta responderá con 0, 4, y 2.

Si se envía un comando que no es ninguno de los listados en la tabla, la tarjeta, como en el caso anterior, devuelve 0.
Este ejercicio se realiza igual que el anterior, escribiendo el código para la función “tarjeta”. En la variable anterior se guarda el
comando que el decodificador envió justo antes del actual. Esta variable es static ya que tiene que conservar el valor que fue reibido
por la tarjeta en la anterior llamada.
Al ejecutar de nuevo el programa, cuando se nos pregunte, hay que elegir que el ejercicio que queremos comprobar es el 9.
EJERCICIO 10. Abre el programa p3e10.c . Es un programa muy similar a p2e12.c, donde había que escribir una función que
implementa un generador de números pseudoaleatorios. En ella hay una variable semilla, que toma un valor inicial, y se va
actualizando cada vez que se llama a la función.
Queremos ahora ampliar esa función para que se permita la posibilidad de cambiar el valor de la semilla al llamar a la función, para
así comenzar la secuencia aleatoria en cualquier punto que nos interese (ver ejercicio 12 de la práctica 2 para más detalles sobre los
generadores de números pseudoaleatorios).
Para ello, ahora la función aleatorio() toma un argumento n, de tipo entero. Al ejecutarse la función se debe comprobar el valor de n.
Si éste es 0, no se modifica el valor de semilla y la función calcula el valor aleatorio como en la versión de la práctica 2, pero si el
valor de n es distinto de 0, se actualizará la variable semilla con el valor de n, antes de seguir con los cálculos de la función.
EJERCICIOS DE PROGRAMACIÓN ADICIONALES, DE CARÁCTER VOLUNTARIO, PARA SEGUIR
PRACTICANDO O PARA SABER MÁS.
EJERCICIO 11. Repite los ejercicios 8 y 9 usando la estructura condicional múltiple switch-case en lugar de if-else if.
5

Documentos relacionados