Pontificia Universidad de Valparaíso Facultad de Ingeniería Escuela de Ingeniería Informática Fundamentos de Programación – ICI 142 Segundo Semestre 2008 jueves 12 de noviembre CERTAMEN 2 Para la realización del presente certamen se dispondrá de 120 minutos. No se pueden utilizar libros ni apuntes. 1. (20 puntos) Implementar un programa en lenguaje C usando memoria dinámica y aritmética de punteros (sin utilizar la librería string.h) que permita ingresar un texto de N líneas desde teclado. Las líneas son de largo variable y cada línea tiene a lo sumo 80 caracteres. Las palabras están separadas por un carácter blanco o por el carácter fin de línea. Las líneas tendrán el siguiente formato. NOMBRE PRECIO CANTIDAD Cuaderno 750 3 Nótese que nombre, precio y cantidad están separadas por un espacio. El programa principal debe invocar al menos las siguientes funciones: LeerTexto: Permite leer cada línea de texto desde interrupciones del teclado. CalcularTotal: Calcula el total de la guía de despacho(precio*cantidad). MostrarTotal: Muestra el total de productos. GuardarDespacho: Función que almacene la guía de despacho en un archivo ASCII llamado despacho.txt. #include<stdio.h> #include<stdlib.h> void LeerTexto(char **a,int n); void CalcularTotal(char **a,int n); int MostarTotal(char **a,int n); void GuardarDespacho(char **a,int n); int main(){ char **texto,buffer[80]; int lineas,i; printf("INGRESE CANTIDAD DE LINEAS QUE POSEE EL TEXTO: "); scanf("%d",&lineas); fflush(stdin); texto=(char**)malloc(lineas*sizeof(char*)); LeerTexto(texto,lineas); CalcularTotal(texto,lineas); printf("LA CANTIDAD TOTAL DE PRODUCTOS ES: %d",MostarTotal(texto,lineas)); GuardarDespacho(texto,lineas); getch(); return(0);SADASA } void copia(char *destino, char *origen){ for(; *origen!= '\0';*destino++=*origen++); } José Miguel Rubio León – Ing. Civil en Informática, P.U.C.V. Pontificia Universidad de Valparaíso Facultad de Ingeniería Escuela de Ingeniería Informática Fundamentos de Programación – ICI 142 Segundo Semestre 2008 jueves 12 de noviembre int largo (char *x){ int cont; for(cont=0;(*x++)!= '\0';cont++); return(cont); } void LeerTexto(char **a,int n){ char buffer[80]; int i; for(i=0;i<n;i++){ printf("INGRESE LA LINEA %d: ",i+1); gets(buffer); fflush(stdin); *(a+i)=(char*)malloc(largo(buffer)*sizeof(char)); copia((*(a+i)),buffer); *(*(a+i)+largo(buffer))='\0'; } } void CalcularTotal(char **a,int n){ float precio, cantidad, total=0; int j,i,espacio; for(i=0;i<n;i++){ j=0; precio=0; cantidad=0; espacio=0; while(*(*(a+i)+j)) { if(espacio==1 && ((*(*(a+i)+j))!=' ')){ precio=precio*10+(*(*(a+i)+j))-'0'; } if(espacio==2){ cantidad=cantidad*10+(*(*(a+i)+j))-'0'; } if((*(*(a+i)+j))==' ') espacio++; j++; } total=total+precio*cantidad; } printf("La cantidad total de ganancias es: %g\n",total); system("pause"); } int MostarTotal(char **a,int n){ int j,i,espacio,cantidad, total=0; for(i=0;i<n;i++){ j=0; cantidad=0; espacio=0; while(*(*(a+i)+j)) { if(espacio==2){ José Miguel Rubio León – Ing. Civil en Informática, P.U.C.V. Pontificia Universidad de Valparaíso Facultad de Ingeniería Escuela de Ingeniería Informática Fundamentos de Programación – ICI 142 Segundo Semestre 2008 jueves 12 de noviembre cantidad=cantidad*10+(*(*(a+i)+j))-'0'; } if((*(*(a+i)+j))==' ') espacio++; j++; } total=total+cantidad; } return(total); } void GuardarDespacho(char **a,int n){ FILE *pt; int i; if( (pt=fopen("despacho.txt","w"))==NULL){ printf("ERROR AL TRATAR DE ESCRIBIR, VERIFIQUE QUE EL ESPACIO SEA EL SUFICIENTE\n"); }else{ fprintf(pt,"DESPACHO TROGLODITA:\n_________________________________________"); fprintf(pt,"\nPRODUCTOS:\nNOMBRE PRECIO CANTIDAD\n"); for(i=0;i<n;i++) fprintf(pt,"%s\n",*(a+i)); fprintf(pt,"_________________________________________"); fclose(pt); } } 2. a) ¿Señale 2 recomendaciones a las que esta sujeta la inclusión de ficheros? (2 puntos) Resp.: - Por lo general los ficheros de cabecera tienen como extensión .h - En los ficheros de cabecera no se incluyen implementación de funciones - Las variables en un fichero de cabecera son declaradas extern y se encuentran declaradas en algún otro fichero .c a) Explique brevemente el funcionamiento de las siguientes funciones de gestión de memoria dinámica (1 puntos): i) void* malloc(size_t): Reserva memoria dinámica. ii) void* realloc(void*,size_t): Ajusta el espacio de memoria dinámica. b) Dadas las siguientes definiciones de variables: int x; int *p1; int **p2; ¿Cuál de las siguientes sentencias permite que x tome el valor 4 de forma correcta? (3 puntos) a) b) c) d) p1 p2 p2 p2 = = = = &p2; *p2 = &x; *p1 =4; &x; *p2 = 4; p1; p1 = &x; *p2 = 4; &p1; p1 = &x, **p2 = 4; José Miguel Rubio León – Ing. Civil en Informática, P.U.C.V. Pontificia Universidad de Valparaíso Facultad de Ingeniería Escuela de Ingeniería Informática Fundamentos de Programación – ICI 142 Segundo Semestre 2008 jueves 12 de noviembre Resp.: D Respeto al manejo de archivos en C, complete la siguiente tabla referente a los modos de apertura y explique el funcionamiento y la sintaxis de la función fopen (10 puntos).. Archivo de texto a r w Archivo binario ab rb wb a+ ab+ r+ rb+ w+ wb+ Significado Abre el fichero para añadir datos al final. Si no existe, se crea. Abre el fichero para lectura. El fichero debe existir. Abre el fichero para escritura desde el principio. Si no existe, se crea. Abre el fichero para lectura y para añadir datos al final. Si no existe, se crea. Abre el fichero para lectura y escritura. Los datos se escriben desde el principio. El fichero debe existir. Abre el fichero para lectura y escritura. Los datos se escriben desde el principio. Si no existe, se crea. FILE *fopen (char *pathname, char *type) – pathname : cadena de caracteres que indica el nombre del fichero, incluido el camino – type : cadena que contiene el tipo de fichero y su modo de apertura Explique mediante un ejemplo como se puede implementar recursividad mediante la utilización de pilas (4 puntos). Algoritmo para hallar el factorial de un número mediante pilas leer n; mientras n > 1 pila.apilar (n); n = n-1; fin mientras factorial = 1; mientras pila no está vacía factorial = factorial * pila.desapilar (); fin mientras 3. Suponga que se tiene la expresión ((5+6)*4)/(17+9): una de las condiciones para que esta sea una expresión aritmética correcta es que tenga sus paréntesis balanceados. Se desea saber si el número de paréntesis que abre es el mismo número de paréntesis que cierran: a) Defina la estrategia a utilizar para resolver el problema mediante estructuras de datos lineales. (5 puntos) José Miguel Rubio León – Ing. Civil en Informática, P.U.C.V. Pontificia Universidad de Valparaíso Facultad de Ingeniería Escuela de Ingeniería Informática Fundamentos de Programación – ICI 142 Segundo Semestre 2008 jueves 12 de noviembre Para resolver este problema usaremos el concepto de pila. La idea es simple. Vamos a leer cada elemento de la expresión, si se trata de un paréntesis que abre, entonces lo insertaremos en una pila; si se trata de un paréntesis que cierra, entonces sacamos un elemento de la pila. Al terminar de leer la expresión revisaremos si la pila está vacía, en cuyo caso habremos concluido que el número de paréntesis que abre es el mismo que el número de paréntesis que cierra y la expresión tiene paréntesis balanceados. b) Implemente su solución (15 puntos) `(' : push(S,`(') `(' : push(S,`(') `5' : nada que hacer `+' : nada que hacer `6' : nada que hacer `)' : v=pop(S) `*' : nada que hacer `4' : nada que hacer `)' : v=pop(S) `/' : nada que hacer `(' : push(S,`(') `17': nada que hacer `+' : nada que hacer `9' : nada que hacer `)' : v=pop(S) Empezamos con un contador iniciado en 0, y por cada push aumentamos un contador, y por cada pop decrementamos el contador. Al final vemos el valor del contador, si el contador=0 entonces terminamos con éxito, de otro modo señalamos el error. /************************************* * C3, Pregunta 3b * * Supuesto: Los operandos son solo digitos (0-9) *************************************/ #include <stdio.h> #include <stdlib.h> typedef struct nodo José Miguel Rubio León – Ing. Civil en Informática, P.U.C.V. Pontificia Universidad de Valparaíso Facultad de Ingeniería Escuela de Ingeniería Informática Fundamentos de Programación – ICI 142 Segundo Semestre 2008 jueves 12 de noviembre { char dato; struct nodo *sig; }NodoLista; NodoLista *head = NULL; char *expresion; void insertar(NodoLista **L, char c); int parentesis_balanceados(NodoLista **L); main() { int res; printf("\nIngrese expresion: "); scanf("%s",expresion); while((*expresion) != '\0') { insertar(&head,(*expresion)); expresion = expresion + sizeof(char); } res = parentesis_balanceados(&head); if(res == 1) printf("\nExpresion Balanceada"); if(res == 0) printf("\nexpresion NO Balanceada"); if(res == -1) printf("\nError. No hay una expresion.."); } void insertar(NodoLista **L, char c) { NodoLista *aux, *nuevo; if(!(*L)) { (*L) = (NodoLista *)malloc(sizeof(NodoLista)); (*L)->dato = c; (*L)->sig = NULL; } else { aux = (*L); while(aux->sig) { aux = aux->sig; } nuevo = (NodoLista *)malloc(sizeof(NodoLista)); nuevo->dato = c; nuevo->sig = NULL; aux->sig = nuevo; } } int parentesis_balanceados(NodoLista **L) { José Miguel Rubio León – Ing. Civil en Informática, P.U.C.V. Pontificia Universidad de Valparaíso Facultad de Ingeniería Escuela de Ingeniería Informática Fundamentos de Programación – ICI 142 Segundo Semestre 2008 jueves 12 de noviembre NodoLista *aux; int ap, cp; //Contadores de abre y cierre parentesis if(!(*L)) return(-1); else { ap = cp = 0; aux = (*L); while(aux->sig) { if(aux->dato == '(') ap++; if(aux->dato == ')') cp++; aux = aux->sig; } } if(ap == cp) return(1); else return(0); } José Miguel Rubio León – Ing. Civil en Informática, P.U.C.V.