Вы находитесь на странице: 1из 28

UNIVERSIDAD DE EL SALVADOR

FACULTAD DE INGENIERIA Y ARQUITECTURA


ESCUELA DE INGENIERIA DE SISTEMAS INFORMATICOS
PROGRAMACION I
Ciclo II-2015

UNIDAD II. ANLISIS ESTRUCTURADO


Objetivo de la Unidad:

Conocer y aplicar los conceptos relacionados con el Anlisis


Estructurado para la solucin de problemas.

Contenido de la Unidad: 2.1 Definicin de Programacin Modular


2.2 Tcnicas de Diseo Modular
2.3 Anlisis Estructurado
2.4 Representacin Grfica de Soluciones Modulares
2.5 Variables Locales
2.6 Variables Globales
2.7 Concepto de Funcin
2.8 Definicin de una Funcin
2.9 Invocacin de una Funcin
2.10 Parmetros de una Funcin
2.11 Ejemplos

Introduccin
Cuando los problemas que se van a resolver son muy grandes o complejos, disear la solucin se
convierte en una actividad lenta y ardua, es aqu donde posee mayor utilidad la Programacin
Modular, ya que facilita la tarea de programar y permite elaborar programas de manera ms rpida
y eficaz.
La experiencia ha demostrado que la mejor manera de desarrollar una solucin y mantenerla, es
construirla a partir de piezas pequeas, que la hacen ms manejable. A continuacin se presentan
diferentes elementos que facilitan el diseo, implementacin, operacin y mantenimiento de
soluciones grandes para problemas grandes.

2.1 Definicin de Programacin Modular


Esta tcnica tambin es conocida como Anlisis Estructurado, y es uno de los mtodos de diseo
ms fcil. Ayuda a mejorar la productividad de los programas adems que, es una forma flexible y
potente de programar.
Esta tcnica divide el problema en pequeas partes o sub-problemas y se debe disear una
solucin para cada una de esas partes. A las divisiones o partes de un problema y a las soluciones
o algoritmos que los resuelven, se les conoce como mdulos; cada mdulo debe realizar una tarea
o actividad especfica, segn las divisiones que se hayan hecho.
Para resolver cada sub-problema (o mdulo), se le aplica la Metodologa para Resolver Problemas
completa, es decir se debe plantear, analizar, disear su algoritmo y codificarlo, individualmente.
Recordar que la solucin de cada sub-problema resuelve slo una parte del problema; la solucin
completa del mismo est formada por el conjunto de todas y cada una de las pequeas soluciones
diseadas y la interrelacin de todas ellas.
Todo problema resuelto por esta tcnica tiene un algoritmo denominado PRINCIPAL, comnmente
conocido como: mdulo raz, mdulo conductor o mdulo de control; ya que controla todo lo que
sucede, tanto en ese mdulo como en todos los dems, transfiriendo el control de ejecucin a
cada mdulo en el momento que sea requerido. De esa forma, cada mdulo puede realizar su
funcin o tarea, pero al terminar regresa el control de ejecucin al algoritmo o mdulo principal.

La solucin de cada mdulo se le conoce como SUB-ALGORITMO, en trminos generales, si est


representado en un diagrama: sub-flujograma, si est escrito en cdigo sub-programa (subrutina)
y en lenguaje C, funcin. Un problema resuelto mediante programacin modular genera un
algoritmo modular que consta de un algoritmo principal y uno o varios sub-algoritmos.
El algoritmo principal debe contener las llamadas (o invocaciones) a los sub-algoritmos; es decir
es el que indica el orden en que se ejecutan cada uno de los sub-algoritmos. Adems, el mdulo
principal puede realizar una o varias tareas. Cada sub-algoritmo como representacin de la
solucin de un mdulo debe mantener todas las propiedades de un algoritmo. Por lo tanto, estos
pueden contener tareas simples que slo se ejecutan una vez o, lo que es ms frecuente, tareas
repetitivas que se ejecutan varias veces y son llamadas para ejecutarse desde el algoritmo
principal.
Si la tarea asignada a un mdulo es muy compleja (o muy grande), debe dividirse todava en otro u
otros mdulos ms pequeos. El proceso sucesivo de subdivisin de mdulos contina hasta que
cada mdulo tenga solamente una tarea o accin especfica que ejecutar, esta tarea puede ser de
entrada, salida, procesamiento o manipulacin de datos, control de otros mdulos o una
combinacin de todos o algunos de estos.
Los datos requeridos en un mdulo pueden leerse en ste o pueden ser enviados a ste por el
mdulo de control; y los resultados producidos por un mdulo pueden ser impresos dentro del
mdulo o remitirse al mdulo de control para que sean utilizados por otro mdulo cuando se
transfiera el control a ellos.
Se disea cada mdulo con independencia de los dems, y siguiendo un mtodo ascendente o
descendente, se llega hasta la descomposicin final del problema en mdulos en forma jerrquica.
En pocas palabras, la tcnica implica dos partes:
1. Dividir el problema en sub-problemas ms pequeos.
2. Aplicar la Metodologa para resolver problemas a cada sub-problema; es decir para cada
sub-problema se hace lo siguiente: * Planteamiento (Qu hace?)
* Anlisis del problema (Cmo lo hace?)
* Diseo de la solucin o flujograma
* Codificacin o programa

2.2 Tcnicas de Diseo Modular


Con el objeto de facilitar el diseo de algoritmos y la organizacin de los diversos elementos que
los componen se utilizan algunas tcnicas que muestran una metodologa a seguir para resolver los
problemas. Estas tcnicas hacen que los programas sean ms fciles de escribir, verificar, leer y
mantener. Algunas de las tcnicas ms conocidas son : Top Down o Diseo Descendente,
Botton Up o Diseo Ascendente y Warnier Orr.
TOP DOWN: tcnica de diseo que consiste en tomar inicialmente, el problema completo, como
un todo y descomponerlo sucesivamente en problemas ms pequeos y por lo tanto, de solucin
ms sencilla, representa cada mdulo por medio de rectngulos, y las relaciones que existen entre
ellos por lneas rectas, siendo el primer mdulo siempre el mdulo raz o de control (ser la tcnica
de diseo adoptada para la asignatura, por esta razn ser abordada ms profundamente ms
adelante en este documento):

Modulo Principal o
mdulo raz o mdulo de
control

