7-FUNCIONES
A medida que nuestro programa se hace grande la lectura de su código fuente se vuelve tediosa de seguir. Por tanto nuestro objetivo va ser acontinuacion romper el código y hacer pequeños piesas modulables reusables y sobretodo mas mantenibles. Es estas pequeñas piezas reciben diferentes nombres:
Modulos
Subrutinas
Metodos
Funciones
En las funciones lo que queremos hacer es tomar un bloque de código, envolverlo y darle un nombre, de esta manera lo que queremos es tratar este bloque de código como una sola cosa. Para nombrar las funciones vamos a utilizar el formato de vervo mas sustantivo. Para ello tendremos un vervo seguido de un sustantivo.
CalcularArea CreaMensaje AnimaImagen
La extraña sensación de que cuando estoy repitiendo demasiadas veces la misma cosa, pienso que tenia que ver la manera deno tener que repetir tantas lo que estoy haciendo y hacerlo de otramanera mas eficiente, respectivamente la hay es encapsularlo en funciones para su reutilización.
Las no muestran valor sino se les indica, para ello es necesario una línea indicando que debe de existir un retorno, el programa no tiene porque saber si quieres devolver un resultado, portanto hay que especificarlo.
Return reultado
Ámbito de funciones, existen funciones globales y locales
MATEMÁTICAS
Las matemáticas son una
herramienta que permite verificar, mediante modelos gráfico-numéricos, los efectos
que pueden generar las variaciones de los elementos o factores que intervienen
en los fenómenos y sucesos que se presentan a lo largo de nuestra vida. En esta
primera unidad se presenta el concepto de función, así como las diversas formas
para su representación.
Se analizarán también los tipos
de funciones, la graficación y las operaciones que pueden haber entre ellas,
con el fin de crear bases sólidas que permitan dar solución práctica a los
diversos problemas que se presentan en el área económico-administrativa. Todo
esto se podrá realizar a través del análisis de situaciones de optimización,
costo total, ingreso, oferta y demanda, y mediante el uso de los diferentes
tipos de funciones y modelos gráficos.
La relación
funcional o función ayuda a describir de manera práctica situaciones que están
presentes en la vida real, en las que un valor o cantidad que varía depende de
la función o determina el valor de otra, por ejemplo
De ahí se
observa que se pueden tener variables o valores que dependen o cambian cuando
un valor determinante varía. Otro ejemplo representativo es el puntaje obtenido
en un juego de tiro al blanco, en el que hay dibujados en un tablero 5 círculos
concéntricos y en cada uno se pueden tener los siguientes valores: 5, 10, 15,
20, 25, iniciando desde el exterior hasta el centro del tablero, como se
muestra en la imagen. Es decir, que la máxima puntuación se obtiene atinándole
al círculo que queda en el centro del tablero (25 puntos), y va disminuyendo
conforme se aleja hacia la orilla, así se obtienen dos conjuntos, uno
correspondiente a los círculos y que se definirá como el conjunto C, y el otro
correspondiente a la puntuación y que se llamará P, esto es:
C = {1, 2, 3, 4, 5}
P = {5, 10,
15, 20, 25}
Ambos
conjuntos están relacionados entre sí, es decir, que ambos dependen el uno del
otro y se puede representar mediante una tabulación o una gráfica
En ambas
representaciones se puede comprobar que para cada elemento del conjunto P
(puntuación) hay un solo valor o elemento que le corresponde del conjunto C
(círculo), es decir, que se cuenta con las siguientes parejas ordenadas: (1,
5), (2, 10), (3, 15), (4, 20), (5, 25).
Otra forma de representación
es mediante un modelo matemático, si consideramos los datos del ejemplo
anterior, se observa que si se acierta en el círculo del centro se tendrán 25
puntos y en el círculo más alejado del centro se obtendrán 5 puntos, así se
observa que existe una situación de dependencia en la que el puntaje dependerá
de a qué círculo del tablero se acierte y cada acierto tiene un valor que
resulta de multiplicar el número del circulo al que se acierta por cinco. Para
llevar a cabo esta operación es necesario conocer el número de círculo al que
se acierta por lo que se puede decir que el número de círculo es el valor que
alimenta al modelo matemático, es decir, que son los valores de entrada y son a
los que hay que multiplicar por cinco, para que dé el resultado del puntaje
obtenido, lo que dará los valores de salida, si se utilizan además variables
que permitan identificar a cada uno de los valores, es decir y para el puntaje
y x para los círculos, podremos obtener la siguiente expresión:
y=5x En donde
y corresponde a una variable dependiente y x a una variable independiente, que
conforman lo que se conoce como función.
Función : Es
la correspondencia entre dos conjuntos: uno de valores de entrada y otro de
valores de salida, en donde existe una regla u operación que determina para
cada valor de entrada un solo valor de salida.
Variable
Dependiente :: Es aquella cuyo valor, propiedad o característica se trata de
cambiar mediante la manipulación de la variable independiente.
Variable
Independiente ::es aquélla que es manipulada en un experimento o evento con el
objeto de estudiar cómo incide sobre la variable dependiente, esto significa
que las variaciones en la variable independiente repercutirán en variaciones en
la variable dependiente.
A
continuación, se muestran los nombres de las partes de una función; se utiliza
la expresión matemática y=5x. Esta expresión, completa, relaciona una variable
independiente con una variable dependiente. La “y” es la llamada variable
dependiente, pues su valor dependerá de los valores que asignemos a la variable
“x”. Por ejemplo, si decidimos dar un valor de x=4, la “y” tomará un valor:
y=5(4)=20. Para cada valor que demos a “x”, “y” tomará a su vez un valor. Por
lo tanto, la “x” es lo que conocemos como variable independiente, pues el valor
que toma no depende de ninguna otra variable y podemos decidirlo. La expresión
completa que contiene a ambas variables, es lo que llamaremos función.
Como se vio en
el tema anterior, la función es la correspondencia de las variables dependiente
e independiente, y a partir de las expresiones algebraicas, existen diferentes
tipos de funciones, las cuales se verán a continuación.
Función
constante: es aquella que tiene la forma:
F(x)=c
En donde c es
un número real
Sea f(x) = 10,
debido a la forma de la función, a la variable x se le puede asignar cualquier
valor que se desee, sin embargo, el resultado de la función será siempre 10.
Observa la
gráfica que se obtiene a partir de la tabla, se presenta una recta paralela al
eje de las X (abscisas) y que f(x) = 10, corta el eje de las Y (ordenadas) en
el punto (0,10).
En este caso,
la x toma los siguientes valores: -15, -10, -5, 0, 5, 10, 15. La variable
independiente toma siempre el mismo valor (la función es constante e indica que
y=10). Se forman entonces 7 pares ordenados (x,y), que son: (-15, 10), (-10,
10), (-5, 10), (0, 10), (5, 10), (10, 10), (15, 10). Hay que recordar que la
variable independiente, x, puede tomar valores no enteros, por lo que existe
una infinidad de pares ordenados aunque no se encuentren expresados en la tabla
que se presenta. La gráfica es una línea recta horizontal (paralela al eje de
las x), que como la función lo indica, pasa por (0, 10). Esta gráfica nos
muestra cómo luce una función lineal.
A continuación
se te presentarán los diversos tipos de funciones y sus gráficas:
Sea f(x) = 2x
+ 4, se observa que se trata de una función lineal en donde: m = 2 b = 4 es
decir, que cuando x = 0, f(x) = y = 4.
Así, se observa que la gráfica es
una línea recta creciente, esto se debe a que m > 0, por lo que conforme “x”
aumenta, también lo hace ”y”, por lo tanto, se trata de una función creciente
ática Tipos de funciones y sus
gráficas En este caso, la x toma los siguientes valores: -3, -2, -1, 0, 1, 2,
3. La variable dependiente toma valores que dependen efectivamente de la
variable independiente. Por ejemplo, para x=-3, y = 2(-3)+4 = -6+4 = -2. Para x=-2,
y = 2(-2)+4 = -4+4 = 0. Para x=-1, y = 2(-1)+4 = -2+4 = 2. Para x=0, y = 2(0)+4
= 0+4 = 4. Para x=1, y = 2(1)+4 = 2+4 = 6. Para x=2, y = 2(2)+4 = 4+4 = 8. Para
x=3, y = 2(3)+4 = 6+4 = 10
Función cuadrática Una función
cuadrática es aquella que tiene la forma:
La forma de la gráfica de una función
cuadrática es una parábola, en donde el vértice es el punto más bajo si la
parábola abre hacia arriba y el vértice es el punto más alto cuando la parábola
abre hacia abajo. Si a > 0, la parábola abre hacia arriba. Si a < 0, la
parábola abre hacia abajo. El vértice está dado por las coordenadas que se
calcula con las siguientes fórmulas: En donde a, b y c son números reales. a ≠
0, mientras que b y c pueden valer cero
Sea , se observa que se trata de una función
cuadrática en donde:
a = 1
b = 4
c = -2
y las coordenadas del vértice:
Por lo que el vértice será:
Gráficamente la función
cuadrática sería como se muestra a continuación:
Observa que la gráfica es una
parábola que abre hacia arriba y que su punto más bajo se encontrará en las
coordenadas del vértice: (-2, -6)
En este caso, la x toma los
siguientes valores: -3, -2, -1, 0, 1, 2, 3. La variable dependiente toma
valores que dependen efectivamente de la variable
independiente. Por ejemplo, para x=-3
Como puedes ver, cada una de las
funciones tiene una representación gráfica que puede mostrar el comportamiento
de una actividad o fenómeno en cualquier Relacionado con la administración,
es importante que conozcas y sepas aplicar las funciones matemáticas, ya que en
algún momento de tu vida laboral te encontrarás con ellas ámbito de tu vida.
Un punto de equilibrio es usado
comúnmente en las empresas u organizaciones para determinar la rentabilidad de
vender X producto.
¿quieres saber cómo? Se te invita
a estudiar los siguientes conceptos:
Es importante mencionar que la
función de ingresos también puede seguir cualquier otro comportamiento
algebraico: cuadrático, lineal, exponencial, entre otros.
A continuación puedes ver un
ejemplo del ingreso.
El planteamiento es: Un club
social que cuenta con 2300 afiliados está por incrementar a los asociados las
cuotas mensuales, quienes actualmente pagan $500.00. Sin embargo, antes de
realizar dicha operación, el consejo directivo realizó una encuesta con la que
determinó que por cada incremento de $50.00 podrían perder a 15 socios
Definiendo una función[editar]
Una función es un conjunto de líneas de código que realizan una tarea específica y puede retornar un valor. Las funciones pueden tomar parámetros que modifiquen su funcionamiento. Las funciones son utilizadas para descomponer grandes problemas en tareas simples y para implementar operaciones que son comúnmente utilizadas durante un programa y de esta manera reducir la cantidad de código. Cuando una función es invocada se le pasa el control a la misma, una vez que esta finalizó con su tarea el control es devuelto al punto desde el cual la función fue llamada.
<tipo> [clase::] <nombre> ( [Parámetros] )
{
cuerpo;
}
Ejemplo de una función
Para comenzar, vamos a considerar el caso en el cual se desea crear la función cuadrado(), que deberá devolver el cuadrado de un número real (de punto flotante), es decir, cuadrado() aceptará números de punto flotante y regresará una respuesta como número flotante.
Nota: aunque para la función que veremos el tipo de retorno coincide con el tipo de parámetro pasado, algunas veces las cosas pueden cambiar, es decir, no es obligatorio que una función reciba un parámetro de un tipo y que tenga que regresar una respuesta de dicho tipo.
// regresar el cuadrado de un número
double Cuadrado(double n)
{
return n*n;
}
Parámetros[editar]
Normalmente, las funciones operan sobre ciertos valores pasados a las mismas ya sea como constantes literales o como variables, aunque se pueden definir funciones que reciban parámetros. Existen dos formas en C++ de pasar parámetros a una función; por referencia o por valor. El hecho es que si en una declaración de función se declaran parámetros por referencia, a los mismos no se les podrá pasar valores literales ya que las referencias apuntan a objetos (variables o funciones) residentes en la memoria; por otro lado, si un parámetro es declarado para ser pasado por valor, el mismo puede pasarse como una constante literal o como una variable. Los parámetros pasados por referencia pueden ser alterados por la función que los reciba, mientras que los parámetros pasados por valor o copia no pueden ser alterados por la función que los recibe, es decir, la función puede manipular a su antojo al parámetro, pero ningún cambio hecho sobre este se reflejará en el parámetro original.
Parámetros por valor
La función cuadrado() (ver arriba) es un clásico ejemplo que muestra el paso de parámetros por valor, en ese sentido la función cuadrado() recibe una copia del parámetro n. En la misma función se puede observar que se realiza un calculo ( n*n ), sin embargo el parámetro original no sufrirá cambio alguno, esto seguirá siendo cierto aún cuando dentro de la función hubiera una instrucción parecida a n = n * n; o n*=n;.
Parámetros por referencia
Para mostrar un ejemplo del paso de parámetros por referencia, vamos a retomar el caso de la función cuadrado, salvo que en esta ocasión cambiaremos ligeramente la sintaxis para definir la misma. Veamos:
// regresar el cuadrado de un número
double cuadrado2(double &n)
{
n *= n;
return n;
}
Al poner a prueba las funciones cuadrado() y cuadrado2() se podrá verificar que la primera de estas no cambia el valor del parámetro original, mientras que la segunda sí lo hace.
Llamar a una función[editar]
para llamar a la función cuadrado() vista anteriormente, podemos emplear:
cout << cuadrado(25);
cout << cuadrado(X);
R = cuadrado(X); // guardar en R el cuadrado de X
Funciones void[editar]
Bajo ciertas circunstancias se deseará escribir funciones que no regresen valor alguno (esto sería algo parecido a escribir procedures en Pascal) y para ello podemos declarar a la función como void. La palabra reservada void es utilizada para declarar funciones sin valor de retorno y también para indicar que una función específica no requiere de parámetros. Por ejemplo, la función pausa() que se verá en seguida, no devolverá valor alguno y la misma no requiere de parámetros.
// esta función requiere de la librería iostream
void pausa(void)
{
cout << "Por favor presione <Enter> HOLA...";
cin.get();
cin.ignore(255, '\n'); // rechazar caracteres introducidos antes de <Enter>
}
;
Notas: se debe de aclarar que el uso de la palabra void dentro de los parentesis es opcional al momento de declarar una función. Así, la función pausa() podría haberse declarado como void pausa(), y la misma puede invocarse como: pausa();.
Funciones anidadas[editar]
A diferencia de Pascal, el lenguaje C, C++ no permite anidar funciones, sin embargo, dentro de una funcíon puede existir la llamada a una o más funciones declaradas previamente, que determinara en cierto punto un resultado para que sea ejecutado cuando el programador lo desee.
Funciones de tipo puntero (*)[editar]
En muchas ocasiones se desea que ciertas funciones regresen una referencia o puntero hacia un tipo (sea este estructurado o no) específico de dato en lugar de un valor específico. En tales casos, la función se deberá declarar como para que regrese un puntero. Por ejemplo, supongamos que deseamos crear una función para convertir un número entero en notación decimal a una cadena de caracteres en forma de números binarios, luego, la función mencionada podría escribirse para que reciba el número entero como parámetro y regrese un puntero a una cadena de caracteres conteniendo la conversión. Para ser más puntuales, vamos a escribir un programa en donde se verá la función binstr(), y cuyo objetivo será precisamente convertir números decimales en cadenas binarias.
Nota: observe que en la sintaxis para declarar funciones tipo puntero se debe de poner el símbolo * despues del tipo y antes del nombre de la función que se está declarando. Esto se puede ver en el programa, ya que la función binstr se declara como: char *binstr(unsigned int);
#include <iostream>
#include <string.h>
using namespace std;
// declaración de prototipo
char *binstr(unsigned int);
// punto de prueba
int main()
{
int n = 128;
cout << "decimal = " << n << ", binario = " << binstr(n) << endl;
cin.get();
}
// definición de función binstr()
// nota: esta funcion requiere de la librería estándar string
char *binstr(unsigned int n)
{
static char buffer[65];
int i = 0;
strcpy(buffer, "0");
if (n > 0) {
while (n > 0) {
buffer[i] = ( n & 1 ) + '0';
i++;
n >>= 1;
}
buffer[i] = '\0';
strrev(buffer);
} // fin (n > 0)
return buffer;
}
Variables estáticas y automáticas[editar]
Dentro de una función, las variables y/o constantes pueden ser declaradas como: auto (por omisión) o como static. Si una variable dentro de una función es declarada como estática significa que la misma retendrá su valor entre las llamadas a la función. Por otro lado, la variables automáticas pierden su valor entre las llamadas. En el programa anterior puede verse que el arreglo de caracteres (buffer[65]) se ha declarado como estático para garantizar que dicho buffer retenga los datos aún despues de que la función termine. En el mismo ejemplo, si el buffer no se declara como estático, el contenido del mismo podría ser destruido al salir de la función y los resultados obtenidos podrían ser no deseados.
Parámetros constantes[editar]
Los parámetros usados por una función pueden declararse como constantes ( const ) al momento de la declaración de la función. Un parámetro que ha sido declarado como constante significa que la función no podrá cambiar el valor del mismo ( sin importar si dicho parámetro se recibe por valor o por referencia ).
Ejemplo:
int funcionX( const int n );
void printstr( const char *str );
Parámetros con valor por defecto[editar]
Los parámetros usados por una función pueden declararse con un valor por defecto. Un parámetro que ha sido declarado con valor por defecto es opcional a la hora de hacer la llamada a la función. Ejemplo: Dada la función:
void saludo( char* mensaje = "Hola Copa America 2015" );
la misma puede ser invocada como:
saludo(); // sin parámetro
saludo("Sea usted bienvenido a C++"); // con parámetro
Para ver un ejemplo más, vamos a considerar el caso de la función binstr() del programa funciones01. Ahora, vamos modificar dicha función, salvo que esta ocasión nos interesa que la misma sirva para convertir números decimales en cadenas numéricas y cuya base de conversión sea pasada como parámetro. Es decir, la función de la que estamos hablando podrá convertir números decimales a: binario, octal, decimal, hexadecimal, etc.; y la única condición será que la base indicada esté entre el 2 y el 36, inclusive.
Nota: Ya que la función servirá para convertir números a cualquier representación la nombraremos como numstr() en lugar de binstr(). Si la función es invocada sin el parámetro base regresará una cadena de digitos decimales.
#include <iostream>
#include <stdlib.h>
using namespace std;
// declaración de prototipo
char *numstr(unsigned int, const int base = 10);
// punto de prueba
int main()
{
int n = 128;
cout << "decimal = " << n << ", binario = " << numstr(n, 2) << endl;
cout << "decimal = " << n << ", octal.. = " << numstr(n, 8) << endl;
cin.get();
}
// definición de función numstr()
// nota: esta funcion requiere de la librería stdlib.h
char *numstr(unsigned int n, const int base)
{
static char buffer[65];
itoa(n, buffer, base);
return buffer;
}
Parámetros de tipo puntero[editar]
Anteriormente se mencionó que en C++ los parámetros a una función pueden pasarse por valor o por referencia, al respecto, podemos agregar que los parámetros también pueden pasarse como punteros. El paso de parámetros de punteros es bastante parecido al paso de parámetros por referencia, salvo que el proceso de los datos dentro de la función es diferente. Por ejemplo, las funciones:
void referencia( int &X ) { X = 100; }
void puntero( int *X ) { *X = 100; }
ambas reciben un puntero o referencia a un objeto de tipo entero, por lo tanto cualquiera de las funciones del ejemplo puede cambiar el valor de la variable entera apuntada por X, la diferencia radica en la forma en que cada una de las mismas lleva cabo la tarea. Si en la función puntero() en lugar de usar *X = 100; se usara X = 100; se le asignaría 100 al puntero X, más no al objeto apuntado por X, y esto podría ser la causa de que el programa se terminara de manera abrupta.
Parámetros estructurados[editar]
Al igual que cualquier otro tipo los parámetros de tipo estruturado pueden pasarse por valor o por referencia, sin embargo, podría ser que si una estructura es pasada por valor el compilador mostrara una advertencia ( warning ) indicando que se pasado por valor una estructura, puesto que el paso de estructuras por valor es permitido usted puede ignorar la advertencia, pero lo mejor es pasar estructuras por referencia. Si una estructura es pasada por valor y si esta es muy grande podria ser que se agotara la memoria en el segmento de pila ( Stack Segment ), aparte de que la llamada a la función sería más lenta.
Para ver un ejemplo, consideremos el caso del siguiente tipo estructurado:
struct empleado {
char nombre[32];
int edad;
char sexo;
};
Ahora, pensemos que deseamos escribir una función para imprimir variables del tipo empleado. Así, la función puede escribirse de las tres maneras siguientes:
void ImprimeEmpleadoV( empleado e)
{
cout << "Nombre: " << e.nombre << endl;
cout << "Edad: " << e.edad << endl;
cout << "Sexo: " << e.sexo << endl;
}
// Parametro empleado pasado por referencia
void ImprimeEmpleadoR( empleado &e )
{
cout << "Nombre: " << e.nombre << endl;
cout << "Edad: " << e.edad << endl;
cout << "Sexo: " << e.sexo << endl;
}
// Parametro empleado pasado como puntero
void ImprimeEmpleadoP( empleado *e )
{
cout << "Nombre: " << e->nombre << endl;
cout << "Edad: " << e->edad << endl;
cout << "Sexo: " << e->sexo << endl;
}
Funciones sobrecargadas[editar]
C++, a diferencia del C estándar, permite declarar funciones con el mismo nombre y a esto se conoce como sobrecarga de funciones. Las funciones sobrecargadas pueden coincidir en tipo, pero al menos uno de sus parámetros tiene que ser diferente. En todo caso, si usted trata de declarar funciones sobrecargadas que coincidan en tipo y número de parámetros el compilador no se lo permitirá. Para poner un ejemplo vamos a considerar el caso de dos funciones cuyo nombre será divide, ambas regresarán el cociente de dos números, salvo que una de ellas operará sobre números enteros y la otra lo hará sobre números reales ( de punto flotante ).
Nota: cuando en los programas se hace una llamada a una función sobrecargada, el compilador determina a cual de las funciones invocar en base al tipo y número de parámetros pasados a la función.
#include <iostream.h>
#include <stdlib.h>
using namespace std;
// divide enteros
int divide(int a, int b)
{
cout << "división entera" << endl;
return ( (b != 0) ? a/b : 0);
}
// divide reales
double divide(double a, double b)
{
cout << "división real" << endl;
return ( (b != 0) ? a/b : 0);
}
// punto de prueba
int main()
{
cout << divide(10, 3) << endl;
cout << divide(10.0, 3.0) << endl;
cin.get();
}
Número variable de parámetros[editar]
En C,C++ se pueden crear funciones que operen sobre una lista variable de parámetros, es decir, en donde el número de parámetros es indeterminado. En esta sección se mostrará un ejemplo de la manera en que podemos crear funciones para manejar tales asuntos, y para ello haremos uso de tres macros soportadas por C++:
1. va_list puntero de argumentos
2. va_start inicializar puntero de argumentos
3. va_end liberar puntero de argumentos
La sintaxis que usaremos para declarar funciones con lista de parámetros variables es:
1) tipo nombrefuncion(...)
2) tipo nombrefuncion(int num, ...)
donde:
1. tipo es el tipo regresado por la función
2. nombrefuncion es el nombre de la función
3. int num es el número de parámetros que la función procesará
4. ... esta notación se emplea para indicar que el número de parámetros es variable
Nota: observe que la primera forma de declaración es realmente variable el número de parámetros a procesar y en estos casos se debe establecer el mecanismo para determinar cuando se ha procesado el último de los argumentos, en el segundo tipo de declaración el número total de parámetros a procesar es igual al valor del parámetro num.
En el siguiente programa, por ejemplo, se define una función ( printstr ) que despliega una lista variable de cadenas de caracteres.
#include <iostream.h>
#include <stdarg.h>
// despliega una lista de cadenas, la ultima debe ser NULL
void printstr(...)
{
va_list ap;
char *arg;
va_start(ap, 0);
while ( (arg = va_arg(ap, char*) ) != NULL) {
cout << arg;
}
va_end(ap);
}
int main()
{
printstr("Hola, ", "Esta es\n", "una prueba\n", NULL);
cin.get();
return 0;
}
En el programa que se listará en seguida, se define la función suma(), misma que operará sobre listas de números enteros, la función devolverá la suma de dichos números.
#include <iostream>//entrada y salida
#include <stdarg.h>
using namespace std;
// Esta función opera sobre una lista variable de números enteros
int suma( int num, ... )
{
int total = 0;
va_list argptr;
va_start( argptr, num );
while( num > 0 ) {
total += va_arg( argptr, int );
num--;
}
va_end( argptr );
return( total );
}
int main()
{
cout << suma(4, 100, 200, 300, 400) << endl;
cin.get();
return 0;
Comentarios
Publicar un comentario