Arreglos 2
Arreglos 2
Arreglos 2
Los arreglos son variables que sirven para almacenar valores de un conjunto, por
ejemplo las calificaciones de un semestre. En la utm, cada materia se califica con 4
exámenes, podemos usar un arreglo para almacenar dichos valores y luego calcular la
calificación del semestre.
La regla es que todos los valores tienen que ser del mismo tipo y estar
relacionados entre sí. Más tarde en el curso se expondrán formas más avanzadas de
almacenar información.
En lenguaje C se tiene que declarar la variable para almacenar los datos en este
caso identificamos que los datos tienen punto decimal por lo que el tipo tiene que ser
float o double, enseguida nos damos cuenta que el tamaño del conjunto es de 4
elementos. Con la información anterior nos damos cuenta que la mejor forma de
almacenar dichos valores es por medio de un arreglo tal como se muestra a
continuación:
float cal[4];
La sintaxis de forma general es: tipo nombre[tamaño]; donde tipo pueden ser
cualquiera de los tipos reconocidos por lenguaje C como short, int, long, float, double
o char. El nombre sigue las mismas reglas que los nombres de las variables y debemos
recordar que siempre es bueno usar un nombre que nos signifique algo o nos de una
pista de lo que vamos a guardar en el arreglo. Por último, tenemos el tamaño que es el
número máximo de elementos que podemos almacenar en el arreglo. En el ejemplo, el
tipo es float porque los datos son números con punto decimal, el nombre es cal para
que nos recuerde que son calificaciones, y el tamaño es 4 porque es la cantidad de
elementos del conjunto.
return 0;
}
#define n 10000
int x[n], i;
float suma, promedio;
suma = 0.0;//iniciar la suma en cero
for(i=0; i<n; i++) suma = suma + x[i]; //sumar cada elemento
promedio = suma / n;
aquí el arreglo tiene un tamaño de 10,000 que es valor definido para n. Dense cuenta
que en lugar de tener una formula enorme que suma todos los valores, se usa un
acumulador y un ciclo para ir sumando un elemento del arreglo a la vez.
Una vez que tenemos almacenados los datos en el arreglo podemos hacer varias
cosas como buscar un elemento en particular y averiguar la posición del arreglo en la
que se encuentra, o bien, saber cual es el valor más grande o más pequeño. Noten que
los ciclos for y los arreglos están muy relacionados, ya que puede usarse un ciclo de
este tipo para procesar los datos que se encuentren en el arreglo sin importar cuantos
son con la condición que se tenga memoria suficiente en la computadora.
Por ejemplo para saber cual es el numero menor en el arreglo anterior, primero
debemos saber o suponer ciertas cosas. Por ejemplo, puedo suponer que el elemento
en la posición cero es el menor y compararlo con el resto y actualizar la información
cada que encuentre un número más pequeño que el último que encontré.
menor = x[0];
Ejercicio 1
Arreglos y funciones
En la unidad anterior se les enseño a usar funciones y a manejar parámetros tanto
por valor como por referencia. En C todos los arreglos se pasan como parámetros por
referencia, regularmente además del arreglo se acostumbra usar un parámetro que
indique el tamaño del arreglo para poder manipularlo correctamente. En el siguiente
ejemplo se ha modificado el programa 1 para que exista una función que calcule el
promedio del arreglo.
#include <stdio.h>
#include <stdlib.h>
//prototipos de las funciones
void leerDatos(float *c, int t);
void imprimirDatos(float *c, int t);
float promedio(float *c, int t);
return (EXIT_SUCCESS);
}
return suma / t;
}
Como puede observarse del programa anterior los prototipos de las funciones
tienen dos parámetros float *c que es el arreglo e int t que es el tamaño del arreglo.
La implementación de las funciones se muestra después de la función principal. En la
implementación podemos ver que se sigue usando la notación de los corchetes [] para
indicar el indice del arreglo, es decir, usamos c[i] que quiere decir el elemento i del
arreglo c. Dentro de la función principal mandamos a llamar las funciones, primero se
manda a llamar leerDatos(cal, 4), que significa que estamos usando el arreglo cal
declarado en dicha función, el 4 es el tamaño del arreglo cal.
leerDatos(calProgra, 4);
leerDatos(calCalculo, 4);
leerDatos(calFilosofía, 4);
Si alguno de los arreglos fuera más grande, simplemente ponemos el tamaño como
segundo parámetro.
Ahora consideren un programa más interesante que encuentra los primeros 100
números primos usando un algoritmo que usa la descomposición en factores primos
para probar si un número es primo o no. Todos los números primos con excepción del
dos son impares, por esa razón el programa solo prueba con los impares. El ciclo de la
función tiene dos condiciones de parada, si el número es divisible por alguno de los
primos menores a él entonces no es primo, la segunda condición dice que basta con
probar con los números primos menores a la raíz cuadrada de el número que
queremos saber si es primo o no. El ciclo por seguridad no busca en el arreglos
elementos con un indice mayor a 99, por que eso genera un error en tiempo de
ejecución que se llama violación de acceso a la memoria y provoca que el programa
se detenga y hacer que el sistema operativo se congele.
#include <stdio.h>
#include <stdlib.h>
#define FALSO 0
#define VERDADERO 1
return (EXIT_SUCCESS);
}
Ejercicio 2
Modifique el ejercicio 1 usando 3 funciones, una que calcule el promedio, otra que
devuelva la temperatura menor y la última que devuelva la temperatura mayor. Los
prototipos de las funciones son: float promedio(float *a, int t); float menor(float *a,
int t); y float mayor(float *a, int t). Nota: puede usar otras dos funciones para leer los
datos y otra para imprimir la lista de temperaturas.
return (EXIT_SUCCESS);
}
Como se puede notar del ejemplo anterior, las matrices siguen reglas muy
parecidas a un arreglo y debido que es una estructura tabular en donde cada renglón i,
tiene j columnas, entonces se necesita un ciclo que vaya cambiando de renglón y otro
independiente que se encargue de las columnas. Esto puede verse si se ejecuta el
código anterior, cuando pide los datos es posible ver que primero pide los datos del
primer renglón que corresponden a m1[0][0] y m1[0][1], sigue con el segundo
renglón que es m1[1][0] y m1[1][1], por último m1[2][0] y m1[2][1] que es el tercer
renglón de la matriz 1. Hace algo similar al pedir los datos de la segunda matriz y
también para encontrar la suma que se almacena en la matriz 3. A la hora de imprimir
lo hace renglón por renglón para visualizar la forma en la que se organizan los datos.
Deben darse cuenta que cada indice del arreglo usa su propio par de corchetes y esa es
una regla de lenguaje C, y también que el primer renglón tiene el indice 0 al igual que
la primer columna por eso el elemento que esta en el primer renglón y la primera
columna tiene los indices [0][0].
Ejercicio 3
return (EXIT_SUCCESS);
}
printf("{ ");
for(i=0; i < r; i++){
printf("{ ");
for(j=0; j < c; j++){
printf("%d", m[i][j]);
if(j < (c-1)) printf(", ");
else printf(" }");
}
if(i < (r-1)) printf("\n");
}
printf(" }\n");
}
Los programas con funciones tienen muchas ventajas, se puede resolver cada
parte del programa por separado y lo más importante se pueden llegar a probar los
módulos o funciones por separado hasta estar seguros que funcionan sin problemas.
Para ello es necesario tener disciplina y buenas prácticas de programación, eso
incluye que el diseño de los programas debe hacerse pensando en subdividir un
problema grande en problemas más pequeños y hacer que las soluciones de cada una
de ellas sean lo más independientes posible. La independencia permite probar por
separado los módulos y hacer que los errores queden contenidos dentro de cada
módulo, esto se consigue usando de forma inteligente el paso de paramétros y
variables locales siempre que sea posible, con la experiencia se da uno cuenta que en
muy pocos casos se justifica usar variables globales y aún así deberíamos evitar
usarlas.
Ejercicio 4
float tempSemanal[24][7];
float suma, promedios[7];
int dia, hora;
return (EXIT_SUCCESS);
}
Arreglos de caracteres y manejo de texto en C
En lenguaje C, los datos de texto se manejan por medio de códigos ASCII
(American Standard Code for Information Interchange), estos códigos son enteros de
un byte (valores de 0 a 255) y representan caracteres o simbolos imprimibles como
letras, números, caracteres especiales como la arroba, el gato, etc. Algunos
representan códigos especiales para controlar el intercambio de datos o bien
dispositivos de impresión como el salto de línea, tabulador, inicio o fin de transmisión,
etc. Se puede encontrar la tabla completa de estos códigos en algunos libros de texto o
en internet, se les deja como ejercicio buscar dicha información para usarla en sus
programas cuando lo consideren necesario. El tipo de dato para esto es char y se
acostumbra representar constantes de tipo caracter por medio del entero de su código
ASCII o encerrando el simbolo entre apostrofes como en ‘a’, ‘\n’, ‘@’, etc.
#define VERDADERO 1
#define FALSO 0
return (EXIT_SUCCESS);
}
Ejercicio 5
return -1;
}
En estadística existe un análisis que se conoce como histograma para graficar las
veces que aparecen datos de un conjunto dentro de subconjuntos especiales llamados
clases. Tipicamente, el rango total se acostumbra dividir en 5 subrangos, por ejemplo
consideremos un conjunto de enteros que representa la edad, podemos poner de 0 a 12
como niñez, 13 a 17 como adolescentes, 17 a 30 como juventud, de 31 a 60 como
adultos y 61 a 100 como ancianos. En un censo puede que nos interese saber que
porcentaje de la población se encuentra en cada rango para planear acciones de
gobierno que atiendan las necesidades de cada segmento. Haga un programa que
almacenando datos de 10,000 personas las clasifique en los rangos mencionados y
calcule el porcentaje de cada rango con respecto a la población total. Nota: puede
probar su programa con una población de solo 20 para comprobar que los resultados
de su programa son correctos. Las veces que un dato o rango de datos se repiten se
llama frecuencia y la frecuencia mayor se conoce como moda. Para encontrar la moda
se recomienda almacenar las frecuencias en un arreglo.
El método de la burbuja ordena el último elemento del arreglo en cada pasada del
ciclo de adentro, por esa razón el ciclo de afuera se debe hacer tantas veces como
elementos tenga el arreglo. El ordenamiento se hace comparando un elemento con el
que se encuentra delante de el, es decir, el que se encuentra en la posición j con el que
se encuentra en la posición j+1, por esta razón el ciclo interior tiene la condición de
terminar con el penúltimo para poderlo comparar con el último. Dado que se ordena
de menor a mayor, un par se encuentra desordenado si el elemento j es mayor que
elemento j+1, en ese caso se lleva a cabo un intercambio el cual tiene que hacerse por
medio de una variable auxiliar. La versión que sirve para ordenar cadenas sigue el
mismo razonamiento, solo que las cadenas tienen que compararse con strcmp y las
cadenas deben copiarse caracter a caracter por medio de la función strcpy, ambas
funciones se encuentran en string.h, puede encontrar una descripción más detallada de
dichas funciones en los libros de Deitel y Aitken que se les proporcionó como parte
del material del curso. También deben notar que un arreglo de cadenas en realidad es
un arreglo de arreglos, es decir, una matriz y la forma de pasarla como parámetros es
igual a los ejemplos que se dieron con matrices, donde LON_MAXIMA + 1 considera
la longitud máxima de las cadenas incluyendo el caracter nulo.
El humilde método de la burbuja puede ser la mejor opción si los datos cambian
raramente y dicha operación no tiene que realizarse de forma frecuente como ocurre
en gran mayoría de los casos, cuálquier cambio en los datos requiere volver a
ordenarlos. Lo más común es que los datos cambien poco, además para poder aplicar
un método eficiente de búsqueda como la búsqueda binaria es necesario usar alguna
clave que sea única para cada dato, un ejemplo de esto es la matrícula que se les
asigna al ingresar a la universidad, de este modo aunque existan dos personas que se
llamen igual, estas no deberían tener la misma matrícula. A continuación se presenta
la versión iterativa (por medio de ciclos) de la búsqueda binaria.
Ejercicio 7