Modulo 0

Modulo 1

Modulo 4

Modulo 2

Modulo 5

Submdulos

Modulo 3

Modulo 6

BOTTON UP:
tcnica que consiste en partir de los detalles ms precisos del algoritmo
completando sucesivamente mdulos de mayor complejidad, este mtodo es inverso al anterior,
parte de lo ms simple para llegar a lo complejo; se recomienda utilizarlo cuando: ya se cuenta con
experiencia en la aplicacin de la tcnica, o cuando se tiene un modelo a seguir y ya se sabe lo
que se va a hacer, o se cuenta con amplia pericia en la resolucin de problemas semejantes.
Conforme se va alcanzando el desarrollo de mdulos ms grandes se plantea como objetivo final la
resolucin global del problema. La tcnica de Botton Up es frecuentemente utilizada para la
realizacin de pruebas a sistemas ya concluidos:
Modulo 4

Modulo 5

Modulo 2

Modulo 1

Submdulos

Modulo 6

Modulo 3

Mdulo Principal o
mdulo raz o mdulo de
control

Modulo 0

WARNIER ORR: tcnica que utiliza una representacin semejante a la de cuadros sinpticos para
mostrar el funcionamiento y organizacin de los elementos que conforman el algoritmo.
Bsicamente es igual al Top Down, ya que toma el problema completo y lo va dividiendo en partes
ms pequeas, se diferencia en la representacin del diseo, Warner Orr utiliza una notacin de
llaves para organizar los mdulos:

Modulo 1

Modulo 4

Submdulos

Modulo 5

Modulo 0
Modulo 2

Modulo 6
Modulo Principal o
mdulo raz o mdulo de
control

Modulo 3

El Diseo Descendente o Top-down, esto es de arriba hacia abajo, es un procedimiento mediante


el cual un problema se descompone en una serie de niveles o pasos sucesivos de refinamiento. La
metodologa consiste en efectuar una relacin entre las etapas de estructuracin (o subproblemas), de modo que se conecten o comuniquen unas con otras, mediante entradas y salidas
de informacin. Es decir, se descompone el problema en etapas o estructuras jerrquicas, de
forma que se puede considerar cada estructura desde dos puntos de vista: qu hace esa etapa?
y, cmo lo hace? Cada nivel de refinamiento o sub-problema, conocidos ahora como mdulos, se
debe consideran de la siguiente forma:

Desde el exterior:
Qu hace ?

Desde el interior:
Cmo lo hace ?

Para dibujar el diseo se debe tomar en cuenta lo siguiente:


Se representa cada sub-problema por medio de un rectngulo, incluyendo el modulo principal.
A cada mdulo se le adjudica un nombre o identificador (igual que a las variables) y se escribe
al centro del rectngulo.
La relacin o dependencia de los mdulos se dibuja por medio de lneas rectas.
El mdulo raz es el primero del diagrama y, es el nico que se encuentra en ese nivel.
El mdulo de un nivel n, le puede enviar datos a un mdulo de ms abajo.
Un mdulo de un nivel le puede enviar resultados al mdulo de quien depende.
Mdulo 0

Mdulo 1

Mdulo 1-2

Mdulo 2

Mdulo 3

Mdulo 3-1

Mdulo 3-2

Mdulo 3-2-1

Mdulo 4

Mdulo 3-3

Mdulo 3-2-2

Mdulo 4-1

Mdulo 4-1-1

Debe recordarse que las lneas que conectan dos mdulos indican en primer lugar dependencia
entre ellos (el mdulo del nivel superior es el que controla la ejecucin del mdulo del nivel inferior)
y, en segundo lugar, comunicacin, ya que entre ellos se pueden enviar datos. La comunicacin
entre mdulos siempre es de forma vertical, nunca de forma horizontal. Por ejemplo, en el
diagrama de la figura anterior, el mdulo 0 (o mdulo principal) indica cundo se ejecuta el mdulo
2 y puede enviarle datos; este mdulo 2 al terminar su ejecucin le puede enviar su resultado al
mdulo principal. Los mdulos 2 y 3 no se relacionan entre ellos (ni dependencia ni
comunicacin).

Para dividir un problema en trozos del mismo, ms pequeos, lo indicado es hacer una lista de las
acciones o cosas que deben realizarse y agruparlas de alguna manera conveniente; adems deben
ser relacionadas, indicando por medio de lneas la dependencia entre los mdulos, en la figura
anterior, el mdulo 3-2-2 depende del mdulo 3-2, ste depende del mdulo 3 y ste a su vez del
mdulo 0.
Se sugiere que, lo primero que se puede hacer, es dividir el problema en tres partes: Entrada,
Proceso y Salida, que como son las partes de todo algoritmo, casi siempre estn presentes y si el
proceso en s es grande o complejo, se puede dividir en ms partes.
Comnmente, se puede dejar la entrada de datos como parte del mdulo principal y la salida puede
ser un solo mdulo o formar parte de los mdulos de proceso; tambin se puede dejar la salida en
el principal y disear un mdulo de entrada de datos y desde luego los de proceso. En fin que no
hay una regla para dividir un problema, cada programador divide y disea los mdulos que
considere necesarios.
Cada mdulo puede contener acciones slo de entrada, slo de proceso, slo de salida de datos o,
una combinacin de todos.
Los datos con que trabaja un mdulo se conocen como parmetros, y estos forman parte de los
datos de entrada, (pero no se leen), son enviados por el mdulo que lo precede. Por ejemplo en la
figura anterior, los parmetros del mdulo 1-2, deben ser facilitados por el mdulo 1.
Cada mdulo puede producir resultados (datos de salida) que no se imprimen, sino que son
requeridos por el mdulo que lo precede y se les conoce como Valor(es) de Retorno, de nuevo en
la figura anterior, el resultado del mdulo 3-2-2 es o pude ser enviado al modulo 3-2. Un mdulo
puede tener uno o varios parmetros, pero slo puede enviar un valor de retorno. El mdulo
principal no tiene parmetros ni valor de retorno.

