ESCUELA TÉCNICA SUPERIOR DE INGENIERÍA INDUSTRIAL FUNDAMENTOS DE INFORMÁTICA PARCIAL FEBRERO 2007 TEORÍA (6 puntos = 2 p + 2 p + 2 p) Apellidos: Nombre: Grupo: Doy autorización al profesor para publicar mi nota en Internet PROBLEMA (6 puntos) Escribir un programa completo (2 puntos) y las dos funciones propuestas a continuación (2 puntos cada una) que permitan calcular el importe total de una factura. Cada Factura estará compuesta por: ¾ Numero de factura: automático, la primera factura tendrá el numero 1, y las siguientes, numeros consecutivos (no se leerá por teclado). ¾ Iniciales del cliente: Se obtendrán llamando a una función, de nombre finiciales_cliente(…), que deberá leer por teclado el nombre completo de una persona, con el formato: nombre apellido1 apellido2 El segundo apellido terminará con un carácter de nueva línea. La función deberá devolver (sin escribir en pantalla) las tres iniciales del nombre leido por teclado. ¾ Lineas que componen la factura: la lectura por teclado y el procesamiento de dichas líneas, se realizará mediante la llamada a una función, de nombre flineas_factura(…), que se encargará de leer por teclado y/o escribir en pantalla los siguientes datos: • • • • Codigo de producto: numero natural dentro del rango 1000..9999; se leerá por teclado hasta que se encuentre dentro de dicho rango. Cantidad: numero entero leído por teclado Precio: numero real leído por teclado (si el iva) Total: numero real resultado de multiplicar la Cantidad por el Precio (sin el iva). La lectura de líneas de la factura terminará cuando se introduzca un cero como valor del Código de producto. Suponer que cada factura tendrá una línea con datos, como mínimo. La función deberá devolver como valor de retorno (y sin escribir en pantalla) el Total sin iva correspondiente a las líneas leídas, que será un numero real que se calculará sumando todos los totales de las líneas de la factura. ¾ Total sin iva: se escribirá el valor devuelto por la función anterior. ¾ Iva: no se leerá por teclado, se mostrará siempre el 16% del Total sin iva. ¾ Total con iva: se calculará y mostrará automáticamente, sumando el Iva (16%) al Total sin iva de la factura en curso. El programa deberá comenzar siempre por la factura numero 1. Una vez calculado y mostrado el Total con iva de la factura en curso, se mostrará por pantalla el mensaje: "¿desea realizar otra factura (S/N)?: " y se leerá por teclado la respuesta del usuario (se deberá admitir solamente las letras 'S' o 'N' tanto en mayúsculas como en minúsculas). En caso de respuesta afirmativa, se procederá a construir otra factura nueva, con un Número de factura siguiente al de la factura anterior. EJEMPLO (el texto que se encuentra en negrita corresponde a datos que deberá teclear el usuario. El resto será texto y datos que deberá escribir el programa) Nº factura: 1 Nombre cliente: Juan García Romero Iniciales: JGR Lineas de la factura: codigo producto: 321 codigo producto: 3221 cantidad: 2 codigo producto: 9999 cantidad: 1 codigo producto: 0 Total sin IVA: 27.780000 euros IVA 16%: 4.444800 euros Total con IVA: 32.224800 euros ¿Otra factura (S/N)?: S Nº factura: 2 ……….. precio: 10.5 precio: 6.78 total: 21.00 euros total: 6.78 euros /* Una posible solución al examen parcial de Fundamentos de Informática de Febrero de 2007 */ #include <stdio.h> #include <conio.h> void finiciales_cliente(char &ini1, char &ini2, char &ini3); float flineas_factura(); int main () { char ini1,ini2,ini3, otra_vez; float total_sin_iva=0.0; unsigned num_factura=0; do{ num_factura++; printf("\nNumero factura: %u",num_factura); finiciales_cliente(ini1,ini2,ini3); printf("Iniciales: %c%c%c\n",ini1,ini2,ini3); printf("Lineas de la factura:\n"); total_sin_iva += flineas_factura(); printf("\nTotal sin IVA: %f",total_sin_iva); printf("\nIVA: %f",total_sin_iva*0.16); printf("\nTotal con IVA: %f",total_sin_iva*1.16); printf("\n¿ Otra factura (S/N)?: "); scanf(" %c",&otra_vez); }while(otra_vez=='S' || otra_vez=='s'); getch(); return 0; } void finiciales_cliente(char &ini1, char &ini2, char &ini3) { char letra; printf("\nIntroduce el nombre :"); scanf("%c",&letra); ini1=letra; while(letra!=' ') scanf("%c",&letra); scanf("%c",&letra); ini2=letra; while(letra!=' ') scanf("%c",&letra); scanf("%c",&letra); ini3=letra; while(letra!='\n') scanf("%c",&letra); } float flineas_factura() { float suma_total=0,total_producto, precio; int codigo, cantidad; printf("\ncodigo producto :"); scanf("%d",&codigo); while(codigo!=0) { while( !(codigo>=1000 && codigo<=9999) ) { printf("\ncodigo producto :"); scanf("%d",&codigo); } printf("cantidad: "); scanf("%d",&cantidad); printf("precio: "); scanf("%f",&precio); total_producto = cantidad * precio; printf("total: %f",total_producto); suma_total += total_producto; printf("\ncodigo producto :"); scanf("%d",&codigo); } return suma_total; } ESCUELA TÉCNICA SUPERIOR DE INGENIERÍA INDUSTRIAL FUNDAMENTOS DE INFORMÁTICA PARCIAL FEBRERO 2008 TEORÍA (5 puntos ) Apellidos: Nombre: Grupo: El centro de detección de vida extraterrestre inteligente cree haber detectado mensajes codificados emitidos desde un planeta cercano al sistema solar. Se sospecha que los seres de dicho planeta tienen 2 dedos en cada mano, suposición que cobra mayor peso ya que parece que expresan los números en base cuatro. Todos los mensaje detectados tienen un formato similar igual al siguiente: orden-numero donde orden es una secuencia de letras del abecedario, de tamaño indeterminado, terminada con un guión (-), y numero es un valor numérico expresado en base 4, constituido por no más de 5 dígitos. El futuro del planeta tierra está en sus manos, ya que debe hacer un programa en C que analice esos mensajes cifrados. Dicho programa leerá por teclado mensajes con ese formato, uno por cada línea, y buscará si en alguno de ellos aparece la orden de ‘atacar la tierra’, y en caso afirmativo, conocer con antelación cual es el continente elegido para iniciar el ataque, sabiendo que la orden de atacar se expresa mediante la secuencia consecutiva de letras “atac”, y que ésta iría insertada dentro de la orden del mensaje. Para conocer el continente elegido, hay que convertir el numero a base 10, y determinar dentro de qué rango de valores se encuentra (en base 10), sabiendo que: [0..199] Æ Europa [600..799] Æ Oceanía [200..399] Æ Asia [800..1023] Æ América [400..599] Æ Africa Se debe escribir el programa completo, función main() incluida. El programa leerá mensajes por teclado hasta que expresamente se desee terminar, o hasta que se encuentre un mensaje de ataque. Se deben usar las funciones que se estimen adecuadas, pero como mínimo se exigen dos: - una función llamada convertir_a_b10 que reciba como parámetro de entrada y salida un número en base 4 y lo convierta a base 10. La función no leerá nada por teclado ni escribirá nada por pantalla. - una función llamada escribe_continente que reciba como parámetro de entrada un número en base 10 (supuestamente dentro del rango [0..1023]) y que escriba en pantalla el continente que representa dicha valor (en función de la información sobre los continentes dada anteriormente). /* Una solución al examen parcial de Fundamentos de Informática de Febrero de 2008 */ #include <stdio.h> #include <math.h> void convierte_a_b10(int &numero); void escribe_continente(int numero); int hay_ataque(); int main() { int numero; char seguir; do{ printf("\nIntroduce ORDEN-NUMERO: "); if (hay_ataque()) { scanf("%d",&numero); convierte_a_b10(numero); printf("El ataque sera en "); escribe_continente(numero); } else printf("\nNo hay ataque"); printf("\nOtro (s/n)? "); fflush(stdin); scanf("%c",&seguir); }while(seguir=='s'); return 0; } void convierte_a_b10(int &numero) { int b10=0,pos=0,cifra,num; num=numero; while(num>0) { cifra=num%10; num/=10; b10+=cifra*(int)pow(4,pos); pos++; } numero=b10; } void escribe_continente(int numero) { if (numero>=0 && numero <=199) printf("Europa"); else if (numero>=200 && numero <=399) printf("Asia"); else if (numero>=400 && numero <=599) printf("Africa"); else if (numero>=600 && numero <=799) printf("Oceania"); else if (numero>=800 && numero <=1023) printf("America"); } int hay_ataque() { char letra; int ataque=0; scanf(" %c",&letra); while(letra!='-') { if (letra=='a') { scanf("%c",&letra); if (letra=='t') { scanf("%c",&letra); if (letra=='a') { scanf("%c",&letra); if (letra=='c') { ataque=1; scanf("%c",&letra); } } } } else scanf("%c",&letra); } return ataque; } ESCUELA TÉCNICA SUPERIOR DE INGENIERÍA INDUSTRIAL FUNDAMENTOS DE INFORMÁTICA PARCIAL FEBRERO 2009 TEORÍA (5 puntos ) Apellidos: Nombre: Grupo: Escribe un programa completo que pida dos números naturales que corresponden a un mes y un año e imprima por pantalla el calendario que corresponde a dicho mes. Una vez mostrado el calendario de dicho mes, el programa preguntará si se quiere repetir el proceso. Para saber el día de la semana en el que cae el primer día del mes en cuestión se puede utilizar la congruencia de Zeller, que viene dada por la siguiente expresión: dia_semana= (700 + (26 * A-2) / 10 + dia + B + B /4 + C / 4 –2*C ) % 7 Donde los valores de A, B y C son vienen dados por: A= B= C= Si mes <=2 mes+10 (año –1) % 100 (año –1) / 100 Si mes >=3 mes –2 año % 100 año / 100 El rango de dia_semana será de 0 a 6, donde 0 indica Domingo, 1 Lunes, 2 Martes, y así sucesivamente. La formula dada es sólo apropiada para el calendario gregoriano que fue adoptado a partir del 14 de septiembre de 1752. Para realizar este programa se deben tener en cuenta los siguientes aspectos: 1. Cuando se lean los valores del mes y del año, se debe forzar a que el mes esté entre 1 y 12 y que el año sea mayor que 1752. En caso de que no lo sean deben preguntarse de nuevo. 2. Para averiguar el día de la semana en el que comienza dicho mes, se utilizará la congruencia de Zeller. Para ello se usará una función llamada calcula_dia()que recibirá como parámetros el día, mes y año en cuestión y devolverá el día de la semana en el que cae. Esta función utilizará una función auxiliar llamada calcula_parametros()que dado el mes y el año, devolverá los parámetros A, B y C, necesarios en la congruencia de Zeller. 3. Para averiguar cuántos días de un mes se usará una función llamada numero_de_dias()que recibirá como parámetro el mes y el año y devolverá el número de días que tiene dicho mes en ese año. Ten en cuenta para febrero que un año es bisiesto si es múltiplo de 400 o bien si es múltiplo de 4 pero no de 100. 4. Para mostrar finalmente el calendario, se usará una función llamada mostrar_calendario()que tendrá dos parámetros, el día de la semana en el que comienza el día 1 del mes a mostrar y el número de días de dicho mes. Nota: para escribir los números bien alineados, utiliza el carácter tabulador '\t'. Se pueden implementar tantas funciones como se vean oportunas, pero como mínimo las que se indican en el enunciado (calcula_dia() , calcula_parametros(), numero_de_dias(), mostrar_calendario()) Un ejemplo de ejecución del programa: Introduce el mes: 14 MES NO VÁLIDO, DEBE ESTAR ENTRE 1 y 12 Introduce el mes: 1 Introduce el año: 1500 AÑO NO VÁLIDO, DEBE SER MAYOR QUE 1752 Introduce el año: 2009 El calendario para ese mes en cuestión es: L M X J V S D ========================================== 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 ¿Quieres repetir el proceso (S/N)? : N #include <stdio.h> unsigned es_bisiesto(unsigned anio); void calcula_parametros(unsigned mes, unsigned anio, unsigned &A, unsigned &B, unsigned &C); unsigned calcula_dia(unsigned dia, unsigned mes, unsigned anio); unsigned numero_de_dias(unsigned mes, unsigned anio); void mostrar_calendario(unsigned dia_semana, unsigned num_dias); int main() { unsigned mes, anio, dia=1, dia_semana, num_dias; char repetir; do{ do{ printf("\nIntroduce el mes :"); scanf("%u",&mes); if (mes<1 || mes >12) printf("\tMES NO VALIDO, DEBE ESTAR ENTRE 1 Y 12"); }while(mes<1 || mes >12); do{ printf("\nIntroduce el anio :"); scanf("%u",&anio); if (anio<=1752) printf("\tANIO NO VALIDO, DEBE SER MAYOR QUE 1752"); }while(anio<=1752); dia_semana=calcula_dia(dia,mes,anio); num_dias=numero_de_dias(mes,anio); mostrar_calendario(dia_semana,num_dias); printf("\n\nQuieres repetir el proceso (S/N)?: "); scanf(" %c",&repetir); }while(repetir=='S' || repetir=='s'); return 0; } unsigned es_bisiesto(unsigned anio) { return (anio%400 ==0) || ( (anio%4 == 0) && !(anio%100 == 0) ); } void calcula_parametros(unsigned mes, unsigned anio, unsigned &A, unsigned &B, unsigned C) { if (mes <= 2) { A = mes + 10; B = (anio -1) % 100; C = (anio -1) / 100; } else // mes >=3 { A = mes - 2; B = anio % 100; C = anio / 100; } } unsigned calcula_dia(unsigned dia, unsigned mes, unsigned anio) { unsigned A, B, C, dia_semana; calcula_parametros(mes, anio, A, B, C); dia_semana = (700 + (26 * A-2) / 10 + dia + B + B/4 + C/4 - 2*C) % 7; return dia_semana; } unsigned numero_de_dias(unsigned mes, unsigned anio) { unsigned num_dias; switch (mes) { case 1: case 3: case 5: case 7: case 8: case 10: case 12: num_dias=31; break; case 2: if (es_bisiesto(anio)) num_dias=29; else num_dias=28; break; default: num_dias=30; } return num_dias; } void mostrar_calendario(unsigned dia_semana, unsigned num_dias) { int i; printf("\nL\tM\tX\tj\tV\tS\tD\n"); for(i=1 ; i<=50 ; i++) printf("="); printf("\n"); if (dia_semana==0) dia_semana = 7; //para que el domingo sea el 7 dia en lugar del 1ero for(i=1 ; i<=dia_semana-1 ; i++) printf("\t"); //Se saltan tabuladores para posicionar 1er dia del mes for(i=1 ; i<=num_dias ; i++) { printf("%u\t",i); if (dia_semana==7) { printf("\n"); dia_semana=1; } else dia_semana++; } }