Herramientas de usuario

Herramientas del sitio


curso-cpp:modularizacion-funciones

Diferencias

Muestra las diferencias entre dos versiones de la página.

Enlace a la vista de comparación

Ambos lados, revisión anterior Revisión previa
Próxima revisión
Revisión previa
curso-cpp:modularizacion-funciones [2017/09/14 19:05]
santo [Parámetros]
curso-cpp:modularizacion-funciones [2017/10/29 19:24] (actual)
santo
Línea 15: Línea 15:
 Supongamos que tenemos el siguiente código (que iría dentro de ''​main''​ en un programa): Supongamos que tenemos el siguiente código (que iría dentro de ''​main''​ en un programa):
  
-<​code>​+<​code ​cpp>
 int a,b; int a,b;
 cout << "​Ingrese el rango de numeros a explorar"​ << endl; cout << "​Ingrese el rango de numeros a explorar"​ << endl;
Línea 42: Línea 42:
 Es muy difícil de entender qué hace este código a simple vista, y el motivo principal es que **hace muchas cosas mezcladas todas a la vez**. Veremos que una función permite **separar** una porción de programa definida, y luego **usarla** cuando la necesitemos. Es bueno comparar el tener que leer y entender el programa anterior, con leer algo como lo siguiente: Es muy difícil de entender qué hace este código a simple vista, y el motivo principal es que **hace muchas cosas mezcladas todas a la vez**. Veremos que una función permite **separar** una porción de programa definida, y luego **usarla** cuando la necesitemos. Es bueno comparar el tener que leer y entender el programa anterior, con leer algo como lo siguiente:
  
-<​code>​+<​code ​cpp>
 int a,b; int a,b;
 leerRangoAExplorar(a,​b);​ leerRangoAExplorar(a,​b);​
Línea 50: Línea 50:
 Aquí, ''​leerRangoAExplorar(a,​b);''​ corresponderá al siguiente fragmento del código anterior: Aquí, ''​leerRangoAExplorar(a,​b);''​ corresponderá al siguiente fragmento del código anterior:
  
-<​code>​+<​code ​cpp>
 cout << "​Ingrese el rango de numeros a explorar"​ << endl; cout << "​Ingrese el rango de numeros a explorar"​ << endl;
 cin >> a >> b; cin >> a >> b;
Línea 57: Línea 57:
 Mientras que ''​sumaDePrimosAlCuadradoEnRango(a,​b)''​ representa: Mientras que ''​sumaDePrimosAlCuadradoEnRango(a,​b)''​ representa:
  
-<​code>​+<​code ​cpp>
 int sumaPrimosAlCuadrado = 0; int sumaPrimosAlCuadrado = 0;
 for (int i=a; i<= b; i++) for (int i=a; i<= b; i++)
Línea 73: Línea 73:
 ''​sumaDeMultiplosEspecialesEnRango(a,​b)''​ corresponde al: ''​sumaDeMultiplosEspecialesEnRango(a,​b)''​ corresponde al:
  
-<​code>​+<​code ​cpp>
 int sumaMultiplosEspeciales = 0; int sumaMultiplosEspeciales = 0;
 for (int i=a; i<= b; i++) for (int i=a; i<= b; i++)
Línea 84: Línea 84:
 Y el ''​mostrarResultados''​ corresponde al: Y el ''​mostrarResultados''​ corresponde al:
  
-<​code>​+<​code ​cpp>
 cout << "La primera suma pedida es:" << sumaPrimosAlCuadrado << endl; cout << "La primera suma pedida es:" << sumaPrimosAlCuadrado << endl;
 cout << "La segunda suma pedida es:" << sumaMultiplosEspeciales << endl; cout << "La segunda suma pedida es:" << sumaMultiplosEspeciales << endl;