********************************************************************************************************
2.3 Anlisis Estructurado
La tcnica de Anlisis Estructurado se conoce tambin como la tcnica Divide y Vencers, ya
que se descompone un problema en mdulos independientes ms simples, que son fciles de
resolver. Se disea la solucin de cada mdulo con independencia de los dems. Lo que facilita el
anlisis, el diseo del algoritmo y, desde luego, su codificacin. Adems, puesto que cada mdulo
se considera independiente, varios programadores pueden disear por separado las soluciones a
diferentes mdulos, con lo cual se minimiza el trabajo o esfuerzo personal y el tiempo de diseo
para la solucin completa.
Algunas ventajas de programar modularmente son:
Disminuir la complejidad.
Aumentar la claridad y fiabilidad.
Posibilitar el uso repetitivo de las rutinas en el mismo o en diferentes programas.
Facilitar la ampliacin del programa mediante nuevos mdulos.
Facilitar las modificaciones y correcciones al quedar automticamente localizadas en un
mdulo, lo cual indica que un programa modular es fcil de mantener y modificar.
Facilitar la escritura y depuracin de programas (ejecutar, probar y optimizar).
Facilitar el control porque el desglose de un problema en mdulos permite encomendar los
mdulos ms complejos a los programadores ms experimentados y los ms sencillos a los
programadores con menos pericia o experiencia.
Ahora bien, independientemente de la tcnica que se utilice para disear, para que este tipo de
programacin sea realmente efectiva, se debe establecer un organigrama modular
(representacin grfica de un algoritmo modular).

2.4 Representacin Grfica de un Algoritmo Modular


La representacin grfica de la solucin de un problema mediante esta tcnica, tiene varios
flujogramas: uno que representa el mdulo principal y, uno o varios que representan a cada uno de
los mdulos que se hayan diseado. Recordar que a cada mdulo se le debe asignar un
identificador o nombre, que lo diferencie de otros.
Para indicar dentro del FLUJOGRAMA principal que se har uso de un subflujograma se utiliza el
rectngulo con doble barra vertical, dentro del cual se escribe el nombre del mdulo, a esto se le
conoce como invocacin del sub-flujograma o llamada a un sub-flujograma.
Para diferenciar un subflujograma del flujograma principal, a los smbolos de inicio y fin se le
aaden barras verticales; en el smbolo de inicio y fin, se escribe el identificador o nombre del
mdulo y los parmetros de ste si los necesita; es muy comn terminar un sub-flujograma con la
palabra retornar en el smbolo de fin, ya que al llegar a ste, se regresa el control de ejecucin al
flujograma principal o, al sub-flujograma que lo ha utilizado o invocado, tambin se escribe aqu el
valor de retorno si el mdulo produce alguno. Las siguientes figuras muestran los smbolos
descritos anteriormente:
Nombre del
mdulo(parmetros)

Nombre del mdulo


(Parmetros)

Fin_Nombre del mdulo,


Valor de retorno

o tambin:
Retornar valor de retorno

Invocacin de un
Sub-flujograma

Inicio de un
Sub-flujograma

Fin de un
Sub-flujograma

La representacin grfica (flujograma) de la solucin de un problema descompuesto en forma


modular, adopta la estructura siguiente:
Inicio

Proceso1

Nombre1

Nombre2

Proceso2

Proceso3

Nombre1
Nombre2

Fin

Flujograma Principal

Fin_Nombre1

Retornar
Subflujogramas

En donde: Proceso1, Proceso2 y Proceso3 pueden contener estructuras:


Secuenciales (lectura, escritura, asignacin)
Selectivas (seleccin simple, doble o mltiple)
Iterativas (Mientras, Desde-hasta, Hasta que)

Un sub-flujograma (mdulo) puede ser invocado desde el flujograma principal o desde otro subflujograma, al terminar de ejecutarse se retorna al flujograma principal o al sub-flujograma que lo
invoc. *****************************************************************************************************

2.5 Variables Locales


Son variables que se declaran dentro de un mdulo, y mantienen su valor mientras este mdulo se
est ejecutando; es decir que cuando se ejecuta otro mdulo no existen en memoria, por lo tanto
no se pueden utilizar fuera del mdulo donde fueron declaradas.

2.6 Variables Globales


Estas variables pueden ser referenciadas desde cualquier mdulo. Lo cual significa que se pueden
utilizar en todos los mdulos, conservando su valor en todos ellos, siempre y cuando no se
modifique; sin embargo, ese valor se puede cambiar en cualquier mdulo que utilice la variable
global y de all en adelante lo conservar en todos los dems mdulos que la utilicen hasta que
alguno de ellos requiera modificarla nuevamente.

2.7 Concepto de Funcin


Un sub-algoritmo es un algoritmo que realiza una tarea especfica dentro de la solucin de un
problema; es decir, que resuelve una parte de un problema. Si se representa por medio de un
diagrama se le conoce como sub-flujograma. Puede ser llamado o invocado desde el flujograma
principal o cualquier otro sub-flujograma. Todo sub-flujograma puede recibir uno o varios datos
(parmetros) de quien lo invoca, pero slo puede enviar un nico resultado (valor de retorno).
Las funciones son un conjunto de instrucciones que realizan una tarea especfica. En general
toman ciertos valores de entrada, llamados parmetros y proporcionan un valor de salida o valor de
retorno; aunque en el Lenguaje C, tanto unos como el otro son opcionales, y pueden no existir.
Todos los programas en C contienen, como mnimo, una que es la funcin main.
Una funcin muy especial es la funcin main. Se trata de la funcin de entrada, y debe existir
siempre, ya que ser la que tome el control cuando se ejecute el programa. Existen reglas para el
uso de los valores de retorno y de los parmetros de la funcin main, pero de momento se usar
como int main() o int main(void), con un entero como valor de retorno y sin parmetros de entrada.
El valor de retorno indicar si el programa ha terminado sin novedad ni errores retornando cero,
cualquier otro valor de retorno indicar un cdigo de error.
Entonces, una funcin es un grupo de instrucciones con un objetivo en particular que se ejecuta al
ser llamada desde otra funcin o procedimiento. Una funcin puede llamarse mltiples veces e
incluso llamarse a s misma (funcin recurrente). En general, deben tener un nombre nico en el
mbito para poder ser llamadas, un tipo de dato del resultado a ser obtenido, una lista de
parmetros de entrada y su cdigo.
Las funciones pueden recibir datos desde afuera al ser llamadas a travs de los parmetros y
deben entregar un resultado. Se diferencian de los procedimientos porque estos no devuelven un
resultado.
Los parmetros o argumentos de una funcin son los datos que son parte de las entradas del
mdulo, pero dentro del cuerpo no se leen, deben de declararse en la invocacin de la funcin y en
el inicio de la misma. Una funcin puede tener o no parmetros.
Los parmetros se comportan como variables locales, crendose al entrar a la funcin y
destruyndose al salir de sta; es decir que, los parmetros reciben sus valores del mdulo que
invoca la funcin, y con estos valores se trabajar dentro de ella.
Se conoce como valor de retorno aquel que se genera en la funcin y se enva al mdulo de quien
depende; es decir, el mdulo que lo invoc.

