Laboratorio 14 - Universidad de Costa Rica

Anuncio
Universidad de Costa Rica
Facultad de Ingeniería
Escuela de Ingeniería Eléctrica
IE0117 – Programación bajo plataformas abiertas
I ciclo 2012
Nota: 100
Excelente.
Profesor
Francisco Siles Canales
Asistente
Félix Suárez Bonilla
Laboratorio
Laboratorio 14
Estudiante
Enrique Sáurez Apuy, A95872
Junio, 2012
1. Escriba una función que tome como argumento una cadena de caracteres, verifique
que los caracteres de la cadena correspondan a un número de punto flotante válido
y realice la conversión, retornando el valor resultante. Si la validación de la cadena
falla, debe retornarse el valor -999999 (o cualquier otro valor que permita
identificar una condición de error). Escriba además un pequeño programa que
permita probar el funcionamiento de la función. La función debe ser capaz de
identificar números de punto flotante escritos de distintas manejas (por ejemplo, 100, 42, 0.23, -.2345 y .20 son todos números de punto flotante válidos).
Para realizar el programa solicitado en el enunciado primero lo que se hace es verificar si
la primer posición es un signo, de ser negativo, se asigna a sign el valor de -1, de lo contrario se
le asigna 1. Si se dio un signo al inicio, se aumenta el contador i, que muestra la posición del
carácter del arreglo de caracteres que se está analizando. Luego se inicializa la variable val a
cero, y se itera sobre el arreglo de caracteres mientras este sea un digito, y este se le suma a la
variable val para que esta almacene su valor, multiplicando por 10 el valor anterior antes de
sumarse.
Cuando se sale de este ciclo significa o que se acabo el número o que es un punto, si es
un punto, se suma 1 al contador i, para entrar al nuevo ciclo, que analizará si hay mas valores
dígitos, de ser así se utiliza la variable power para almacenar el valor que se tiene que dividir
para que la coma, quede en la posición correcta.
Luego de la anterior iteración lo único que puede aparecer para que el número sea
correcto es un \0 que es el carácter de finalización de número. De lo contrario significa que hay
un error y se devuelve –9999999. El código ya compilado se muestra en prueba1.o
#include <stdio.h>
#include <string.h>
#include <ctype.h>
float conversion(char s[]){
//Se definen las variables
float val, power;
int i, sign;
//Se asigna a i un cero
i = 0;
//Se verifica si la primer posiciÓn es -, de ser asÍ se asigna un -1 al signo
sign = (s[i] == '-')?-1:1;
//Si las primeras posiciones son - o + se suma uno a i, que es el que itera sobre el char
if(s[i]=='+'||s[i]=='-'){
i++;
}
//Se recorre el char mientras s[i] sea un digito, y se le va asignando a val
for(val = 0.0; isdigit(s[i]); i++){
val = 10.0 * val + (s[i]-'0');
}
//Si se sale del ciclo anterior se verifica si la siguiente posicion es un punto, de ser asi, se le
suma uno a i.
if(s[i]=='.')
i++;
//Si luego del punto, hay mÁs números, se van sumando a la variable val, y se multiplica
power por 10, que va a dar la posicion del decimal
for(power = 1.0 ; isdigit(s[i]); i++){
val = 10.0 * val + (s[i]-'0');
power *= 10.0;
}
//Si luego de iterar sobre todas las condiciones anteriores no se llega al final de la palabra,
significa que no era un número, por lo tanto se devuelve un -999999
if(s[i]!='\0'){
return -999999;
}
//Si no se entro en la condiciÓn anterior se devuelve el numero, que es el signo multiplicado
por el numero y divido entre power.
return sign * val / power;
}
//main con las pruebas
int main(){
char s[1000] = "53.5868";
printf("El nÚmero es: %f \n",conversion(s));
char s1[1000] = "-23.8894";
printf("El nÚmero es: %f \n",conversion(s1));
char s2[1000] = "hola";
printf("El nÚmero es: %f \n",conversion(s2));
char s3[1000] = "+37372";
printf("El nÚmero es: %f \n",conversion(s3));
char s4[1000] = "-100";
printf("El número es: %f \n",conversion(s4));
char s5[1000] = "0.23";
printf("El número es: %f \n",conversion(s5));
char s6[1000] = "-.2345";
printf("El número es: %f \n",conversion(s6));
char s7[1000] = ".20";
printf("El número es: %f \n",conversion(s7));
return 0;
}
Código 1
Con las pruebas del main, se analizan las principales posibilidades para la conversión de
string a flotante (se utilizaron todos los ejemplos del enunciado), los resultados se observan en la
Figura 1. Donde los prints en la pantalla son los esperados, dado que se obtuvieron los números
esperados.
Figura 1; Prueba del código 1.
2. Escriba un programa que reciba, a través de la línea de comandos, el nombre de un
archivo que contenga números enteros (uno por línea, máximo 100) en desorden,
copie los números a un arreglo, ordene el arreglo de manera ascendente e imprima
la lista de números ordenados en la terminal.
Para realizar las acciones solicitadas primero es necesario abrir el archivo, lo cual se
realiza utilizando fopen. Además es necesario reservar espacio de memoria para almacenar los
números que trae el archivo, se reserva un tamaño igual a 100*sizeof(int), dado que en el
enunciado se aclara que hay máximo 100 números. Posterior a esto se recorre el archivo,
obteniendo cada línea, y almacenando el entero que hay en ella, en la posición que indica el
contador i. De darse un EOF, se sale del for, y en caso de ser más de 100 líneas, el for no los
toma en cuenta. En este caso se hace una conversión de string a integer.
Posteriormente se imprime una línea, que indica que se ordenaron los números, y se
utiliza la función interna de C, qsort para ordenar el arreglo de enteros, para esto fue necesario
definir la función de comparación int_cmp que lo que hace es comparar a partir de los punteros
si dos números cuales son mayores, iguales o menores. Por último se imprime la lista ya
ordenada. (Solo se toman en cuenta las posiciones de memoria utilizadas), y se libera el espacio
utilizado, y se cierra el archivo abierto.
En el main solo se invoca a la función y se revisa la cantidad de parámetros enviados por
el usuario, sea la correcta. El código ya compilado se llama prueba2.o
#include <stdio.h>
#include <stdlib.h>
int int_cmp(const void *a, const void *b)
{
const int *ia = (const int *)a; //Se hace un casting para cambiar el tipo de puntero
const int *ib = (const int *)b;
return *ia - *ib;
/*La comparación de enteros regresa un valor positivo si a es mayor que b, negativo si b es
mayor que a, y 0 si son iguales*/
}
void archivo(char *open){
/* Punteros a archivo */
FILE *origen;
//Se definen las variables que se van a utilizar para iterar o guardar los valores de los caracteres.
int i,j;
int valor;
char c;
//Se define el puntero, que apunta a la primer posicion de memoria donde se van a guardar un
vector con los enteros, a ordenar.
int *p;
//Se define que la posicion de memoria tiene 100 espacios, dado que este es el mayor tamaÑo
estipulado en el enunciado
p = (int *)malloc(100*sizeof(int) );
/* Abre los archivos */
origen = fopen(open, "r");
/* Comprueba que los archivos se hayan abierto correctamente */
if(origen == NULL) {
fprintf(stderr, "Error de entrada/salida\n");
exit(2);
}
//Se itera sobre el archivo, sobre maximo 100 lineas.
for(i=0;i<100;i++){
//En cada iteración se inicializar la variable valor en 0
valor = 0;
//Mientras c sea distinto de EOF y fin de linea, captura el valor de c en valor, convirtiendolo
en un int.
while(((c = fgetc(origen)) != '\n')&&(c != EOF)){
valor = valor * 10 + (c-'0');
}
//Se asigna al espacio de memoria p[i] el valor, de valor.
p[i]=valor;
//Si se dio fin de archivo, se da un break, dado que no hay mas nÚmeros
if(c==EOF){
break;
}
}
//Se imprime una instrucciÓn con lo que se va a hacer.
printf("Los nÚmeros ordenados son:\n");
//Utilizando la funciÓn qsort implementada en la librerÍa de C, se ordena el arreglo de enteros.
qsort(p, i, sizeof(int), int_cmp);
//Luego de ordenarlos se imprime en la pantalla, utilizando un ciclo for
for(j=0;j<i;j++){
printf("%d\n",p[j]);
}
/* Cierra el archivo */
fclose(origen);
//Se libera la memoria utilizada
free(p);
}
int main(int argc, char *argv[]) {
/* Comprueba que la cantidad de argumentos sea la correcta */
if(argc != 2) {
fprintf(stderr, "Error: Cantidad de argumentos incorrecta\n");
exit(1);
}
archivo(argv[1]);
}
Código 2
Para verificar el correcto funcionamiento del programa se generó el siguiente archivo con
solo números (se acomodó en columnas en el presente documento, para facilitar su lectura):
3
2
1
8
11
3
7
8
9
1
2
3
4
5
6
7
8
9
1
5
3
3
5
2
1
2
3
4
5
6
7
8
9
7
8
6
4
234
4
6
78
8
5
7
9
7
6
5
4
3
3
5
6
7
8
9
4
5
3
3
3
34
45
6
8
7
5
4
7
8
9
3
4
5
44
3
45
6
7
9
45
6
5
4
3
2
2
6
8
89
9
23
45
7
8
9
6
235
Utilizando la siguiente línea en la terminal:
./prueba2.o hola.txt > a.txt
Se almacena los resultados del programa en a.txt, los cuales se muestran a continuación
Los números ordenados son:
1
1
1
1
2
2
2
2
2
2
3
3
3
3
3
3
3
3
3
3
3
3
3
3
4
4
4
4
4
4
4
4
4
5
5
5
5
5
5
5
5
5
5
5
6
6
6
6
6
6
6
6
6
6
6
7
7
7
7
7
7
7
7
7
7
7
8
8
8
8
8
8
8
8
8
8
8
9
9
9
9
9
9
9
9
9
11
23
34
44
45
45
45
45
78
89
234
235
De no colocarse el pipe a la llamada del programa, los números anteriores se mostrarían
en la terminal, 1 por línea. Pero dada la cantidad de números una imagen de los mismo no aporta
mayor valor al presente trabajo.
Con lo cual se demuestra que el programa funciona correctamente, se puede generar
cualquier archivo con números, y este los ordenará correctamente, con excepción a números con
más de 100 líneas, donde solo tomará en cuenta las primeras 100 líneas, y procederá a
ordenarlas. De aparecer letras, el programa los tomará como números, y calculará su
correspondiente numérico – ‘0’, y los tratará como números y los ordenará como tal.
Descargar