El objetivo de esta práctica es afianzar ciertos conceptos básicos de la programación en lenguaje C:
- Bucles y tablas.
- Entrada y salida de datos.
- Paso de argumentos a un programa.
- Manejo de archivos.
- Funciones.
- Uso de memoria dinámica.
EJERCICIO 1.
Escribir un programa (es decir una función main) que pida por teclado una serie de números enteros, los almacene en una tabla estática y posteriormente escriba por pantalla todos los números introducidos indicando además cual es el mayor y el menor. Lo primero que debe hacer el programa es preguntar al usuario cuantos números se van a introducir y comprobar que dicha cantidad es menor que la dimensión de la tabla. Para dicha dimensión debe definirse una constante (por ejemplo MAX_DIMENSION) a la cual se puede asignar un valor razonable (por ejemplo, 100).
Funciones C a utilizar:
· scanf: para leer nĂşmeros introducidos por el teclado.
- printf: para imprimir por pantalla.
Ejemplo de ejecuciĂłn: lo que se verĂa por pantalla debe ser algo asĂ como
Introduce la cantidad de nĂşmeros:
3
Introduce los nĂşmeros:
5
7
2
Los nĂşmeros introducidos son:
5
7
2
El mayor es el 7.
El menor es el 2.
/*********************************************************
* Autor: Victor Sanchez2
* Web: http://usuarios.tripod.es/VictorSanchez2
* Correo: victorss18@hotmail.com
*
**********************************************************/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define OK 1
#define ERR -10001
#define MAX_DIM 100
int enteros[MAX_DIM]; /* Array para guardar los enteros */
int num_total;
int lectura(void);
int sacarpantalla(int max, int min, int num_total);
int calcular(int *max, int *min, int total);
int es_digito(char caracter[]);
int main()
{
int menor; /* Numero menor */
int mayor; /* Numero mayor */
if (lectura() == ERR)
{
printf("Error al leer el numero de terminos.\n");
return ERR;
}
if (calcular(&mayor, &menor, num_total) == ERR)
{
printf("Error al intentar calcular el mayor y el menor");
return ERR;
}
if (sacarpantalla(mayor, menor, num_total) == ERR)
{
printf("Error al mostrar por pantalla.\n");
return ERR;
}
return OK;
}
/*********************************************************
* Funcion: int lectura(int *total)
*
* IN: Toma una variable tipo int.
* OUT: Devuelve OK si se ha leido correctamente, ERR si hay algun fallo.
* MAKE: Obtiene los numeros que introduce el usuario y los guarda
* en un array de enteros
**********************************************************/
int lectura(void)
{
int continuar = OK;
int n;
char numeros[MAX_DIM];
for (n = 0; n < (int) strlen(numeros); n++)
numeros[n] = '0';
printf("\nCuantos numeros va a introducir? --> ");
do {
gets(numeros);
continuar = OK;
if ((num_total = es_digito(numeros)) == ERR)
continuar = ERR;
if (num_total <= 0)
{
printf("Debe introducir un numero positivo.\n");
continuar = ERR;
}
} while (continuar != OK);
printf("\nIntroduzca los numeros: \n");
for (n = 0; n < num_total; n++)
{
gets(numeros);
if ((enteros[n] = es_digito(numeros)) == ERR)
{
printf("Error al leer el numero, por favor repita introduccion.\n");
n--;
}
}
return OK;
}
/*********************************************************
* Funcion: int calcular(int *max, int *min, int num_total)
*
* IN: *max y *min que acumulan el numero mayor y menor. num_total
* acumula la cantidad de numeros que se van a introducir.
* OUT: OK si se ha realizado correctamente o ERR si hay fallos.
* MAKE: Encuentra el minimo y el maximo de los numeros introducidos
*
**********************************************************/
int calcular(int *max, int *min, int total)
{
int n;
*min = *max = enteros[0]; /* Lo inicializamos */
for (n = 1; n < total; n++)
{
if (*min > enteros[n])
*min = enteros[n];
if (*max < enteros[n])
*max = enteros[n];
}
return OK;
}
/*********************************************************
* Funcion: int sacarpantalla(int max, int min, int num_total)
*
* IN: toma el valor maximo,minimo y total de elementos
* OUT: devuelde ERR si no puede y OK si puede
* MAKE: Nada
*
**********************************************************/
int sacarpantalla(int max, int min, int num_total)
{
int n;
printf("Los numeros introducidos son: ");
for (n = 0; n < num_total; n++)
printf("%d, ", enteros[n]);
printf("\nMinimo: %d", min);
printf("\nMaximo: %d\n", max);
return OK;
}
/*********************************************************
* Funcion: int es_digito(char caracter)
*
* IN: Se le da una serie de caracteres para que se pasen a numero
* OUT: Nos devolvera ERR si se produce un eroor
* MAKE: Comprueba la integridad de los datos
*
**********************************************************/
int es_digito(char caracter[])
{
int i;
int num = 0;
int rango;
/* Si la cadena esta vacia */
if (caracter[0] == 0)
return ERR;
if (caracter[0] == '-') /* Si se ha introducido un numero negativo */
{
i = 1;
/* Empezamos el bucle para ver si es caracter desde el siguiente caracter */
rango = 5;
}
else /* Debe ser un numero positivo o hay algun error */
{
i = 0;
rango = 4;
}
/* Comprobamos que todos los elementos sean digitos */
/* El mayor numero que permitimos es 9999 */
if ((int) strlen(caracter) > rango)
{
printf("No puede introducir esa cantidad de numeros!!!\n");
printf("Es demasiado grande. Introduzca numeros entre -9999 y 9999\n");
return ERR;
}
for (i = i; i < (int) strlen(caracter); i++)
if (caracter[i] < '0' || caracter[i] > '9')
{
printf("\nIntroduzca unicamente digitos, por favor.\n");
return ERR;
}
/* Si solo se ha introducido un caracter */
if (strlen(caracter) == 1)
return num = caracter[0] - '0'; /* Devolvemos el digito */
/* Si hay mas de un caracter */
for (i = 0; i != (int) strlen(caracter); i++)
num = (num * 10) + (caracter[i] - '0');
return num;
}
EJERCICIO 2.
Escribir un programa (es decir una funciĂłn main) que lea el contenido de un archivo de texto y lo vuelque por pantalla, indicando posteriormente la longitud de la lĂnea más larga. El programa debe recibir el nombre del archivo como argumento, no teniendo que introducirse Ă©ste por pantalla. Para ello la funciĂłn main debe tener el prototipo estándar int main(int argc, char *argv[]).
Funciones C a utilizar:
· fopen: para abrir un archivo.
- fclose: para cerrar un archivo.
- fgets: para leer una lĂnea de un archivo.
- strlen: para obtener la longitud de una cadena.
/******************************************************************************
* Autor: Victor Sanchez2
* Web: http://usuarios.tripod.es/VictorSanchez2
* Correo: victorss18@hotmail.com
* Make: Este algoritmo lee un archivo introducido por el usuario
* y calcula cual es el numero de caracteres de la linea mayor.
*****************************************************************************/
#include <stdio.h>
#include <string.h>
#define ERR -1
#define OK 1
#define MAX_DIM 80 /* Maxima longitud de la linea */
#define mayor(a,b)((a) > (b) ? (a):(b))
char *fgets(char *linea, int max, FILE * fp);
int mayor_linea(void);
int leer_archivo(char *archivo[]);
void ayuda(void);
FILE * fp;
int max = MAX_DIM;
int main(int argc, char *argv[])
{
/* Debe introducir <nombre del ejecutable> <nombre del archivo> */
if (argc != 2)
{
ayuda();
return ERR;
}
if (leer_archivo(&argv[1]) == ERR)
return ERR;
printf("\nLa linea mas larga tiene %d caracteres.\n", mayor_linea());
fclose(fp);
return OK;
}
/******************************************************************************
* Funcion: int leer_archivo(char *archivo[])
*
* IN: Nombre del archivo
* OUT: OK si se ha leido correctamente, ERR si ha habido algun fallo
* MAKE: Lee un archivo introducido por el usuario.
*
*****************************************************************************/
int leer_archivo(char *archivo[])
{
if ((fp = fopen(archivo[0], "r")) == NULL)
{
printf("Error al intentar abrir el archivo\n");
return ERR;
}
return OK;
}
/******************************************************************************
* Funcion: int mayor_linea(void)
*
* IN:
* OUT: Tamagno de la linea de mayor longitud del archivo.
* MAKE: Calcula el tamagno de la linea mas larga.
*
*****************************************************************************/
int mayor_linea(void)
{
char cad[MAX_DIM];
int mayor_cad = 0; /* Inicializamos el valor de la cadena */
while (!feof(fp))
{
fgets(cad, MAX_DIM, fp);
mayor_cad = mayor(mayor_cad, (int) strlen(cad));
}
return mayor_cad;
}
/******************************************************************************
* Funcion: void ayuda(void)
*
* IN:
* OUT: Mensaje de ayuda para el usuario.
* MAKE: Muestra ayuda al usuario para que introduzca los datos correctamente.
*
*****************************************************************************/
void ayuda(void)
{
printf("\nDebe introducir: <nombre del ejecutable> <nombre del archivo>\n");
}
EJERCICIO 3.
El nĂşmero e (2.7183...) se puede aproximar mediante la suma:
Sumatorio de 1/n! desde n=0 hasta n=N
En esta expresiĂłn la precisiĂłn queda determinada por el valor N. El valor n! representa el factorial de n (1·2·...·(n -1)·n). Recordemos que, por definiciĂłn, 0!=1.
Escribir un programa (es decir una funciĂłn main) que permita calcular la aproximaciĂłn al nĂşmero e dada por N (valor preguntado al usuario). Debe utilizarse una funciĂłn auxiliar de prototipo float Factorial (int n); dicha funciĂłn debe ser una funciĂłn recursiva, puesto que n!=n·(n-1)!.
/*********************************************************
* Autor: Victor Sanchez2
* Web: http://usuarios.tripod.es/VictorSanchez2
* Correo: victorss18@hotmail.com
*
* MAKE: Este programa realiza la aproximacion al numero e.
* Lo hemos realizado de 2 maneras:
* - Recursivamente.
* - Forma mas eficiente (sin usar recursividad).
*
* Un ejemplo: (introduciendo 10000 terminos)
* - Recursividad: 12 segundos aproximadamente
* - Eficientemente: Se obtiene el resultado instantaneamente.
*
**********************************************************/
#include <stdio.h>
#include <string.h>
#define OK 1
#define ERR -10001
#define NO 0
#define MAX_TERM 1000000
float n_term;
int eficiente;
int lectura(int *eficiente, float *n_term);
float calcular(float n_term);
int sacarpantalla(float numeroe);
float factorial(int n);
int es_digito(char caracter[]);
int main()
{
if (lectura(&eficiente, &n_term) == ERR)
{
printf("Error al leer el numero de terminos\n");
return ERR;
}
if (sacarpantalla(calcular(n_term)) == ERR)
{
printf("Error al sacar por pantalla/calcular el numero\n");
return ERR;
}
return OK;
}
/*********************************************************
* Funcion: int sacarpantalla(float numeroe)
*
* IN: Toma la variable numeroe de tipo float.
* OUT: Devuelve OK si lo consigue, ERR si hay algun
* MAKE: Saca por pantalla el resultado. No modifica ninguna variable.
*
**********************************************************/
int sacarpantalla(float numeroe)
{
printf("\nEl valor de la aproximacion al numero e es: %f\n\n", numeroe);
return OK;
}
/*********************************************************
* Funcion: int lectura(int *eficiente, float *n_term)
*
* IN: Toma la direccion de la variable eficiente, y el numero de términos
* OUT: Nos devuelve OK si lo consigue ERR si hay algun fallo.
* MAKE: Se encarga de leer el numero de terminos a calcular. Modifica
* n_term y eficiente.
*
**********************************************************/
int lectura(int *eficiente, float *n_term)
{
char numero[5];
char temp = 0;
int continuar = NO;
do {
printf("\nIntroduzca el numero de terminos a calcular del numero e: ");
gets(numero);
} while ((*n_term = es_digito(numero)) == ERR || (*n_term < 1));
do {
printf("Desea usar el modo de calculo rapido? [S,N]:\t");
fflush(stdin);
fflush(stdout);
scanf("%c", &temp);
fflush(stdin);
if ((temp == 'S') || (temp == 'N') || (temp == 's') || (temp == 'n'))
{
continuar = OK;
if ((temp == 'S') || (temp == 's'))
*eficiente = OK;
else
{
*eficiente = NO;
if (strlen(numero) > 4) /* Permitimos hasta el numero 9999 */
{
printf("\nSi desea calcular este numero con recursividad puede
ocasionar problemas.");
printf("\nIntentelo con la manera eficiente.\n");
return ERR;
}
}
}
else
{
continuar = NO;
printf("Por favor introduzca un valor valido!!! \n");
}
} while (continuar != OK);
return OK;
}
/*********************************************************
* Funcion: float calcular(float terminos)
*
* IN: Numero de terminos para realizar la aproximacion.
* OUT: La aproximacion al numero e si es correcto o ERR si ha habido un
* fallo.
* MAKE: Calcula la serie: 1 entre el factorial de un numero dado.
*
**********************************************************/
float calcular(float terminos)
{
float e = 0;
float facto = 1; /* Va a ir acumulando el valor del factorial cuando se haya
seleccionado "eficiente" */
int n;
if (eficiente == OK)
{
printf("\nSe esta calculando el numero e de la manera mas eficiente.");
e = 1;
for (n = 1; n < (int) terminos; ++n)
{
facto *= n;
e += 1 / facto;
}
return e;
}
else /* Calculamos la serie usando recursividad */
{
do {
e += (1 / factorial((int) terminos--));
} while (terminos >= 0);
printf("\nSe esta calculando el numero e usando recursividad.");
}
return e;
}
/*********************************************************
* Funcion: float factorial (int n)
*
* IN: Numero de terminos de los que se calcularan sucesivos factoriales
* OUT: El factorial del numero o ERR si ha habido algun error.
* MAKE: Calcula el factorial de un numero dado.
*
**********************************************************/
float factorial(int n)
{
if (n == 0)
return 1;
else
return (n * factorial(n - 1));
}
/*********************************************************
* Funcion: int es_digito(char caracter)
*
* IN: Se le da una serie de caracteres para que se pasen a numero
* OUT: Nos devolvera ERR si se produce un eroor
* MAKE: Comprueba la integridad de los datos
*
**********************************************************/
int es_digito(char caracter[])
{
int i;
int num = 0;
int rango;
/* Si la cadena esta vacĂa */
if (caracter[0] == 0)
return ERR;
if (caracter[0] == '-') /* Si se ha introducido un numero negativo */
{
i = 1;
/* Empezamos el bucle para ver si es caracter desde el siguiente caracter */
rango = 7;
}
else /* Debe un numero positivo o hay algun error */
{
i = 0;
rango = 7;
}
/* Comprobamos que todos los elementos sean digitos */
/* El mayor numero permitido es 9999999 */
if ((int) strlen(caracter) > rango)
{
printf("No puede introducir esa cantidad de numeros!!!\n");
printf("Es demasiado grande. Rango: -9999999 y 9999999\n");
return ERR;
}
for (i = i; i < (int) strlen(caracter); i++)
if (caracter[i] < '0' || caracter[i] > '9')
{
printf("\nIntroduzca unicamente digitos, por favor.\n");
return ERR;
}
/* Si solo se ha introducido un caracter */
if (strlen(caracter) == 1)
return num = caracter[0] - '0'; /* Devolvemos el digito */
/* Si hay mas de un caracter */
for (i = 0; i != (int) strlen(caracter); i++)
num = (num * 10) + (caracter[i] - '0');
return num;
}
EJERCICIO 4.
Modificar el programa del ejercicio 1 para que en lugar de utilizar una tabla estática utilice una tabla alocada dinámicamente. La tabla debe alocarse una vez que el usuario ha indicado el número de elementos y debe liberarse al finalizar el programa.
Funciones C a utilizar:
· malloc: para alocar memoria dinámicamente.
- free: para liberar memoria previamente alocada.
/******************************************************************************
* Autor: Victor Sanchez2
* Web: http://usuarios.tripod.es/VictorSanchez2
* Correo: victorss18@hotmail.com
*
*****************************************************************************/
#include <stdio.h>
#include <alloc.h>
#include <stdlib.h>
#include <string.h>
#define OK 1
#define ERR -10001
#define NO 0
#define MAX_DIM 9999
int creartabla(int **ptabla, int *numero);
int rellenartabla(int *tabla, int numero);
int controldeerrores(int numero);
int calcular(int *tabla, int numero, int *max, int *min);
int mostrarvalores(int *tabla, int numero, int max, int min);
int es_digito(char caracter[]);
int *tabla = NULL;
int numero, max, min;
int main(void)
{
if (creartabla(&tabla, &numero) == ERR)
return ERR;
if (rellenartabla(tabla, numero) == ERR)
return ERR;
calcular(tabla, numero, &max, &min);
mostrarvalores(tabla, numero, max, min);
return OK;
}
/******************************************************************************
* Funcion: int creartabla(int **ptabla, int *numero)
*
* IN: la direccion de un puntero y la direccion del numero de elementos a
* guardar
* OUT: OK si se consigue, ERR si se falla
* MAKE: Crea una tabla dinamica de enteros en donde se guardaran los numeros
* introducidos
*
*****************************************************************************/
int creartabla(int **ptabla, int *numero)
{
int continuar;
char elementos[MAX_DIM];
do {
continuar = OK;
printf("Por favor introduzca el numero de elementos: ");
gets(elementos);
/* Si esta vacio, es negativo o 0... */
if (elementos[0] == 0 || elementos[0] == '-' || elementos[0] == '0')
continuar = ERR;
if ((*numero = es_digito(elementos)) == ERR)
continuar = ERR;
} while (continuar != OK);
*ptabla = (int *) malloc(*numero * sizeof(int));
if (*ptabla == NULL)
return ERR;
return OK;
}
/******************************************************************************
* Funcion: int rellenartabla(int *tabla, int numero)
*
* IN: la direccion de la tabla, el numero de enteros a guardar
* OUT: OK si se consigue ERR si se falla
* MAKE: rellena la tabla con los numero que introduzca el usuario
*
*****************************************************************************/
int rellenartabla(int *tabla, int numero)
{
int i, continuar;
char num[MAX_DIM];
printf("Por favor introduzca los numeros: \n");
for (i = 0; i < numero; ++i)
{
continuar = OK;
gets(num);
if (num[0] == 0)
{
printf("Deberia introducir algun digito.\n");
continuar = ERR;
}
if ((*tabla++ = es_digito(num)) == ERR)
{
printf("Error al leer el numero.\n");
continuar = ERR;
}
if (continuar == ERR)
i--;
}
return OK;
}
/******************************************************************************
* Funcion: int calcular(int *tabla, int numero, int *max, int *min)
*
* IN: La direccion de la tabla, el numero de elementos, y la direccion del * numero mas grande y mas pequeño
* OUT: OK si se consigue ERR si falla
* MAKE: calcula el numero mas grande y el mas pequeño
*
*****************************************************************************/
int calcular(int *tabla, int numero, int *max, int *min)
{
int i;
*max = *min = tabla[1];
for (i = 0; i < numero; i++)
{
if (tabla[i] > *max)
*max = tabla[i];
if (tabla[i] < *min)
*min = tabla[i];
}
return OK;
}
/******************************************************************************
* Funcion: int mostrarvalores(int *tabla, int numero, int max, int min)
*
* IN: La direccion de la tabla y los valores del numero maximo, minimo y * numero de enteros
* OUT: OK si se consigue ERR si falla
* MAKE: mostrar por pantalla los valores
*
*****************************************************************************/
int mostrarvalores(int *tabla, int numero, int max, int min)
{
int i;
printf("Los valores introducidos han sido:\t");
for (i = 0; i < numero; i++)
printf("%d\t", tabla[i]);
free(tabla);
printf("\nEl valor maximo ha sido:\t%d", max);
printf("\nEl valor minimo ha sido:\t%d", min);
printf("\nEl numero de terminos introducidos ha sido: %d\t\n", numero);
return OK;
}
/*********************************************************
* Funcion: int es_digito(char caracter)
*
* IN: una cadena de caracters
* OUT: el valor del numero
* MAKE: nada
*
**********************************************************/
int es_digito(char caracter[])
{
int i;
int num = 0;
int rango;
if (caracter[0] == '-') /* Si se ha introducido un numero negativo */
{
i = 1;
/* Empezamos el bucle para ver si es caracter desde el siguiente caracter */
rango = 5;
}
else /* Debe un numero positivo o hay algun error */
{
i = 0;
rango = 4;
}
/* Comprobamos que todos los elementos sean digitos */
if ((int) strlen(caracter) > rango)
/* El mayor numero que permitimos es 9999 */
{
printf("No puede introducir esa cantidad de numeros!!!\n");
printf("Es demasiado grande. Introduzca numeros entre -9999 y 9999\n");
return ERR;
}
for (i = i; i < (int) strlen(caracter); i++)
if (caracter[i] < '0' || caracter[i] > '9')
{
printf("\nIntroduzca unicamente digitos, por favor.\n");
return ERR;
}
/* Si solo se ha introducido un caracter */
if (strlen(caracter) == 1)
return num = caracter[0] - '0'; /* Devolvemos el digito */
/* Si hay mas de un caracter */
for (i = 0; i != (int) strlen(caracter); i++)
num = (num * 10) + (caracter[i] - '0');
return num;
}