Entonces, una funcin es un conjunto de lneas de cdigo que realizan una tarea especfica y
puede retornar un valor. Las funciones pueden tomar parmetros que modifiquen su
funcionamiento. Las funciones son utilizadas para descomponer grandes problemas en tareas
simples y para implementar operaciones que son comnmente utilizadas durante un programa y de
esta manera reducir la cantidad de cdigo. Cuando una funcin 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
funcin fue llamada.

2.8 Definicin de una Funcin


La forma genrica de definir funciones en C es:
tipoValorRegreso nombreFuncion (parmetros)
{
declaraciones
sentencias
}
tipoValorRegreso es el tipo de dato del resultado de llamar a la funcin, puede ser un entero, una
cadena, un carcter, etc. o tambin puede ser void que indica que esa funcin no devolver ningn
valor.
nombreFuncion es un identificador o nombre vlido. Por lo general se aconseja poner un nombre
corto que especifique lo que hace esa funcin.
Los parmetros son una lista, separada por comas, que especifica los datos que se espera recibir.
Si se escribe void se entiende que esa funcin no necesita ningn parmetro.
La funcin tiene un cuerpo o bloque, donde estn las declaraciones y las sentencias. En las
declaraciones se especifican variables locales (slo podrn ser usadas dentro de esa funcin). No
se deben declarar las variables que llegan por parmetro. No se pueden definir funciones dentro de
otra funcin, pero s se puede llamar a una funcin dentro de otra funcin (incluso se puede llamar
a s misma que es el caso de las funciones recursivas).
Dentro del enunciado de las funciones se debe regresar el control al punto desde donde se invoc
a dicha funcin. En el caso de las funciones que no regresen resultados, estas finalizan cuando
termina de ejecutarse la ltima lnea de la funcin o cuando se llega al enunciado return. Si la
funcin devuelve un resultado, se debe especificar: return expresin;
Para terminar, se debe recordar que la mejor prctica al programar es modularizar, o sea, crear
mltiples funciones simples que trabajarn juntas para crear un programa complejo.
Ms especficamente, la sintxis de una definicin de funcin en DevC es:
[extern|static] <tipoValorRetorno> [modificadores] <identificador>(<listaParametros>)
{
[sentencias]
}
Opcionalmente (indicado por la presencia de corchetes) posee una palabra que especifica el tipo
de almacenamiento, puede ser extern o static. Si no se especifica ninguna, por defecto ser
extern. Esto quiere decir que son accesibles desde cualquier punto del programa, aunque se
encuentren en otros archivos fuente del mismo programa. En contraposicin las funciones
declaradas static slo son accesibles dentro del archivo fuente donde se definen.

Los programas complejos se escriben normalmente usando varios archivos fuente. Estos archivos
se compilan separadamente y se enlazan todos juntos, dentro de un Proyecto. Esto es una gran
ventaja durante el desarrollo y depuracin de grandes programas, ya que las modificaciones en un
archivo fuente slo obligarn a compilar dicho archivo fuente, y no el resto, con el consiguiente
ahorro de tiempo. La definicin de las funciones y clases puede hacerse dentro de los archivos
fuente o tambin pueden enlazarse desde bibliotecas compiladas previamente.
Por ejemplo si un programador quiere ofrecer ciertas funciones agrupadas bajo una biblioteca para
realizar una tarea en particular, pero internamente necesita crear y usar unas funciones auxiliares,
entonces restringe el acceso a esas funciones auxiliares, porque no pertenecen al juego de
funciones que quiere ofrecer. As:
// "oper.cpp"
// Ejecuta una instruccin de un procesador especializado
// para realizar cualquier operacin aritmtica
static double instAritmetica( unsigned int nInst, double param1, double param2 )

{
...
}
double sumar( double der, double izq )
{
return instAritmetica( 1, der, izq );
}
double restar( double der, double izq )
{
return instAritmetica( 2, der, izq );
}
double multiplicar( double der, double izq )
{
return instAritmetica( 3, der, izq );
}
double dividir( double der, double izq )
{
return instAritmetica( 4, der, izq );
}
De esta manera, cualquier programador tendr acceso a las cuatro funciones aritmticas que el
programador original quiso ofrecer. No se ofrece la funcin, 'instAritmetica()', porque no pertenece a
ese conjunto de funciones creado por el programador original.
Otro ejemplo puede ser a la hora de limitar la cantidad de funciones ofrecidas siguiendo una
documentacin establecida por los diseadores. Un jefe de proyecto da una lista de las funciones
que se deben implementar, pero no limita mucho en cuanto a la forma de implementarlas. Para
implementar las funciones indicadas, se pudieron haber creado unas cuantas funciones ms para
ayudar en la creacin de las dems. Esas otras funciones auxiliares que fueron creadas no forman
parte del cometido original, y como se limitan a un cdigo fuente, se decides usar 'static'.
Otra razn puede ser que existan coincidencias con las funciones que se usan en varios archivos
fuente. Para separar una funcin de las otras "versiones", se usa 'static' para no compartirlas y as
evitar problemas de conflicto de nombres.
El tipoValorRetorno, que puede ser void, si no se necesita valor de retorno. En C, si no se
establece, ser int por defecto, aunque en general se considera una mala tcnica de programacin
omitir el tipo de valor de retorno de una funcin. En C++ es obligatorio indicar el tipo del valor de
retorno.

