PRÁCTICA ARREGLOS CON FUNCIONES Objetivos El alumno será capaz de programar algoritmos que incluyan el manejo de arreglos utilizando funciones. Al final de esta práctica el alumno podrá: 1. Realizar exitosamente programas que hagan uso de arreglos como parámetros de funciones. Antecedentes 1. Conocer la utilización del ciclo for para guardar arreglos. 2. Conocer el manejo de funciones y el paso de valores a través de funciones. 3. Saber como de declara y manipula un arreglo unidimensional. Introducción En C se indica el número de elementos que tiene un arreglo unidimensional poniendo, después del nombre del arreglo, la dimensión del mismo entre corchetes: nombre[N], donde N es el número de elementos. El índice del primer elemento del arreglo es 0 y el último es N-1. El paso de arreglos a funciones es una de las operaciones más comunes en la programación. Para que una función pueda recibir un arreglo unidimensional simplemente se especifica su tipo y se coloca después de su identificador, un par de corchetes vacíos. Por ejemplo en el siguiente prototipo de función: float Prom( float x[ ], int n); El compilador reconoce que el primer argumento que la función va a recibir es un arreglo por el par de corchetes vacío. El segundo argumento, que es una cantidad entera, representa el número de elementos del arreglo que será procesado. También se puede especificar, por ejemplo, si se va a pasar un arreglo de 10 elementos, la dimensión del arreglo así: float Prom(float x[10], int n); pero como no es necesario, rara vez se utiliza. Elaborada por: M.C. Vicente Fuentes Gea vfg@servidor.unam.mx M.C. Cintia Quezada Reyes cintia@fi-b.unam.mx Ing. Alejandra Vargas E. De los M. alejandrav@correo.unam.mx 1 PRÁCTICA ARREGLOS CON FUNCIONES Para invocar a Prom se coloca el identificador del arreglo como primer parámetro y el número de datos que se desea procesar como segundo. Por ejemplo, a continuación se define a Prom de modo que regrese el promedio de una serie de números reales: float Prom(float x[], int n) { int i; float r = 0; for(i = 0;i < n; i++) r += x[i]; /* se suman los elementos*/ return r / n; } int main(void) { float a[10] = {3.1, 4.6, 8.0, 7.2, 6.9}; float p; p = Prom(a, 5); /* sólo se desea procesar los 5 primeros elementos del arreglo*/ printf(“%f\n”, p); return 0; } Cuando se pasa en arreglo a una función se está proporcionando a la función la dirección de comienzo asignada al arreglo, por lo que la función que recibe el arreglo, puede escribir o manipular la información contenida en el mismo. En otras palabras, en realidad no se pasa el arreglo a la función, y toda la carga que esto representa, sobre todo tratándose de arreglos de tamaños considerables, sino la dirección en donde éste comienza. En el siguiente programa de ejemplo, presenta a una función que recibe un arreglo y el número de datos que se desea procesar, y lo ordena de forma ascendente, mediante el método conocido como “método de la burbuja” /*Ejemplo 1: Método de la burbuja*/ #include <stdio.h> #include <conio.h> /*Función que recibe un arreglo y lo ordena de forma ascendente por el método de la burbuja*/ void Ordena(float Arreglo[], int Tam) { Elaborada por: M.C. Vicente Fuentes Gea vfg@servidor.unam.mx M.C. Cintia Quezada Reyes cintia@fi-b.unam.mx Ing. Alejandra Vargas E. De los M. alejandrav@correo.unam.mx 2 PRÁCTICA ARREGLOS CON FUNCIONES int i,j; float t; for(i=1; i<Tam; ++i) for(j=Tam-1; j>=i; --j) if(Arreglo[j-1]>Arreglo[j]) { t=Arreglo[j-1]; Arreglo[j-1]=Arreglo[j]; Arreglo[j]=t; } } /* Función que guarda los datos en un arreglo,y posteriormente lo envía a otra función que los ordena*/ void GuardaArreglo() { int i, Tam; float Arreglo[100]; printf("DAR EL NUMERO DE DATOS QUE SE QUIERE PROCESAR \n"); scanf("%d", &Tam); if(Tam>100) printf("EL NÚMERO QUE DISTE EXCEDE AL TAMAÑO DEL ARREGLO \n"); else { printf("DAR LOS ELEMENTOS DEL ARREGLO \n"); for(i=0; i<Tam; i++) { printf("Arreglo[%d]= ", i); scanf("%f", &Arreglo[i]); } Ordena(Arreglo, Tam); /*llamada a la función Ordena con el envío del el arreglo y el numero de datos a procesar */ printf("\n LOS NÚMEROS ORDENADOS SON \n"); for(i=0; i<Tam; i++) printf("%.2f \t", Arreglo[i]); return 0; } } Elaborada por: M.C. Vicente Fuentes Gea vfg@servidor.unam.mx M.C. Cintia Quezada Reyes cintia@fi-b.unam.mx Ing. Alejandra Vargas E. De los M. alejandrav@correo.unam.mx 3 PRÁCTICA ARREGLOS CON FUNCIONES int main(void) { GuardaArreglo(); /* Se llama a la función que guarda datos en el arreglo*/ return 0; } Otros ejemplos que muestran el paso de arreglos a una función son: Ejemplo 2. Número capicúa Se desea leer por teclado un número entero largo e indicar si el número leído es o no capicúa. Para esto, se debe considerar que un número capicúa es aquél que es leído igual de izquierda a derecha que de derecha a izquierda por ejemplo 15651. Es indispensable, como primer paso, saber la cantidad (k) de dígitos que el número ingresado contiene, cuáles son estos dígitos y la posición que ocupan dentro del número – contabilizar la posición a partir de cero y finalizando en cantidad de dígitos menos uno (k-1). En el número 15615 se tienen 6 dígitos y las posiciones de cada uno son: 1 5 6 5 1 Posición 0 Posición 1 Posición 4 (k-1) Posición 3 Posición 2 El segundo paso consiste en comparar de dos en dos los dígitos del número, iniciando en los extremos y finalizando en el centro, esto es, la primera comparación se realiza entre el primer dígito y el dígito k-1, la segunda comparación es entre el segundo dígito y el dígito k-2, así sucesivamente. 1 5 6 5 1 Primera comparación Segunda comparación Elaborada por: M.C. Vicente Fuentes Gea vfg@servidor.unam.mx M.C. Cintia Quezada Reyes cintia@fi-b.unam.mx Ing. Alejandra Vargas E. De los M. alejandrav@correo.unam.mx 4 PRÁCTICA ARREGLOS CON FUNCIONES Observar que un número con una cantidad de dígitos impar, no necesita comparar el dígito central con otro dígito. Considerando los pasos anteriores, se plantean en el programa dos funciones: a) int numero(long c,int tabla[]) - la cual permite realizar la cuenta de la cantidad de dígitos contenidos en el número y guardar uno por uno en un arreglo. b) int comparar_numero(int c,int tabla[]) – ésta permite realizar las comparaciones por parejas de los dígitos contenidos en el número, para resolver si éste es o no capicúa. /*Ejemplo 2: Programa que indica si un número entero es o no capicúa*/ #include <stdio.h> int numero(long a,int tabla[]); int comparar_numero(int c,int tabla[]); int main(void) { long n; int t[50], c; printf("\nIntroduce un número para ver si es capicúa :"); scanf("%ld",&n); c=numero(n,t); if(comparar_numero(c,t)) printf("\nEl número es capicúa \n "); else printf("\nEl número no es capicúa\n"); } int numero(long a,int tabla[]) /*Función que cuenta la cantidad de dígitos en el número*/ { int cifras=0; while(a!=0) { tabla[cifras]=a%10; a=a/10; cifras++; } return cifras; /*Cantidad de dígitos */ } int comparar_numero(int c,int tabla[]) /*Función que compara los dígitos*/ { Elaborada por: M.C. Vicente Fuentes Gea vfg@servidor.unam.mx M.C. Cintia Quezada Reyes cintia@fi-b.unam.mx Ing. Alejandra Vargas E. De los M. alejandrav@correo.unam.mx 5 PRÁCTICA ARREGLOS CON FUNCIONES int i=0; while(i<c) { if(tabla[i]!=tabla[c-1]) return 0; /*El número no es capicúa*/ i++; c--; } return 1; /*El número es capicúa*/ } Ejemplo 3. Análisis de regresión lineal Se desea ajustar parejas de datos experimentales xi , y i a la ecuación de la recta: y = mx + b en donde m es la pendiente y b la ordenada al origen. De acuerdo con el método de los mínimos cuadrados estos coeficientes, llamados coeficientes de regresión, y el coeficiente de correlación r, se obtienen como sigue: n m= n n n∑ xi y i − ∑ xi ∑ y i i =1 i =1 i =1 n∑ x − ∑ xi i =1 i =1 b = y − mx n n 2 i 2 n r= n n i =1 i =1 n∑ xi yi − ∑ xi ∑ yi i =1 n 2 n n 2 n 2 n∑ xi − ∑ xi n∑ yi − ∑ yi i =1 i =1 i =1 i =1 2 En las anteriores ecuaciones n representa el número de parejas de datos xi , y i y x , y su valor promedio, respectivamente. Hacer un programa que, mediante la invocación a una función denominada RegLin efectúa un análisis de regresión lineal sobre parejas de datos contenidas en dos arreglos. La función RegLin lleva a cabo una análisis de regresión con datos contenidos en los arreglos x[], y[]; también recibe en la variable n el número de datos que contienen los arreglos. Como la función entrega tres resultados, se le envía un arreglo de dos elementos Elaborada por: M.C. Vicente Fuentes Gea vfg@servidor.unam.mx M.C. Cintia Quezada Reyes cintia@fi-b.unam.mx Ing. Alejandra Vargas E. De los M. alejandrav@correo.unam.mx 6 PRÁCTICA ARREGLOS CON FUNCIONES mb[2], de modo que ahí ponga los coeficientes de regresión m, b. El coeficiente de correlación lo regresa de manera normal, usando la instrucción return. /*Ejemplo 3: Análisis de regresión lineal*/ #include <stdio.h> #include <math.h> float RegLin(float x[], float y[], int n, float mb[2]) { /* Ajusta por el método de los mínimos cuadrados los datos contenidos en los arreglos x[], y[] a la recta y = mx + b, retornando el coeficiente de correlación r de la manera usual. Los valores de m, b los entrega en el arreglo mb[2].*/ int i ; float xy, x2, y2, sx, sy, sx2, sy2, sxy ; float r ; sx = sy = sx2 = sy2 = sxy = 0; /* primero se obtienen las sumatorias*/ for(i = 0; i < n; i++) { sx += x[i] ; /* suma de x's*/ sy += y[i] ; /* suma de y's*/ sx2 += x[i] * x[i] ; /* suma de x's al cuadrado*/ sy2 += y[i] * y[i] ; /* suma de y's al cuadrado*/ sxy += x[i] * y[i] ; /* suma de productos x*y's*/ } xy = n * sxy - sx * sy ; x2 = n * sx2 - sx * sx ; y2 = n * sy2 - sy * sy ; /* se hacen unos cálculos adicionales*/ mb[0] = xy / x2 ; mb[1] = sy / n - mb[0] * sx / n ; r = xy / sqrt(x2 * y2) ; return r; /* pendiente*/ /* ordenada al origen*/ /* coeficiente de correlación*/ } int main(void) { float mb[2], r; /* se forman dos conjuntos de datos de prueba*/ float x[7] = {12, 18, 24, 30, 36, 42, 48}; float y[7] = {5.27, 5.68, 6.25, 7.21, 8.02, 8.71, 8.42}; r = RegLin(x, y, 7, mb); printf("Analisis de regresión: y = mx + b \n"); Elaborada por: M.C. Vicente Fuentes Gea vfg@servidor.unam.mx M.C. Cintia Quezada Reyes cintia@fi-b.unam.mx Ing. Alejandra Vargas E. De los M. alejandrav@correo.unam.mx 7 PRÁCTICA ARREGLOS CON FUNCIONES printf("m = %f\nb = %f\nCoeficiente de correlación r = %f\n",mb[0], mb[1], r); return 0; } Errores más comunes que se pueden cometer: 1. Omitir el tipo de valor de regreso definido para una función en la declaración del prototipo, olvidando escribir un valor de retorno. 2. Regresar un valor de una función que fue declarada como void. 3. Volver a definir dentro de la función una variable como local, siendo que ésta fue declarada como variable paramétrica dentro de los paréntesis de la función. Ejercicios propuestos Nota: Realizar el algoritmo antes de elaborar el programa 1. Programar un algoritmo que obtenga la moda de un cierto número de valores dados por el usuario. La moda es el número que aparece con más frecuencia en un conjunto de datos. 2. Hacer un programa que utilizando una función, reciba un arreglo de números reales y entregue el número mayor. 3. Variar el programa anterior obteniendo el número menor. 4. Hacer un programa que utilizando una función, reciba un arreglo de números reales y entregue el valor promedio y la desviación estándar de los datos en un arreglo de dos elementos. 5. Diseñar un programa que determine la distribución de frecuencias de un conjunto de datos dados desde el teclado y colocados en un arreglo de reales. Las frecuencias deberán obtenerse en NI intervalos de clase. (Sugerencia: Utilizar las funciones desarrolladas en los problemas 2 y 3 para calcular los valores máximo y mínimo de los datos, y dividir este intervalo en los NI intervalos de clase). 1. Hacer un programa que interpole linealmente entre y1 y y2 cada dµ de acuerdo con la siguiente fórmula: yint = (1 - µ)y1 + µy2 en donde 0 ≤ µ ≤ 1; µ = 0 en y1, µ = 1 en y2 El programa debe invocar a una función a la cual se le proporcionan los extremos del intervalo de interpolación y1 y y2, el número de datos a interpolar n, y dos arreglos vacíos x[], y[], en donde deberán colocarse los valores interpolados. Elaborada por: M.C. Vicente Fuentes Gea vfg@servidor.unam.mx M.C. Cintia Quezada Reyes cintia@fi-b.unam.mx Ing. Alejandra Vargas E. De los M. alejandrav@correo.unam.mx 8 PRÁCTICA ARREGLOS CON FUNCIONES Posteriormente el programa debe invocar a otra función que tabule los valores (1 − 0) ). contenidos en los dos arreglos mencionados. (Ayuda: dµ = n 7. Repetir el ejercicio 6 usando la interpolación coseno, cuya fórmula es: (1 − cos( µπ )) µ2 = 2 yint = (1 – µ2)y1 + µ2y2 8. Hacer un programa que utilizando una función, reciba un arreglo de números enteros y calcule el promedio de los que estén en posiciones pares. 9. Hacer un programa que utilizando una función, reciba un arreglo de números enteros y calcule el promedio de los que estén en posiciones impares. 10. Hacer un programa que utilizando una función, contabilice los dígitos de un número entero y posteriormente indique si un número entero tiene más de dos dígitos. 11. Realizar un programa donde se ingrese un número y cada dígito sea cambiado con base en la tabla siguiente: Dígito 0 1 2 3 4 5 6 7 8 9 Cambiar por 9 5 4 2 7 6 1 3 0 8 (Sugerencia: Utilizar dos funciones, una para obtener cada dígito que conforma el número y otra para cambiarlo con base en la tabla anterior). Posteriormente visualizar el número que resulta de la modificación. Elaborada por: M.C. Vicente Fuentes Gea vfg@servidor.unam.mx M.C. Cintia Quezada Reyes cintia@fi-b.unam.mx Ing. Alejandra Vargas E. De los M. alejandrav@correo.unam.mx 9