Funciones en C

Page 1

FUNDAMENTOS DE PROGRAMACION II UNIDAD 1. FUNCIONES INTRODUCCIÓN Una de las herramientas fundamentales a lo largo de la historia de la programación, ha sido la inclusión de funciones, que se comportan como mini programas dentro de otro programa, permitiendo la reducción de espacio, la agrupación de muchas instrucciones repetitivas bajo un mismo nombre, además permiten que los programas sean legibles, estructurados y comprensibles, logrando con esto poder actualizarlos y/o corregirlos de una manera rápida, sin tener que afectar la integridad de todo el programa. En resumen, las funciones sirven para encapsular las operaciones en pequeñas unidades que hacen que los programas sean más claros y más fiables. Definición Podemos definir a las funciones como: • “Una función es simplemente un algoritmo el cual devuelve un único valor al sitio del programa en que fue invocada o llamada”. • “Es un conjunto de instrucciones que cumplen con una tarea específica” • “Una función es una sección de código independiente, con nombre, que ejecuta una tarea específica y opcionalmente devuelve un valor al programa que la llamó”. • Una función es un bloque de código que recibe unos valores de entrada (argumentos) y devuelve un resultado. Declaración de una función (prototipo) Antes de escribir el código de la función, la función como tal debe declararse para que el compilador sepa que existe y cuáles son sus argumentos. La sintaxis de una declaración genérica es: TipoRetorno NombreFunción ( TipoArgumento1 a , TipoArgumento2 b , ... ) ; En las declaraciones de los argumentos debe ponerse el tipo (TipoArgumento1, TipoArgumento2 , etc.) y, opcionalmente, un nombre de variable identificativo (a, b, ...) que será desechado por el compilador. En consecuencia, no tiene por qué coincidir con el que se utilice posteriormente en la definición de dicha función, pero puede ayudar a identificar qué tipo de argumento se está pasando a la función. Por ejemplo, si se lee: double CosteTotal (int unidades, double precio); Queda bastante claro el objetivo de dicha función y qué papel juega cada argumento, bastante mejor que un simple: double CosteTotal (int, double); Si no se especifica el tipo de retorno, se asumirá int por defecto, aunque se recomienda especificarlo siempre por razones de claridad.


Definición de una función (implementación) Definir una función es describir lo que hace. Una función sólo puede ser definida una vez y en cualquier parte del programa, excepto dentro de otra función. La sintaxis de la implementación de una función es: TipoRetorno NombreFunción (Tipo1 i , Tipo2 j , Tipo3 k ) { Sentencia1; ... SentenciaN; } Llamada a la función En el código se debe llamar a una función por su nombre y pasarle las variables de los argumentos entre paréntesis (obligatorios aunque no tenga parámetros, o sea tipo void). Los parámetros que entran en la función deben ser del mismo tipo que los declarados en el prototipo y en la definición, en caso contrario se recomienda realizar una conversión (casting) para evitar errores de compilación y ejecución. Retorno de valores La sentencia return es necesaria para poder retornar valores desde las funciones. Su sintaxis es: return expresión ; La expresión debe ser del mismo tipo o convertible al tipo de retorno de la función. Si no se pudiese convertir, el compilador daría un aviso (warning) o un error. Siempre es recomendable retornar un valor para poder verificar la correcta ejecución de la función; en este caso el retorno no está asociado a ninguna operación con los argumentos, sino con el correcto funcionamiento del programa. Se pueden declarar funciones que no devuelven ningún valor, son declaradas como void. Por ello puede omitirse la sentencia return y, en caso de ponerla, se debe escribir sin la expresión. En consecuencia, la estructura de un programa en C++ quedaría así:

[directivas del pre-procesador: includes y defines] [declaración de variables y constantes globales] [prototipos de funciones] función main () { //instrucciones programa principal } [definiciones de funciones]//definidas en los prototipos


Ejemplos Funciones que devuelven un valor //******************************************************** // Programa que permite calcular el área y el perimetro de un rectangulo // mediante a la utilización de funciones //******************************************************** #include <iostream.h> #include <conio.h> float area, perim, base, altura; float area_rec (float x, float y); float peri_rec (float x, float y);

//prototipo de funciones

// Función principal int main() { cout << “Introduzca la base y altura del rectángulo:” << endl; cin >> base; cin >> altura;

Se está pasando valores a la función area_rec, primero el area = area_rec(base, altura); // llamado a la función “area_rec” valor base a x y segundo el perim = peri_rec(base, altura); // llamado a la función “peri_rec” valor altura a y.

cout << “El área del rectángulo es: “ <<area << endl; out << “El perimetro del rectángulo es: “ <<perim << endl; getch(); return 0; } // Función area_rec float area_rec (float x, float y) { float r; r= x*y; return r; } // Función peri_rec float peri_rec (float x, float y) { float r; r= 2*x+2*y; return r; }


Funciones que no devuelven ningún valor. //******************************************************** // Programa que dado un número entero determina si es par o impar, //usando funciones. //******************************************************** #include <stdio.h> #include <conio.h> void par_impar (int a); int main() { int a; printf("Ingrese el valor de a:\n"); scanf("%d", &a); par_impar(a); /*Llamado de la función*/ getch(); return 0; } void par_impar(int a) { int r; r=a % 2; if (r===) printf("El número es %d es par\n\n", a); else printf("El número es %d es impar\n\n", a); }

Ejercicios propuestos •

Implementar un programa que mediante el uso de funciones, convierta una distancia expresada en metros a su equivalente en millas y kilometros.

Implementar un programa que mediante el uso de funciones, averigue si un número dado es perfecto o no. Un número perfecto es aquel cuya suma de sus divisores da como resultado el mismo número.

Implementar un programa que mediante el uso de funciones, calcule el mayor de tres números introducidos por teclado por teclado.


Ámbito o alcance (scope) de variables Las variables son una entidad fundamental en cualquier programa, sus valores deciden el resultado de la ejecución del programa. El cambio en los valores de una variable se produce en dos casos: el código la modifica conforme a las necesidades del programa, o bien, se producen errores en la gestión de memoria por parte del sistema operativo o de ejecución del programa. El primer caso es el deseable, el segundo el impredecible. Hay que aceptar que las variables son entidades frágiles, sólo existen en un lugar de la memoria del ordenador por un espacio reducido de tiempo, por ello hay que cuidarlas al máximo. El riesgo de que se produzca un cambio en una variable de forma involuntaria aumenta de acuerdo con el ámbito de la variable. El ámbito o alcance de una variable es el lugar donde ha sido declarada, ese espacio de código en el que existe y desde el que puede ser modificada. Es lógico pensar que cuantas más variables maneje el programa y cuanto mayor sea su ámbito, más probabilidades habrá que los valores en memoria puedan variar bruscamente por errores de ejecución o de gestión de memoria. Sobre todo si el código crece por la colaboración de varios programadores. En general, es deseable que las variables tengan la vida lo más corta posible y que sólo se puedan modificar desde pequeños bloques de código. El alcance en el que pueden estar definidas y, en consecuencia, ser utilizadas las variables son: Variables Globales A las variables que declaramos fuera del cuerpo de cualquier función se dice que tiene un alcance global y por lo tanto estas funciones están disponibles para cualquier función del programa, incluyendo a main (). Esto significa que puede ser modificada desde cualquier punto del programa. Por lo tanto, su gran ventaja es al mismo tiempo su mayor inconveniente. Utilizar variables globales va en contra del encapsulamiento, en consecuencia se deben evitar en lo posible. Se pueden definir variables con el mismo nombre, del mismo o distinto tipo, siempre que no se hayan definido en el mismo campo. Atención porque, al definir con el mismo nombre una variable local y una global, tiene predominancia el valor de la local en el trozo en el que actúa. Variables Locales En C++ está permitido declarar variables en cualquier parte del código fuente. Están delimitados por llaves { y } (no por paréntesis), ya sea de bloque o de función. Bloque: Si declaramos una variable dentro de un bloque {}, la variable sólo será válida dentro de ese bloque y no será accesible desde fuera. Función: Si declaramos una variable dentro de una función, la variable puede ser utilizada en cualquier sitio de la función donde ha sido declarada. Las variables que se pasan en los argumentos de la función siempre se copian localmente, esto significa que se duplican en memoria y que no se modifica su valor al salir de la función. Para alterar sus valores se deberán pasar como apuntadores o referencias, esta propiedad se verá en capítulos posteriores.