Modificadores es, como lo indican los corchetes, opcional. Tienen un uso muy especfico que ser
tratado posteriormente.
Es muy til y recomendable que el identificador de la funcin posea un nombre que indique, lo
ms claramente posible, qu es lo que hace la funcin, y que permita interpretar qu hace el
programa con slo leerlo. Cuando se precisen varias palabras se utilizar la Tcnica Camel ya
explicada en la Unidad I.
La lista de declaraciones de parmetros entre parntesis, son los valores de entrada (y en
ocasiones tambin de salida). Para la funcin se comportan exactamente igual que variables, y de
hecho cada parmetro se declara igual que una variable. Una lista de parmetros es un conjunto de
declaraciones de parmetros separados con comas. Puede tratarse de una lista vaca.
Una definicin contiene adems las instrucciones con las que la funcin realizar su trabajo, es
decir, su cdigo o conjunto de sentencias que la componen. El cuerpo de la funcin representa el
cdigo que ser ejecutado cuando se llame a la funcin. El cuerpo de la funcin se encierra entre
llaves "{}". Por ejemplo:
int Mayor(int a, int b)
{
if (a > b) return a;
else return b;
}
La definicin de una funcin sirve para indicar al compilador los tipos de retorno y los de los
parmetros de una funcin, de modo que compruebe si son del tipo correcto cada vez que se use
esta funcin dentro del programa, o para hacer las conversiones de tipo cuando sea necesario.
Para el ejemplo expuesto, se indica al compilador que existe dentro del programa una funcin
"Mayor" que admite dos parmetros de tipo int y que devolver un valor de tipo int.

2.9 Invocacin de una Funcin


La invocacin o llamada de una funcin es la sentencia o instruccin a travs de la cual se hace
uso de ella y est escrita dentro del mdulo principal o del mdulo demandante de la operacin a
realizar. Por ejemplo, una forma de invocar la funcin Mayor descrita anteriormente podra ser:
//Programa que lee dos enteros y determina el mayor de ellos
#include <stdio.h>
main()
{
int n1, n2, nMayor;
printf(Introduzca primer nmero entero a comparar: );
scanf (%i, &n1);
printf(Introduzca segundo nmero entero a comparar: );
scanf (%i, &n2);
nMayor = Mayor(n1, n2); //Invocacin o llamada de la funcin Mayor
printf(El nmero mayor es: , nMayor);
getch();
}

10

2.10 Parmetros de una Funcin


Se va considerar el caso en el cual se desea crear la funcin cuadrado(), que deber devolver el
cuadrado de un nmero real (de punto flotante), es decir, cuadrado() aceptar nmeros de punto
flotante y regresar una respuesta como nmero flotante. (Nota: aunque para la funcin de
ejemplo, el tipo de retorno coincide con el tipo de parmetro pasado, algunas veces las cosas
pueden cambiar, es decir, no es obligatorio que una funcin reciba un parmetro de un tipo y que
tenga que regresar una respuesta de dicho tipo).
// Regresar el cuadrado de un nmero
double cuadrado(double n)
{
return n*n;
}
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 no reciban
parmetros. Existen dos formas en C de pasar parmetros a una funcin; por referencia o por valor.
El hecho es que si en una declaracin de funcin se declaran parmetros 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 parmetro es declarado para ser pasado
por valor, el mismo puede pasarse como una constante literal o como una variable. Los parmetros
pasados por referencia pueden ser alterados por la funcin que los reciba, mientras que los
parmetros pasados por valor o copia no pueden ser alterados por la funcin que los recibe, es
decir, la funcin puede manipular a su antojo el parmetro, pero ningn cambio hecho sobre este
se reflejar en el parmetro original.
La funcin cuadrado() es un clsico ejemplo que muestra el paso de parmetros por valor, en ese
sentido la funcin recibe una copia del parmetro n. En la misma funcin se puede observar que se
realiza un clculo ( n*n ), sin embargo el parmetro original no sufrir cambio alguno, esto seguir
siendo cierto an cuando dentro de la funcin hubiera una instruccin parecida a n = n * n; o n*=n;.
Para mostrar un ejemplo del paso de parmetros por referencia, se va a retomar el caso de la
funcin cuadrado, salvo que en esta ocasin se cambiar ligeramente la sintxis para definir la
misma:
// Regresar el cuadrado de un nmero
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 parmetro original, mientras que la segunda s lo hace.
Para llamar o invocar a la funcin cuadrado() vista anteriormente, se puede emplear:
cout << cuadrado(25);
cout << cuadrado(X);
R = cuadrado(X); // Guardar en R el cuadrado de X
Los parmetros usados por una funcin pueden declararse como constantes ( const ) al momento
de la declaracin de la funcin. Un parmetro que ha sido declarado como constante significa que
la funcin no podr cambiar el valor del mismo ( sin importar si dicho parmetro se recibe por valor
o por referencia ). Ejemplo:
int funcionX( const int n );
void printstr( const char *str );

11

Bajo ciertas circunstancias se desear escribir funciones que no regresen valor alguno y para ello
se puede declarar a la funcin como void. La palabra reservada void es utilizada para declarar
funciones sin valor de retorno y tambin para indicar que una funcin especfica no requiere de
parmetros. Por ejemplo, la funcin pausa() que se ver en seguida, no devolver valor alguno y la
misma no requiere de parmetros.
// Requiere de la librera iostream
void pausa(void)
{
cout << "Por favor presione <Enter> HOLA...";
cin.get();
cin.ignore(255, '\n');
// Rechazar otras teclas presionadas antes de <Enter>
}
Notas: se debe de aclarar que el uso de la palabra void dentro de los parntesis es opcional al
momento de declarar una funcin. As, la funcin pausa() podra haberse declarado como void
pausa(), y la misma puede invocarse como: pausa();.
cin es para entrada de datos y cin>>a donde a es la variable de entrada donde se va a guardar la
informacin solicitada al usuario. cout<< es para la salida para lo que se desea conocer o
preguntar. Por ejemplo:

luego, con cin :

cout<<"Introducir la marca de un carro";


cin>>marca;

marca es la variable donde se guarda la informacin pedida.