Línea 112: Línea 112:
 Finalmente, llamaremos ''​mostrarResultados''​ al proceso del paso 4), que **usa los resultados obtenidos en los pasos 2 y 3**. Con estas ideas, podemos planear un ''​esqueleto''​ de nuestro programa, que quedaría más o menos así: Finalmente, llamaremos ''​mostrarResultados''​ al proceso del paso 4), que **usa los resultados obtenidos en los pasos 2 y 3**. Con estas ideas, podemos planear un ''​esqueleto''​ de nuestro programa, que quedaría más o menos así:
  
-<​code>​+<​code ​cpp>
 int a,b; int a,b;
 leerRangoAExplorar(a,​b);​ leerRangoAExplorar(a,​b);​
Línea 134: Línea 134:
 La sintaxis para definir una función es la siguiente: La sintaxis para definir una función es la siguiente:
  
-<​code>​+<​code ​cpp>
 tipo_de_la_respuesta nombreDeLaFuncion(lista_de_parametros) tipo_de_la_respuesta nombreDeLaFuncion(lista_de_parametros)
 { {
Línea 148: Línea 148:
 Veamos un ejemplo de función con ''​lista_de_parametros''​ vacía, lo cual es válido en C++: Veamos un ejemplo de función con ''​lista_de_parametros''​ vacía, lo cual es válido en C++:
  
-<​code>​+<​code ​cpp>
 int leerUnNumeroYElevarloAlCuadrado() int leerUnNumeroYElevarloAlCuadrado()
 { {
Línea 165: Línea 165:
 Veamos a continuación un ejemplo de programa completo que usa esa función: Veamos a continuación un ejemplo de programa completo que usa esa función:
  
-<​code>​+<​code ​cpp>
 #include <​iostream>​ #include <​iostream>​
  
Línea 192: Línea 192:
 Así, si al ejecutar el programa anterior ingresáramos los valores 3, 1, y 10, sería como si en el main se ejecutase lo siguiente: Así, si al ejecutar el programa anterior ingresáramos los valores 3, 1, y 10, sería como si en el main se ejecutase lo siguiente:
  
-<​code>​+<​code ​cpp>
 int main() int main()
 { {
Línea 204: Línea 204:
 Obteniendo el resultado 110. A modo de ejemplo, damos una versión distinta del programa que calcula la suma del **triple** de cada número al cuadrado, para que quede claro que las llamadas a funciones se pueden usar en el medio de expresiones más complejas si así nos conviene (damos solo el main, pues la función es igual que antes): Obteniendo el resultado 110. A modo de ejemplo, damos una versión distinta del programa que calcula la suma del **triple** de cada número al cuadrado, para que quede claro que las llamadas a funciones se pueden usar en el medio de expresiones más complejas si así nos conviene (damos solo el main, pues la función es igual que antes):
  
-<​code>​+<​code ​cpp>
 int main() int main()
 { {
Línea 216: Línea 216:
 Incluso sería válido (aunque es más difícil de leer) escribir el programa original con todas las llamadas en la misma línea: Incluso sería válido (aunque es más difícil de leer) escribir el programa original con todas las llamadas en la misma línea:
  
-<​code>​+<​code ​cpp>
 int main() int main()
 { {
Línea 239: Línea 239:
 Veamos a continuación el ejemplo de la función para elevar un entero al cuadrado: Veamos a continuación el ejemplo de la función para elevar un entero al cuadrado:
  
-<​code>​+<​code ​cpp>
 int alCuadrado(int x) int alCuadrado(int x)
 { {
Línea 252: Línea 252:
 Veamos un ejemplo completo de programa que usa la función ''​alCuadrado'':​ Veamos un ejemplo completo de programa que usa la función ''​alCuadrado'':​
  
-<​code>​+<​code ​cpp>
 #include <​iostream>​ #include <​iostream>​
  
Línea 279: Línea 279:
 Una función puede necesitar varios datos para realizar su tarea. De ser así, se trabaja de idéntica manera pero separando los parámetros con comas, y dándolos siempre en el mismo orden. Por ejemplo, a continuación se muestra un ejemplo de código que usa una función que pega dos palabras usando un guión entre ellas: Una función puede necesitar varios datos para realizar su tarea. De ser así, se trabaja de idéntica manera pero separando los parámetros con comas, y dándolos siempre en el mismo orden. Por ejemplo, a continuación se muestra un ejemplo de código que usa una función que pega dos palabras usando un guión entre ellas:
  
-<​code>​+<​code ​cpp>
 #include <​iostream>​ #include <​iostream>​
  
Línea 310: Línea 310:
 ¿Por qué podríamos querer que una función no devuelva nada? Porque podría importarnos solamente lo que la función **hace**, es decir, las instrucciones que ejecuta, sin necesidad de que nos devuelva un valor final. Un ejemplo sencillo de esto podría ser alguna función que escriba en pantalla: ¿Por qué podríamos querer que una función no devuelva nada? Porque podría importarnos solamente lo que la función **hace**, es decir, las instrucciones que ejecuta, sin necesidad de que nos devuelva un valor final. Un ejemplo sencillo de esto podría ser alguna función que escriba en pantalla:
  
-<​code>​+<​code ​cpp>
 void mostrarConEspacios(string palabra) void mostrarConEspacios(string palabra)
 { {
Línea 332: Línea 332:
 Supongamos que escribimos la siguiente función, con la idea de que aumente en uno la variable indicada: Supongamos que escribimos la siguiente función, con la idea de que aumente en uno la variable indicada:
  
-<​code>​+<​code ​cpp>
 void incrementar(int x) void incrementar(int x)
 { {
Línea 341: Línea 341:
 Con lo que vimos hasta ahora, podría parecer que esta función hará lo que queremos. Podemos intentar utilizarla en un programa: Con lo que vimos hasta ahora, podría parecer que esta función hará lo que queremos. Podemos intentar utilizarla en un programa:
  
-<​code>​+<​code ​cpp>
 #include <​iostream>​ #include <​iostream>​
  
Línea 367: Línea 367:
 Para ayudar a entender esto agregaremos al programa un par de instrucciones con ''​cout''​ dentro de la función, para ver si se incrementa o no. Para ayudar a entender esto agregaremos al programa un par de instrucciones con ''​cout''​ dentro de la función, para ver si se incrementa o no.
  
-<​code>​+<​code ​cpp>
 #include <​iostream>​ #include <​iostream>​
  
Línea 413: Línea 413:
 Nuestro ejemplo quedaría entonces (solamente le agregamos un ''&''​ en el parámetro ''​x''​):​ Nuestro ejemplo quedaría entonces (solamente le agregamos un ''&''​ en el parámetro ''​x''​):​
  
-<​code>​+<​code ​cpp>
 #include <​iostream>​ #include <​iostream>​
  
Línea 463: Línea 463:
 Un ejemplo podría ser una función que recibe un ''​vector<​int>''​ y duplica todos sus elementos: Un ejemplo podría ser una función que recibe un ''​vector<​int>''​ y duplica todos sus elementos:
  
-<​code>​+<​code ​cpp>
 #include <​iostream>​ #include <​iostream>​
 #include <​vector>​ #include <​vector>​
Línea 510: Línea 510:
 Por ejemplo, el siguiente código: Por ejemplo, el siguiente código:
  
-<​code>​+<​code ​cpp>
 int mivar = 32; int mivar = 32;
  
Línea 534: Línea 534:
  
   * En las funciones se puede llamar (utilizar) otras funciones: esto está totalmente permitido:   * En las funciones se puede llamar (utilizar) otras funciones: esto está totalmente permitido:
-    <​code>​+    <​code ​cpp>
     int multiplicar(int a, int b)     int multiplicar(int a, int b)
     {     {
Línea 554: Línea 554:
  
   * Nuestro primer ejemplo es la función ''​main'',​ que ya venimos usando en todos nuestros programas: Es una función que devuelve un ''​int'',​ que usa la computadora para saber si hubo errores. Por convención,​ se debe devolver cero si todo salió bien, y por eso es buena costumbre terminar todos los programas con ''​return 0''​. La función ''​main''​ es importante porque tiene la característica especial de que allí comienzan a ejecutarse todos nuestros programas, aunque tengan otras funciones.   * Nuestro primer ejemplo es la función ''​main'',​ que ya venimos usando en todos nuestros programas: Es una función que devuelve un ''​int'',​ que usa la computadora para saber si hubo errores. Por convención,​ se debe devolver cero si todo salió bien, y por eso es buena costumbre terminar todos los programas con ''​return 0''​. La función ''​main''​ es importante porque tiene la característica especial de que allí comienzan a ejecutarse todos nuestros programas, aunque tengan otras funciones.
-  * Como ejemplo de pensamiento top-down, supongamos que debemos realizar un programa que lea una secuencia de números, y luego calcule y muestre por pantalla la suma, el máximo y el mínimo de todos estos números. Podemos programar primero que anda el main de la siguiente manera:<​code>​+  * Como ejemplo de pensamiento top-down, supongamos que debemos realizar un programa que lea una secuencia de números, y luego calcule y muestre por pantalla la suma, el máximo y el mínimo de todos estos números. Podemos programar primero que anda el main de la siguiente manera:<​code ​cpp>
 int main() int main()
 { {
Línea 562: Línea 562:
     return 0;     return 0;
 } }
-</​code>​ Donde nos hemos ordenado y hemos logrado **descomponer** el problema entero en tareas más pequeñas. Luego podríamos agregarle las funciones que faltan al programa, para completarlo,​ dejando inalterado el mismo main que ya escribimos: <​code>​+</​code>​ Donde nos hemos ordenado y hemos logrado **descomponer** el problema entero en tareas más pequeñas. Luego podríamos agregarle las funciones que faltan al programa, para completarlo,​ dejando inalterado el mismo main que ya escribimos: <​code ​cpp>
 vector<​int>​ leerNumeros() vector<​int>​ leerNumeros()
 { {
Línea 589: Línea 589:
 </​code>​ </​code>​
  
-  * El siguiente es un ejemplo con funciones que calculan áreas de figuras geométricas,​ que muestra como podemos reutilizar ciertas funciones dentro de otras: <​code>​+  * El siguiente es un ejemplo con funciones que calculan áreas de figuras geométricas,​ que muestra como podemos reutilizar ciertas funciones dentro de otras: <​code ​cpp>
 int areaParalelogramo(int base, int altura) int areaParalelogramo(int base, int altura)
 { {
Línea 603: Línea 603:
 } }
 </​code>​ </​code>​
-  * El siguiente es un ejemplo de función que recibe dos variables enteras, e intercambia sus valores. ¡Notar el uso del ampersand! <​code>​+  * El siguiente es un ejemplo de función que recibe dos variables enteras, e intercambia sus valores. ¡Notar el uso del ampersand! <​code ​cpp>
 void intercambiar(int &​variable1,​ int &​variable2) void intercambiar(int &​variable1,​ int &​variable2)
 { {
Línea 609: Línea 609:
     variable1 = variable2;     variable1 = variable2;
     variable2 = auxiliar;     variable2 = auxiliar;
-} </​code>​ Similarmente,​ el siguiente ejemplo permite "​rotar"​ los valores de tres variables dadas: Es decir, transforma [a,b,c] en [b,c,a]: <​code>​+} </​code>​ Similarmente,​ el siguiente ejemplo permite "​rotar"​ los valores de tres variables dadas: Es decir, transforma [a,b,c] en [b,c,a]: <​code ​cpp>
 void rotar3(int &a, int &b, int &c) void rotar3(int &a, int &b, int &c)
 { {
Línea 630: Línea 630:
 ===== Algunos errores comunes ===== ===== Algunos errores comunes =====
  
-   * Pasar a la función una cantidad de parámetros diferente de las que la función necesita, o con el tipo incorrecto. Por ejemplo si tenemos la función <​code>​+   * Pasar a la función una cantidad de parámetros diferente de las que la función necesita, o con el tipo incorrecto. Por ejemplo si tenemos la función <​code ​cpp>
 int mayor(int num1, int num2) int mayor(int num1, int num2)
 { {
Línea 638: Línea 638:
         return num2;         return num2;
 } }
-</​code>​ serían incorrectas las siguientes llamadas: <​code>​+</​code>​ serían incorrectas las siguientes llamadas: <​code ​cpp>
 mayor(k,​m,​n) // Pasa 3 parámetros,​ pero la función toma solamente 2 mayor(k,​m,​n) // Pasa 3 parámetros,​ pero la función toma solamente 2
 mayor(23, "​miliwatt"​) // Pasa 2 parámetros,​ pero el segundo es una cadena y debería ser un int mayor(23, "​miliwatt"​) // Pasa 2 parámetros,​ pero el segundo es una cadena y debería ser un int
Línea 663: Línea 663:
 Mediante un ''#​define'',​ es posible definir lo que se denomina una //macro//, que es una regla para **reemplazar textualmente un fragmento de código en el programa**. Por ejemplo, supongamos que colocamos en cualquier línea de un programa, el siguiente ''#​define'':​ Mediante un ''#​define'',​ es posible definir lo que se denomina una //macro//, que es una regla para **reemplazar textualmente un fragmento de código en el programa**. Por ejemplo, supongamos que colocamos en cualquier línea de un programa, el siguiente ''#​define'':​
  
-<​code>​+<​code ​cpp>
 #define declaraEInicializaEnUnValor(nombreVariable,​ valor) int nombreVariable = valor #define declaraEInicializaEnUnValor(nombreVariable,​ valor) int nombreVariable = valor
 </​code>​ </​code>​
Línea 670: Línea 670:
 Por ejemplo,el siguiente sería un programa válido: Por ejemplo,el siguiente sería un programa válido:
  
-<​code>​+<​code ​cpp>
 #include <​iostream>​ #include <​iostream>​
  
Línea 688: Línea 688:
 Que muestra por pantalla 140. Notar que luego de los reemplazos, el programa es absolutamente equivalente a si se hubiera escrito directamente:​ Que muestra por pantalla 140. Notar que luego de los reemplazos, el programa es absolutamente equivalente a si se hubiera escrito directamente:​
  
-<​code>​+<​code ​cpp>
 #include <​iostream>​ #include <​iostream>​
  
Línea 708: Línea 708:
 Especialmente en competencias de programación,​ es muy común tener un fragmento de código como el siguiente: Especialmente en competencias de programación,​ es muy común tener un fragmento de código como el siguiente:
  
-<​code>​+<​code ​cpp>
 for (int numero = 0; numero < valorMaximo;​ numero++) for (int numero = 0; numero < valorMaximo;​ numero++)
     // instrucciones     // instrucciones
Línea 717: Línea 717:
 Otra variante muy similar sería cuando queremos recorrer todos los índices de un cierto vector: Otra variante muy similar sería cuando queremos recorrer todos los índices de un cierto vector:
  
-<​code>​+<​code ​cpp>
 for (int var = 0; var < int(vector.size());​ var++) for (int var = 0; var < int(vector.size());​ var++)
     // instrucciones     // instrucciones
Línea 726: Línea 726:
 Para programar más fácilmente y con menor chances de errores este tipo de for comunes, podemos utilizar un ''#​define''​ para definir una forma compacta de indicar los elementos importantes que cambian de caso en caso, y que el resto se reemplace mecánicamente siempre igual: Para programar más fácilmente y con menor chances de errores este tipo de for comunes, podemos utilizar un ''#​define''​ para definir una forma compacta de indicar los elementos importantes que cambian de caso en caso, y que el resto se reemplace mecánicamente siempre igual:
  
-<​code>​+<​code ​cpp>
 #define forn(i,n) for(int i=0;​i<​int(n);​i++) #define forn(i,n) for(int i=0;​i<​int(n);​i++)
 </​code>​ </​code>​
Línea 734: Línea 734:
 De esta forma, una vez que tenemos este #define el primer for que mostramos nos quedaría simplemente:​ De esta forma, una vez que tenemos este #define el primer for que mostramos nos quedaría simplemente:​
  
-<​code>​+<​code ​cpp>
 forn(numero,​ valorMaximo) forn(numero,​ valorMaximo)
     // instrucciones     // instrucciones
Línea 741: Línea 741:
 Y el segundo quedaría: Y el segundo quedaría:
  
-<​code>​+<​code ​cpp>
 forn(var, vector.size()) forn(var, vector.size())
     // instrucciones     // instrucciones
Línea 748: Línea 748:
 Vemos que ahora solamente hace falta especificar **una vez** el nombre de la variable, y todo lo demás es copiado automáticamente en forma mecánica por el ''#​define''​. Vemos que ahora solamente hace falta especificar **una vez** el nombre de la variable, y todo lo demás es copiado automáticamente en forma mecánica por el ''#​define''​.
  
-Se puede consultar [[cpp-avanzado:​macros |aquí]] otros ejemplos de macros muy útiles para programación competitiva,​ además del ''​forn''​ ya mostrado.+Se puede consultar [[cpp-avanzado:​macros |aquí]] otros ejemplos de macros ​más avanzadas, ​muy útiles para programación competitiva,​ además del ''​forn''​ ya mostrado.
 ==== Por qué es mejor usar funciones ==== ==== Por qué es mejor usar funciones ====
  
Línea 755: Línea 755:
 Supongamos que queremos tener un fragmento de código para elevar un número al cuadrado. La forma más simple de hacerlo es multiplicar al número con sí mismo, ya que multiplicar es una operación atómica disponible. Podemos entonces pensar en hacer un ''#​define''​ para ello: Supongamos que queremos tener un fragmento de código para elevar un número al cuadrado. La forma más simple de hacerlo es multiplicar al número con sí mismo, ya que multiplicar es una operación atómica disponible. Podemos entonces pensar en hacer un ''#​define''​ para ello:
  
-<​code>​+<​code ​cpp>
 #define cuadrado(x) x*x #define cuadrado(x) x*x
 </​code>​ </​code>​
Línea 761: Línea 761:
 De esta forma, cuando escribamos ''​cuadrado(2)'',​ por ejemplo, se reemplaza por ''​2*2'',​ que es el número al cuadrado como queremos. Sin embargo, el ''#​define''​ que acabamos de definir es muy peligroso de utilizar: imaginemos por ejemplo que lo usamos en la siguiente línea: De esta forma, cuando escribamos ''​cuadrado(2)'',​ por ejemplo, se reemplaza por ''​2*2'',​ que es el número al cuadrado como queremos. Sin embargo, el ''#​define''​ que acabamos de definir es muy peligroso de utilizar: imaginemos por ejemplo que lo usamos en la siguiente línea:
  
-<​code>​+<​code ​cpp>
 cout << cuadrado(2+3) << endl; cout << cuadrado(2+3) << endl;
 </​code>​ </​code>​
Línea 771: Línea 771:
 Esto podría resolverse si utilizamos **paréntesis en todos lados**: Esto podría resolverse si utilizamos **paréntesis en todos lados**:
  
-<​code>​+<​code ​cpp>
 #define cuadrado(x) ((x)*(x)) #define cuadrado(x) ((x)*(x))
 </​code>​ </​code>​
Línea 777: Línea 777:
 Este ''#​define''​ funciona correctamente,​ pero ahora quedó bastante más feo y difícil de leer. Una función como  Este ''#​define''​ funciona correctamente,​ pero ahora quedó bastante más feo y difícil de leer. Una función como 
  
-<​code>​+<​code ​cpp>
 int cuadrado(int x) int cuadrado(int x)
 { {
curso-cpp/modularizacion-funciones.1505415912.txt.gz · Última modificación: 2017/09/14 19:05 por santo