Declaración (prototipo):Los nombres que se les da a las variables en la lista de argumentos de la definición de una función son identificadores inútiles y son olvidados por el ordenador. Ejemplo int suma(int valor1, int valor2) { int local; // variable local local = valor1 + valor2; return local; }

Paso de parámetros por Valor: En el caso de parámetros por valor: el valor de la variable que se esté pasando, es asignado a la variable local que es declarada al definir la función. Tanto la variable que se utilice al efectuar la invocación como la que la recibe “por valor” deben ser del mismo tipo, en caso contrario se presentará un error. Es hora de llevar lo anterior a la práctica, realizaremos un ejemplo para determinar cada una de las partes que conforman un programa con funciones: //******************************************************** // Programa que permite realizar una multiplicación // y una suma mediante a la utilización de funciones //******************************************************** #include <iostream.h> void divide (int x, int y); //prototipo de funciones int multiplica (int, int); // Función principal int main() { int x, y,r; Se está pasando valores a la cout << “Introduzca dos numeros” << endl; función divide, primero el cin >> x valor x inicial y en el segundo cin >> y; llamado el valor y inicial divide(x, y); // llama a la función “Divide” divide(y, x); r = multiplica(x, y); Los valores X y Y, se cout << “La multiplicación de X y Y es = a: “ << r << endl; convierten en valorx, return 0; valory, lo mismo sucede en la función multiplica } // Función divide void divide (int valorx, int valory) Variable local, afecta { solo a esta función int respuesta; // variable local respuesta= (valorx / valory;); cout << “La división de los dos valores es: “ << resultado << endl; } // Función multiplica int multiplica(int valorx, int valory) {


int mult; // variable local mult = valorx * valory; return mult;// retorna el valor del proceso } La instrucción RETURN es quien regresa un, y solo un dato a la parte del programa que este llamando o invocando. Sin embargo, es de considerar que return puede regresar un dato, una variable o una expresión algebraica (no ecuación o formula) como lo muestran los siguientes ejemplos: a) return 3.1416; b) return area; c) return x+15/2; El siguiente programa soluciona un sistema lineal de tres incógnitas con tres variables, por el método de Cramer, mediante la utilización de funciones #include <iostream.h> #include <conio.h> // declaración de variables globales float a,b,c,d,e,f,g,h,i,j,k,l; // coeficientes y términos independientes X, Y, Z; // incógnitas a encontrar. void LeerCoeficientes(); // prototipo de función que permite leer los coeficientes void CalculoIncognitas(); // prototipo de función que permite realizar los cálculos void EscribirResultados();// prototipo -función que permite escribir los resultados void main(){ LeerCoeficientes(); // lamado a cada una de las funciones CalculoIncognitas(); EscribirResultados(); } // Desarrollo de la Función que permite leer las variables void LeerCoeficientes() { cout << “Digite términos de la Primera Ecuación: \n”; cout << “ \n”; cout << “Coeficiente de X : “; cin >> a; cout << “Coeficiente de Y : “; cin >> b; cout << “Coeficiente de Z : “; cin >> c; cout << “Término independiente: “; cin >> d; cout << “\nDigite términos de la Segunda Ecuación: \n”; cout << “ \n”; cout << “Coeficiente de X : “; cin >> e; cout << “Coeficiente de Y : “; cin >> f; cout << “Coeficiente de Z : “; cin >> g; cout << “Término independiente: “; cin >> h; cout << “\nDigite términos de la Tercera Ecuación: \n”; cout << “ \n”; cout << “Coeficiente de X : “; cin >> i;


cout << “Coeficiente de Y : “; cin >> j; cout << “Coeficiente de Z : “; cin >> k; cout << “Término independiente: “; cin >> l; } // En esta función se realiza el cálculo de las incognitas void CalculoIncognitas() { float DetX, DetY, DetZ, DetSistema; // Variables locales DetSistema = a*f*k + e*j*c + i*b*g - i*f*c - j*g*a - k*e*b; DetX = d*f*k + h*j*c + l*b*g - l*f*c - j*g*d - k*h*b; DetY = a*h*k + e*l*c + i*l*g - i*h*c - l*g*a - k*e*d; DetZ = a*f*l + e*j*d + i*b*h - i*f*d - j*h*a - l*e*b; X = DetX / DetSistema; Y = DetY / DetSistema; Z = DetZ / DetSistema; } // funcion que permite mostrar por pantalla los resultados void EscribirResultados() { cout << “\n\n”; cout << “X = “ << X << “ Y = “ << Y << “ Z = “ << Z; cout << “\n\nDigite cualquier tecla para terminar...”; getch(); } Observación: Es importante que como futuro programador de computadoras, documente muy bien cada uno de los bloques del programa o las líneas que usted considere de mayor relevancia, los motivos: 1.- Es importante que otras personas entienda lo que usted está haciendo en cada una de las partes del programa 2.- Pasado un tiempo, con toda seguridad usted no recordará que quiso hacer en ese bloque o segmento y esto le ocasionará demoras en su trabajo y por consiguiere perdidas. A continuación se presenta un pequeño taller para que lo resuelva individualmente o con su grupo de trabajo colaborativo •