A continuacin se ejemplifican algunas instrucciones:
cout<<"car1="
// car1 es un mensaje porque va entre comillas dobles
cout<<car1
// car1 es una variable. La instruccin imprime el contenido de car1
<<endl
// fin de lnea, dejando el cursor en la siguiente lnea
El lenguaje C no permite anidar funciones, sin embargo, dentro de una funcin puede existir la
llamada a una o ms funciones declaradas previamente.
Dentro de una funcin, las variables y/o constantes pueden ser declaradas como: auto (por
omisin) o como static. Si una variable dentro de una funcin es declarada como esttica significa
que la misma retendr su valor entre las llamadas a la funcin. Por otro lado, las variables
automticas pierden su valor entre las llamadas.
Los parmetros usados por una funcin pueden declararse con un valor por defecto. Un parmetro
que ha sido declarado con valor por defecto es opcional a la hora de hacer la llamada a la funcin.
Por ejemplo: Dada la funcin:
void saludo( char* mensaje = "PRN115
2012" );
la misma puede ser invocada como:
saludo(); // sin parmetro
saludo("Sea usted bienvenido a "); // con parmetro

12

Para ver un ejemplo ms, se va a considerar el caso de la funcin binstr() del siguiente programa.
Se va a modificar dicha funcin de manera que sirva para convertir nmeros decimales en cadenas
numricas y cuya base de conversin sea pasada como parmetro. Es decir, la funcin podr
convertir nmeros decimales a: binario, octal, decimal, hexadecimal, etc.; y la nica condicin ser
que la base indicada est entre el 2 y el 36, inclusive. Nota: Ya que la funcin servir para convertir
nmeros a cualquier representacin ser nombrada como numstr() en lugar de binstr(). Si la
funcin es invocada sin el parmetro base regresar una cadena de dgitos decimales:
#include <iostream>
#include <stdlib.h>
int main()
{
int n = 128;
cout << "decimal = " << n << ", binario = " << numstr(n, 2) << endl;
cout << "decimal = " << n << ", octal.. = " << numstr(n, 8) << endl;
cin.get();
}
// Definicin de funcin numstr()
// Nota: esta funcin requiere de la librera stdlib.h
char *numstr(unsigned int n, const int base)
{
static char buffer[65];
itoa(n, buffer, base);
return buffer;
}
En el programa anterior, el arreglo de caracteres (buffer[65]) se ha declarado como esttico para
garantizar que dicho buffer retenga los datos an despus de que la funcin termine. En el mismo
ejemplo, si el buffer no se declara como esttico, el contenido del mismo podra ser destruido al
salir de la funcin y los resultados obtenidos podran ser no deseados.
EN CONCLUSION:
La estructura de un programa en C con mdulos o funciones quedara as:
[directivas del pre-procesador: includes y defines]
[declaracin de variables globales]
[declaraciones de funciones] Si no se usan declaraciones, las definiciones deben ir aqu
funcin main
[definiciones de funciones]

*****************************************************************************************************************

2.11 Ejemplos
Ejemplo 1:
Disear una solucin que calcule los minutos y segundos que equivalen a una cantidad de horas.
I. PLANTEAMIENTO GENERAL DEL PROBLEMA
Entrada de datos
Salida de datos

Cantidad de horas a convertir

13

Nmero de minutos
Nmero de segundos

II. TOP DOWN


Grandes pasos o cosas que hacer:
1. Leer y validar los datos
2. Convertir a minutos
3. Convertir a segundos
4. Imprimir
Con los pasos anteriores, se decide que se van a disear 4 mdulos y el principal:
uno de entrada o lectura de datos, que adems los valida;
otro que convierte las horas en minutos;
otro que convierte los minutos a segundos y
el cuarto que imprime los resultados.
El mdulo principal, llamado Tiempos, por lo que se desea que haga; solo recibe los datos, invoca
los otros mdulos en el orden debido y enva los parmetros. El diagrama Top Down asociado es:
tiempos

minutos

leer

imprimir

segundos

III. APLICACIN METODOLOGA PARA RESOLVER PROBLEMAS (por mdulo)


a. MDULO leer:

** Qu Hace? Lee y valida los datos.


Entrada de datos

Salida de datos

Cantidad de horas a convertir

Devuelve el nmero de horas

** Cmo lo hace?
Datos de Salida:
Variables de Salida: No hay, devuelve el nmero de horas
Datos de Entrada
Variables de Entrada:
Nombre Tipo
Descripcin
hora
entero Representa el nmero de horas a convertir, variable local
Parmetros: No hay, la funcin no tiene parmetros.
Constantes: No existen.
Restricciones:
hora >0
Proceso:
No hay, solo lee y valida el nmero de horas
Variables de Proceso: No hay

14

Diseo de Solucin: Sub-flujograma:


leer ( )

*
Mientras hora<=0

Digite el
nmero
de horas

Debe ser positivo

hora

hora

Retornar hora

b. MDULO minutos:

** Qu Hace? Convierte las horas en minutos.


Entrada de datos

Salida de datos

Recibe la cantidad de horas

Devuelve el nmero de minutos

** Cmo lo hace?
Datos de Salida
Variables de Salida: No hay, devuelve el numero de minutos
Datos de Entrada:
Variables de Entrada: No hay.
Parmetros:
Nombre Tipo
Descripcin
h
Entero Representa el nmero de horas a convertir
h: Nmero de horas a convertir, ledas en el mdulo leer.
Constantes: El nmero de minutos que tiene una hora: 60.
Restricciones:
Proceso:

No hay

min = 60 * h

Variables de Proceso:
Nombre Tipo
Descripcin
min
Entero Representa el nmero de minutos, variable local

15

Diseo de Solucin Sub-flujograma:


minutos ( h )

min = 60 * h

Retornar min

c. MDULO segundos:

** Qu Hace? Convierte los minutos en segundos.


Entrada de datos

Salida de datos

Recibe la cantidad de minutos

Devuelve el nmero de segundos

** Cmo lo hace?
Variables de Salida: No hay, devuelve el nmero de segundos
Variables de Entrada: No hay.
Parmetros:
Nombre
m

Tipo
Descripcin
entero Representa el nmero de minutos a convertir

Constantes: La cantidad de segundos que tiene un minuto: 60.


Restricciones: No hay
Proceso:

seg = 60 * m

Variables de Proceso:
Nombre
Tipo
Descripcin
seg
entero Representa el nmero de segundos, variable local
Diseo de Solucin Sub-flujograma:
segundos ( m )

seg = 60 * m
Retornar seg

16

d. MDULO imprimir:

** Qu Hace? Imprime horas, minutos y segundos.


Entrada de datos

Salida de datos

Recibe la cantidad de horas,


minutos y segundos

Cantidad de horas
Cantidad de minutos
Cantidad de segundos

** Cmo lo hace?
Variables de Salida:
Nombre Tipo
Ho
entero
Mi
entero
Se
entero

Descripcin
Representa el nmero de horas, variable local
Representa el nmero de minutos, variable local
Representa la cantidad de segundos, variable local

Variables de Entrada: No hay, recibe como parmetros el nmero de horas, minutos y segundos.
Parmetros:
Ho, Mi, Se: Nmero de horas, minutos y segundos a imprimir ledos o
Calculados en los otros mdulos.
Constantes: No existen.
Restricciones:
Proceso:

No hay

No hay

Variables de Proceso:

No hay

Diseo de Solucin Sub-flujograma:


imprimir ( ho, mi, se )

No. Horas, ho

Equivalentes a:

mi, Minutos se,


Segundos

Retornar

17

e. MDULO Principal:

** Qu Hace? Llama a los otros mdulos y Recibe-Asigna los resultados.


Entrada de datos

Salida de datos

Recibe la cantidad de horas


Recibe la cantidad de minutos
Recibe la cantidad de segundos

Enva la cantidad de
horas,
minutos
y
segundos

** Cmo lo hace?
Variables de Salida: No hay, enva como parmetros: el nmero de horas, minutos y segundos a
la funcin imprimir.
Variables de Entrada: No hay, recibe los valores de retorno de los otros mdulos: el nmero de
horas, minutos y segundos
Parmetros: No hay.
Constantes: No existen.
Restricciones:
No hay
Proceso:
Invoca los mdulos, enva parmetros y recibe-asigna los resultados:
numH = Leer( )
//resultado de Leer
numM = minutos( numH )
//resultado de minutos
numS = segundos( numM ) //resultdo de segundos
Variables de Proceso:
Nombre Tipo
Descripcin
numH
entero Representa el nmero de horas, variable local
numM entero Representa el numero de minutos, variable local
numS
entero Representa el nmero de segundos, variable local
Disee de solucin Flujograma:
Inicio

numH = leer()
numM = minutos(num_h)

numS = segundos(num_m)

imprimir( numH, numM, numS)

Fin

18

#include <conio.h>
#include <stdio.h>
// Convierte una cantidad de horas en minutos y segundos
// Declaracion y Definicion de Funciones
int leer () {
// Funcion que lee desde teclado la cantidad de horas a convertir
int hora;
printf ("Digite el numero de horas: ");
scanf ("%i", &hora);
while (hora <= 0) {
printf("Debe ser positiva ") ;
scanf("%i", &hora);
} // while
return hora;
} // leer
int minutos (int h) {
// Funcion que convierte la cantidad de horas en minutos
int min;
min = 60*h;
return min;
} // minutos
int segundos (int m) {
// Funcion que convierte la cantidad de minutos en segundos
int seg;
seg = 60*m;
return seg;
} // segundos
void imprimir (int ho, int mi, int se) {
// Despliega la cantidad de horas, minutos y segundos
printf ("No.Horas: %i", ho);
printf (" Equivalente a: %i Minutos y %i Segundos ", mi,se);
return;
} // imprimir
// Modulo Principal
main () {
int numH, numM, numS;
numH = leer();
numM = minutos(numH);
numS = segundos(numS);
imprimir(numH, numM, numS);
getch(); //pausa
}

19

Ejemplo 2
Disear una solucin que simule una calculadora sencilla; es decir, que realice las operaciones
aritmticas bsicas: SUMA, RESTA, MULTIPLICACIN Y DIVISIN. El programa debe permitir
realizar varias operaciones e imprimir cada vez: el nombre de la operacin realizada, los datos, el
resultado obtenido y, el nmero total de operaciones que se realizaron.
I. PLANTEAMIENTO GENERAL
Entrada de datos

Salida de Datos

Datos a operar
Tipo de operacin
deseada

Nombre de la operacin
Datos Iniciales
Resultado
No. de operaciones realizadas

II.
TOP- DOWN
El tener una idea de lo que se va a hacer ayuda mucho a decidir cuantos mdulos se van a disear
y la relacin que existe entre ellos; por lo tanto, las grandes cosas o pasos que se deben realizar
son:
1. Leer datos
2. Elegir la Operacin
3. Operar (producir el resultado)
4. Imprimir el resultado
5. Contar las operaciones
De aqu se puede inferir que se va a tener un mdulo para cada operacin aritmtica; adems el
mdulo principal va a leer los datos y es necesario validarlos, luego los enva a los mdulos,
tambin va a contar e imprimir el nmero de veces que se opera. El top-down queda as:
Principal

suma

III.

resta

multi

divi

ANLISIS ESTRUCTURADO
a. MODULO suma

** Qu hace?: Suma dos nmeros e imprime: la palabra SUMA, los


nmeros sumados y el resultado de la suma
Entrada de datos

Salida de Datos

Recibe
los
dos
nmeros a sumar

20

Mensaje: SUMA
Datos Iniciales o sumados
Resultado

** Cmo lo Hace?:
Variables de Salida.
Nombre Tipo
a
Real
b
Real
r
Real

Descripcin
El primer operando
El segundo operando
El resultado de la operacin

Variables de Entrada: No hay.


Parmetros: a, b: Los dos nmeros que se van a sumar.
Constantes: No existen.
Restricciones: No hay.
Proceso:
r=a+b
Variables de Proceso: No hay.
Flujograma: (Diseo de Solucin)

suma(a,b)
SUMA
r=a+b
Datos, a,b
Resultado de la
operacin:, r

Retornar

b. MDULO resta

** Qu hace ?: Resta dos nmeros e imprime: la palabra RESTA, los


nmeros restados y el resultado de la diferencia
Entrada de datos

Salida de Datos

Recibe
los
dos
nmeros a restar

21

Mensaje: RESTA
Datos Iniciales
Resultado

** Cmo lo Hace?:
Variables de Salida.
Nombre Tipo
a
Real
b
Real
r
Real

Descripcin
El primer operando
El segundo operando
El resultado de la operacin

Variables de Entrada: No hay, se reciben los datos a restar (a,b)


Parmetros: a, b: Los dos nmeros que se van a restar.
Constantes: No existen.
Restricciones: No hay.
Proceso:
r=a-b
Variables de Proceso: No hay.
Diseo de Solucin Sub-flujograma:

resta(a,b)
RESTA
r=a-b
Datos, a,b
Resultado de la
operacin:, r

Retornar

c. MDULO multi

**
Qu
hace?:
Multiplica
dos nmeros
e
imprime:
la
palabra
MULTIPLICACION, los nmeros multiplicados y el resultado del producto.
Entrada de datos

Salida de Datos

Recibe los dos


nmeros a
multiplicar

22

Mensaje: MULTIPLICACIN
Datos Iniciales
Resultado

** Cmo lo Hace?:
Variables de Salida.
Nombre Tipo
a
Real
b
Real
r
Real

Descripcin
El primer operando
El segundo operando
El resultado de la operacin

Variables de Entrada: No hay.


Parmetros: a, b: Los dos nmeros que se van a multiplicar.
Constantes: No existen.
Restricciones: No hay.
Proceso: r = a * b
Variables de Proceso: No hay.
Diseo de Solucin Sub-flujograma:

multi(a,b)
MULTIPLICACIN
r=a*b
Datos, a,b
Resultado de la
operacin:, r

Retornar

d. MDULO divi

** Qu hace?: Divide dos nmeros e imprime: la palabra DIVISION, los nmeros dividos
y el resultado de la divisin
Entrada de datos

Salida de Datos

Recibe
los
dos
nmeros a dividir

23

Mensaje: DIVISION
Datos Iniciales
Resultado

** Cmo lo Hace?:
Variables de Salida.
Nombre Tipo
a
Real
b
Real
r
Real

Descripcin
El primer operando
El segundo operando
El resultado de la operacin

Variables de Entrada: No hay,


Parmetros: a, b: Los dos nmeros que se van a dividir.
Constantes: No existen.
Restricciones: No hay.
Proceso: Hay que recordar que la divisin por cero no se puede ejecutar, por lo tanto:
b!=0?
Si: r = a/b
No: imprimir a, b no se pueden dividir
Variables de Proceso: No hay.
Diseo de solucin Sub-flujograma

divi(a,b)
DIVISION
No

Si

b!=0

r=a/b

a, y, b, No se
pueden dividir

Datos, a,b
Resultado de la
operacin:, r

Retornar

24

e. MDULO principal

** Qu hace?: Lee dos datos reales, elige la operacin a realizar y cuenta las
operaciones hechas en total.
Entrada de datos

Salida de Datos

Dos datos a operar


Tipo de operacin
Valor para hacer
otro clculo

Nmero de operaciones
realizadas
Enva los datos a operar

** Cmo lo Hace?:
Variables de Salida:
Nombre Tipo
i
Real

Descripcin
El contador de las operaciones realizadas. Vi=0, Vc=1,
Vf.?
Debe enviar o mandar los dos nmeros a operar a cada mdulo

Variables de Entrada:
Nombre Tipo
x
Real
y
Real
op
Entero
otra
Parmetros:

Entero

Descripcin
El primer operando
El segundo operando
El tipo de la operacin a realizar 1: suma
2: resta
multiplicacin 4: divisin
Indica si se requiere otra operacin, 1: otro clculo

No hay, la funcin principal nunca tiene parmetros.

Constantes: No existen.
Restricciones: op>=1 && op<=4.
Proceso:
i=0
leer otra
leer x, y
leer op
Mientras
otra==1
op =

// y validar
1:
2:
3:
4:

Llamar Suma(x,y)
Llamar Resta(x,y)
Llamar Multi(x.y)
Llamar Divi(x,y)

i= i + 1
leer otra
Variables de Proceso: No hay.

25

3.

Diseo de Solucin (Flujograma):


Inicio

i=0
op

Para hacer
una operacin
digite 1

1
2

otra

4
otra==1

No

Si
1:
2:
3:
4:

Suma
Resta
Mutiplicacin
Divisin

suma(x,y)
resta(x,y)
multi(x,y)
divi(x,y)

i=i+1
Para hacer
otra operacin
digite 1

op
MIENTRAS
op<1 || op>4

otra
2

Error, debe
ser entre 1 y
4
3

op

Se realizaron:
, i, operaciones
x, y
Fin
1

26

#include <conio.h>
#include <stdio.h>
// Simulador de una calculadora sencilla: +, -, * y /
// Declaracion y Definicion de Funciones
void suma (float a, float b) {
// Suma dos numeros
float r;
printf ("\nS U M A\n");
r = a + b;
printf("\nDatos: %.2f %.2f ", a, b) ;
printf("\nResultados de la Operacion: %.2f", r);
return;
} // suma
void resta (float a, float b) {
// Resta dos numeros
float r;
printf ("\nR E S T A\n");
r = a - b;
printf("\nDatos: %.2f %.2f ", a, b) ;
printf("\nResultados de la Operacion: %.2f", r);
return;
} // resta
void multi (float a, float b)
// Multiplica dos numeros
float r;
printf ("\nM U L T I P L I
r = a * b;
printf("\nDatos: %.2f %.2f
printf("\nResultados de la
return;
} // multi

{
C A C I O N\n");
", a, b) ;
Operacion: %.2f", r);

void divi (float a, float b) {


// Divide dos numeros
float r;
printf ("\nD I V I S I O N\n");
if (b != 0) {
r = a/b;
printf("\nDatos: %.2f %.2f ", a, b) ;
printf("\nResultados de la Operacion: %.2f", r);
}
else
printf("%.2f y %.2f No se pueden dividir", a, b) ;
return;
} // divi

27

// Modulo Principal
main () {
int i, otra, op;
float x,y; //Numeros a operar
i=0;
printf ("\nPara hacer una operacion digite 1 ");
scanf("%i", &otra);
while (otra==1) {
printf("\n1: Suma");
printf("\n2: Resta");
printf("\n3: Multiplicacion");
printf("\n4: Division");
printf("\nDigite el numero de la opcion elegida: ");
scanf ("%i", &op);
while (op<1 || op>4) {
printf ("\nError, debe ser entre 1 y 4 ");
scanf ("%i", &op);
}
printf("\nIntroduzca los dos numeros a operar: ");
scanf ("%f %f", &x, &y);
switch (op) {
case 1:
suma (x,y);
break;
case 2:
resta (x,y);
break;
case 3:
multi (x,y);
break;
case 4:
divi (x,y);
break;
}
i++;
printf("\nPara hacer otra operacion, digite 1 ");
scanf("%i", &otra);
}
printf ("\nSe realizaron %i operaciones", i);
getch(); //pausa
}

28

Вам также может понравиться