• •

Las calculadoras, se convierten en un electo esencial en la vida cotidiana, por consiguiente y mediante el uso de funciones, se debe desarrollar una calculadora estándar, con todas las funciones incorporadas, (suma, resta, multiplicación, división, porcentaje, raíz cuadrada …). Si se quiere mejorar el ejercicio anterior, se propone tener un menú, con las opciones estándar y/o científica. Existen muchos ejercicios que despiertan la creatividad, personalmente me inclino por los juegos, pues ellos permiten despertar habilidades propias de los ingenieros (como el ingenio), por lo anterior usted debe desarrollar un pequeño juego, donde se vea reflejada la utilización de funciones.


Paso de parámetros por referencia: “Otra forma de comunicación, adicional al retorno de un valor, el cual puede producir una función, consiste en el paso de parámetros por referencia, en el cual cada variable pasada como parámetro, puede ser modificada por las instrucciones contenidas en el ámbito de la función. En la invocación se pasa la variable de igual forma que se hace por valor, esto es una “desventaja” ya que al ver la instrucción no nos daríamos cuenta si se está pasando por referencia o valor, la costumbre nos haría pensar que es por valor, pero para estar seguros debemos ver la definición de la función; al identificador que recibe, en la definición de la función, se le antepondrá el operador de dirección, &; de esta forma, en la memoria RAM tomará la misma dirección del parámetro de invocación” No nos inquietemos, en el siguiente capítulo se estudiará lo referente a punteros, esto nos permitirá una mayor claridad, sin embargo es bueno que el estudiante vaya indagando acerca de este apasionante tema. Miremos el siguiente ejemplo: donde se hace el intercambio de dos valores en la memoria ram del computador //Paso de parámetros por referencia // #include <stdio.h> #include <iostream.h> void intercambio(int *, int *); // prototipo de la función main() {

}

int a = 20, b = 30; intercambio(&a, &b); // a y b son pasados por referencia cout<<“a es “<<a; cout <<“ b es “ <<b;

void intercambio(int *x, int *y) { int z = *x; // z toma el contenido de la dirección x *x = *y; // x toma el contenido de y *y = z; // contenido de y = z }


Otro ejemplo de paso de parámetros por referencia: Se trata de convertir un valor decimal a binario, en este ejemplo nos aproximamos más a la siguiente unidad, porque tenemos que utilizar un arreglo para su realización #include <iostream.h> int leer(); CalcularBinario(int, int); void main() { int i, decimal, binario[20]; decimal = leer(); CalcularBinario(decimal, binario); } int leer() { int N; cout << “Digite un entero para convertirlo a binario: “; cin >> N; return (N); } CalcularBinario(int N, int *p) { int c,r; c = N >> 1; *p = N % 2; cout <<“\n Leer desde abajo hacia arriba” << *p; while(c){ p++; *p = c % 2; cout << “\n” << *p; c >>= 1; } return 0; }


Recursividad Esta es la propiedad que tienen las funciones en C++ de poder llamarse a sí mismas. Se dice que una función es recursiva cuando se autollama. No todas las funciones pueden llamarse a sí mismas (ser recursivas), deben estar diseñadas especialmente para que tengan una final y no se conviertan en ciclos o bucles infinitos. Es importante notar que cuando una función se llama a sí misma, una nueva copia de esta función es la que se ejecuta. Las variables locales de la segunda función no interfieren con las variables locales de la primera, así mismo, las variables locales no se pueden afectar mutuamente. Tomemos como ejemplo un programa que calcule el factorial de un número entero introducido por el usuario. El factorial está definido como el producto del número en cuestión por todos los números enteros menores que él, de tal manera que el factorial de 5=5*4*3*2*1 = 120. El código puede quedar así: #include <iostream.h> double factorial(int valor); int K=1; // variable global, para un contador general int main() { int num; cout << “Introduzca un numero” << endl; cin >> num; cout << endl; cout << “El factorial del número es “ << factorial(num) << endl; cout << “La función se llamo en forma recursiva “ << k << “ veces” << endl; return 0; } double factorial(int valor) { double R; if(valor<=1) return 1; else { R= (valor*factorial(valor-1)); K = K+1; } return resultado; } 1.) la función se declara de tipo doble, puesto que los valores que retorna la función pueden ser demasiado grandes. 2.) También se utiliza una variable global (K), que sirve de contador, para determinar el número de iteraciones que la función se repite 3.) El programa empieza solicitándole un número entero y después llama por primera vez a la función factorial ( ). La recursividad necesita una condición para terminar el proceso en el momento especifico, por ésta razón, la función factorial ( ) determina en primer lugar si el valor pasado como parámetro de la función es igual a 1, en cuyo


caso la función retorna 1. Si el valor del parámetro es mayor que 1, entonces la función factorial ( ) se llama a sí misma tomando como parámetro el valor original menos uno, multiplicando éste valor por el valor del parámetro original y almacenando el resultado en la variable llamada resultado. (se recomienda realizar una prueba de escritorio para entender un poco más el movimiento de la función y sus iteraciones). Algunas conclusiones De acuerdo a las definiciones dadas podemos, podemos decir lo siguiente: • Una función tiene un único nombre, al utilizar éste nombre en otras partes del programa se pueden ejecutar las instrucciones contenidas en la función. A esto se le conoce como llamar o llamado a la función, e inclusive se puede llamar desde otras funciones • Una función es independiente, es decir pude ejecutar sus tareas sin interferencia ó interferir en otras partes del programa. • Una función ejecuta una tarea específica. Una tarea es un trabajo discreto que un programa debe ejecutar como parte de su desempeño general, por ejemplo mandar una línea de texto a centrar, realizar ordenamientos, realizar cálculos matemáticos, .. • Una función opcionalmente devuelve un valor al programa que la llamó. Cuando un programa llama a una función se ejecutan las instrucciones contenidas en ésta, si el programa lo requiere, éstas instrucciones pueden devolver un valor al programa que llamó a la función mediante la orden return. Otras características importantes de las funciones y/o profundización a las anteriores: • Las funciones están concebidas para devolver valores, por defecto el valor es int, de querer que la función no retorne valor, se le antecede al instrucción “void” o puede tomar cualquier valor como si fuese una variable. • Las funciones deben tener nombres y se aconseja que este nombre identifique claramente lo que hace la función, si se necesita varias palabras para el nombre, se recomienda separarlo con un guión “_” o iniciando con mayúscula la primera letra de la palabra, un ejemplo puede ser “centrar _ palabra”, “Centrar palabra”. • Los parámetros de una función van entre paréntesis y representa los valores de salida, y podemos afirmar que cada parámetro es una variable, en caso de no realizar paso de parámetros, simplemente se escribe el nombre de la función y los paréntesis “llamado()” • Las funciones se comportan exactamente como programas, por lo tanto deben tener un inicio y un fin { } • C++ está soportado mediante funciones, de hecho el programa principal es una función main()


Turn static files into dynamic content formats.

Create a flipbook
Issuu converts static files into: digital portfolios, online yearbooks, online catalogs, digital photo albums and more. Sign up and create your flipbook.