Está en la página 1de 11

TEMA I Programacin Modular Programacin I

Uno de los problemas habituales del programador ocurre cuando los programas
alcanzan un tamao considerable en cuanto a lnea de cdigo. El problema se
puede volver tan complejo que fuera inabordable.
Para mitigar este problema apareci la programacin modular. En ella el
programa se divide en mdulos de tamao manejable. Cada mdulo realiza una
funcin mu concreta se pueden programar de forma independiente. !e basa en
Concentrar los esfuerzos en resolver problemas sencillos una vez resueltos" el
conjunto de esos problemas soluciona el problema original.
En definitiva la programacin modular implementa el paradigma divide y
vencers" tan importante en la programacin. El programa se descompone en
mdulos. #os mdulos se puede entender que son pequeos programas. $eciben
datos a partir de ellos realizan un c%lculo o una determinada tarea. Una vez el
mdulo es probado validado se puede utilizar las veces que haga falta en el
programa sin necesidad de tener que volver a programar.
En C los mdulos se llaman funciones. En los temas anteriores hemos usado
algunas funciones implementadas en las libreras del lenguaje C &printf scanf
por ejemplo'. El lenguaje C proporciona diversas funciones a preparadas &se las
llama funciones estndar' para evitar que el programador tenga que codificar
absolutamente todo el funcionamiento del programa.
#as funciones son invocadas desde el cdigo utilizando su nombre. Cuando
desde el cdigo se invoca a una funcin" entonces el flujo del programa salta
hasta el cdigo de la funcin invocada. (espu)s de ejecutar el cdigo de la
funcin" el flujo del programa regresa al cdigo siguiente a la invocacin.
Uso de las Funciones.
*oda aplicacin de consola creada en lenguaje C se basa en una funcin llamada
main que contiene el cdigo que se ejecuta en primer lugar en el programa.
(entro de ese main habr% llamadas a funciones a creadas" bien por el propio
programador o bien funciones que forman parte de las bibliotecas de C o de
bibliotecas privadas &una biblioteca o librera no es m%s que una coleccin de
funciones'.
+s por ejemplo,
int main(){
printf(%lf, pow(3,4));
}
Ese cdigo utiliza dos funciones" la funcin printf que permite escribir en la
pantalla la funcin pow que permite elevar un n-mero a un e.ponente &en el
ejemplo calcula, /0'.
Para poder utilizarlas las funciones tienen que estar definidas en el cdigo del
programa o en un archivo e.terno. !i est%n en un archivo e.terno &como ocurre en
el ejemplo' habr% que incluir la cabecera de ese archivo para que al crear el
Prof. Mara Anglica Lpez
TEMA I Programacin Modular Programacin I
ejecutable de nuestro programa se enlacen los archivos compilados de las
funciones e.ternas que utilice el programa.
Es decir ha que indicar en qu) archivos se definen esas funciones. En el ejemplo"
habra que incluir al principio estas lneas,
#include <stdio.h>
#include <math.h>
Crear de las Funciones.
!i creamos funciones" )stas deben definirse en el cdigo. #os pasos para definir
una funcin son,
El tipo de datos que devuelve dicha funcin &si no devuelve nada" se indica con
la palabra void'
El nombre de la funcin" se indica justo despu)s del tipo de datos &en la misma
lnea.
#os parmetros que acepta a funcin" se colocan en la misma lnea se
encierran entre par)ntesis. #os par%metros son los datos de entrada que necesita
la funcin para trabajar. Por ejemplo una funcin que sirva para dibujar el
cuadrado seguramente tendr% como par%metro el tamao del cuadrado. Una
funcin que no usa par%metros se suele indicar colocando la palabra void en el
que normalmente iran los par%metros &ho en da se puede obviar esta palabra"
pero no los par)ntesis'
1ndicar las variables locales a la funcin
1ndicar las instrucciones de la funcin
1ndicar el valor que devuelve mediante la palabra return &salvo que la funcin
sea void'
!inta.is,
tipo nombreDeLaFuncin(parmetros){
definiciones
instrucciones
}
#a primera lnea de la sinta.is anterior es lo que se llama el prototipo de la
funcin. Es la definicin formal de la funcin. (esglosamos m%s su contenido,
tipo. !irve para elegir el tipo de datos que devuelve la funcin. *oda funcin
puede obtener un resultado. Eso se realiza mediante la instruccin return. El tipo
puede ser, int, char, long, float, double".... tambi)n void. 2ste -ltimo se utiliza
si la funcin no devuelve ning-n valor & a estas funciones se las suele llamar
procedimientos'.
nombreDeLafuncin. El identificador de la funcin. (ebe cumplir las reglas a
comentadas en temas anteriores correspondientes al nombre de los
identificadores.
parmetros. !u uso es opcional" ha funciones sin par%metros &funciones con
par%metros void'. #os par%metros son una serie de valores que la funcin puede
Prof. Mara Anglica Lpez
TEMA I Programacin Modular Programacin I
requerir para poder ejecutar su trabajo. En realidad es una lista de variables los
tipos de las mismas. !on variables cua e.istencia est% ligada a la funcin.
Ejemplo de funcin,
double potencia(int base, int exponente){
int contador;
int negativo; /* Indica si el exponente es negativo*/
double resultado=.!;
if (exponente<!) {
exponente="exponente;
negativo=;
}
for(contador=;contador<=exponente;contador##)
resultado$=base;
if (negativo) resultado=%resultado;
return resultado;
}
En los par%metros ha que indicar el tipo de cada par%metro &en el ejemplo se
pone int base, int exponente no int base, exponente'" si no se pone el tipo se
suele tomar el tipo int para el par%metro &aunque esto puede no ser as en
algunos compiladores'.
Prototipos de las Funciones
En realidad fue el lenguaje C++ el que ide los prototipos" pero C los ha aceptado
para verificar mejor el tipo de los datos de las funciones.
3racias a estos prototipos el compilador reconoce desde el primer momento las
funciones que se van a utilizar en el programa. #os prototipos se ponen al principio
del cdigo &tras las instrucciones #include' delante del main.
Ejemplo &programa completo',
#include <stdio.h>
#include <conio.h>
/*Prototipo de la funcin*/
double potencia(int base, int exponente);
int main(&'
int b, e;
do{
printf((scriba la base de la potencia (o cero para salir&;
scanf(%d,)b&;
if (b*=!){
printf((scriba el exponente&;
scanf(%d,)e&;
printf(+esultado, %lf, potencia(b,e&&;
}
}while(b*=!&;
getch(&;
Prof. Mara Anglica Lpez
TEMA I Programacin Modular Programacin I
}
double potencia(int base, int exponente&{
int contador;
int negativo=!;
double resultado=.!;
if (exponente<!) {
exponente="exponente;
negativo=;
}
for(contador=;contador<=exponente;contador##&
resultado$=base;
if (negativo& resultado=%resultado;
return resultado;
}
+unque no es obligatorio el uso de prototipos" s es mu recomendable a que
permite detectar errores en compilacin &por errores en el tipo de datos' que
seran mu difciles de detectar en caso de no especificar el prototipo.
Funciones void
+ algunas funciones se les pone como tipo de datos el tipo void. !on funciones
que no devuelven valores. !irven para realizar una determinada tarea pero esa
tarea no implica que retornen un determinado valor. Es decir son funciones sin
instruccin return.
+ estas funciones tambi)n se las llama procedimientos. 4uncionan igual salvo
por la cuestin de que al no retornar valores" no tienen por qu) tener instruccin
return. !i se usa esa instruccin dentro de la funcin" lo -nico que ocurrir% es que
el flujo del programa abandonar% la funcin &la funcin finaliza'.
5o es mu recomendable usar as el return en funciones de tipo void a que
propicia la adquisicin de mu malos h%bitos al programar &programacin no
estructurada'.
Parmetros !ariables
6a se ha comentado antes que las funciones pueden utilizar par%metros para
almacenar valores necesarios para que la funcin pueda trabajar.
#a cuestin es que los par%metros de la funcin son variables locales que recogen
valores enviados durante la llamada a la funcin que esas variables mueren tras
finalizar el cdigo de la funcin.
En el ejemplo anterior" base exponente son los par%metros de la funcin
potencia. Esas variables almacenan los valores utilizados en la llamada a la
funcin &por ejemplo si se llama con potencia(7,2)" base tomar% el valor 7
exponente el valor8'.
Paso de parmetros por Valor y por Referencia
En el ejemplo,
Prof. Mara Anglica Lpez
TEMA I Programacin Modular Programacin I
int x=-, .=/;
printf(%lf,potencia(x,y)&;
!e llama a la funcin potencia utilizando como par%metros los valores de . e .
Estos valores se asocian a los par%metros base exponente. #a duda est% en
qu) ocurrir% con x si en la funcin se modifica el valor de base.#a respuesta es"
nada.
Cuando se modifica un par%metro dentro de una funcin no le ocurre nada a la
variable que se utiliz para pasar valores a la funcin. En el ejemplo" base tomar%
una copia de x. Por lo que x no se ver% afectada por el cdigo de la funcin.
Cuando ocurre esta situacin se dice que el par%metro se pasa por valor.
!in embargo en la funcin scanf ocurre lo contrario,
scanf(%d,)x&;
#a variable x s cambia de valor tras llamar a scanf. Esto significa que x se pasa
por referencia. En realidad en C slo se pueden pasar valores" otros lenguajes
&como Pascal por ejemplo' admiten distincin. En C para usar el paso por
referencia ha que pasar la direccin de la variable &9.'" o lo que es lo mismo un
puntero a la variable.
Es decir la llamada scanf"#$d%,&'( enva la direccin de x a la funcin printf" esa
funcin utiliza dicha funcin para almacenar el n-mero entero que el usuario
escriba por teclado.
Variables static
#as variables static son variables que permanecen siempre en la memoria del
ordenador. !u uso fundamental es el de variables locales a una funcin cuo valor
se desea que permanezca entre llamadas.
Para entender mejor su uso" veamos este ejemplo,
#include <stdio.h>
#include <stdlib.h>
void prueba(&;
int main(&'
int i;
for(i=;i<=!;i##) prueba();
s.stem(0pause0&;
}
void prueba(){
int var=!;
var##;
printf(%d1n,var&;
}
En el ejemplo" se llama :; veces seguidas a la funcin prueba()" esta funcin
escribe siempre lo mismo" el n-mero :. #a razn est% en que la variable var se
Prof. Mara Anglica Lpez
TEMA I Programacin Modular Programacin I
crea e inicializa de nuevo en cada llamada a la funcin muere cuando el cdigo
de la funcin finaliza. Con lo que siempre vale :.
!i modificamos las declaracin de la variable var para que ahora sea est%tica,
void prueba(){
static int var=!;
var##;
printf(%d1n,var&;
}
+hora el resultado es absolutamente distinto" al ser est%tica la variable var se crea
en la primera llamada permanece en memoria" es decir no se elimina al finalizar
la funcin. En la segunda llamada no se crea de nuevo la variable" es m%s la
instruccin de creacin se ignora" a que la funcin a est% creada. El resultado
ahora es absolutamente distinto. +parecer%n en pantalla los n-meros del : al :;.
Ambito de las variables y las funciones
*oda variable tiene un ciclo de vida que hace que la variable sea declarada"
inicializada" utilizada las veces necesarias finalmente eliminada. En la
declaracin adem%s de declarar el tipo" implcitamente estamos declarando el
%mbito" de modo que una variable que se declara al inicio se considera global"
significa pues que se puede utilizar en cualquier parte del archivo actual.
!i una variable se declara dentro de una funcin" )sta muere en cuanto la funcin
termina. #o mismo ocurre con los par%metros" en realidad los par%metros son
variables locales que copian el valor de los valores enviados en la llamada a la
funcin" pero su comportamiento es el mismo que el de las variables locales.
#as variables static son variables locales que mantienen su valor entre las
llamadas" es decir no se eliminan pero slo se pueden utilizar en la funcin en la
que se crearon.
El %mbito m%s pequeo lo cubren las variables declaradas dentro de un bloque &<='
de una funcin. Estas variables slo se pueden utilizar dentro de las llaves en las
que se defini la variables" tras la llave de cierre del bloque &='" la variable muere.
Es importante tener en cuenta que todo lo comentado anteriormente es
aplicable a las funciones. 5ormalmente una funcin es global" es decir su
prototipo se coloca al principio del archivo eso hace que la funcin se pueda
utilizar en cualquier parte del archivo" pero lo cierto es que se puede definir una
funcin dentro de otra funcin. En ese -ltimo caso dicha funcin slo se puede
utilizar dentro de la funcin en la que se declara.
Definicin de macro funciones con #define
#a directiva de procesador #define" que permite declarar constantes" en realidad
macros. !e trata de definiciones que son sustituidas cuando se preprocesa el
cdigo.
+s,
#define 234567892:3; <
Prof. Mara Anglica Lpez
TEMA I Programacin Modular Programacin I
>ar% que cuando aparezca en el cdigo el te.to ?+@ACB#U?5+!" el
preprocesador lo sustituir% por :C.
#a realidad es que Ddefine permite macroEsustituciones m%s elaboradas" a que
permite que se usen par%metros en la definicin.
Por ejemplo,
#define 693=+3=7(x& x$x
Cuando el preprocesador se encuentra con esta definicin en el cdigo" sustituir%
esta funcin por su forma e.pandida" por ejemplo,
area>otal=693=+3=7(base&;
el preprocesador lo convertir% en,
area>otal=base$base;
>a que tener cuidado con el uso prioritario de los operadores" de hecho conviene
siempre definir el resultado de la funcin entre par)ntesis" de otro modo puede
haber problemas" por ejemplo,
#define ?@ -.A<BC
#define 6@+69:D(+(:6@3(x& C$x$?@
4allara en la e.presin,
longitud6ircunf=6@+69:D(+(:6@3(h"-&;
6a que se e.pande como,
longitud6ircunf = C$h"-$?@;
6 eso es no calcula lo que pretendemos. Por lo que la definicin correcta sera,
#define 6@+69:D(+(:6@3(x& (C$(x&$?@&
6 el ejemplo anterior quedara e.pandido como,
longitud6ircunf = (C$(h"-&$?@&
#a ventaja de usar macros en lugar de funciones es que se evita usar llamadas a
funciones &lo que acelera la ejecucin del programa'. Pero tiene dos desventajas a
tener en cuenta,
El tamao del cdigo aumenta. 6a que se e.pande m%s cdigo
El uso de macros queda fuera del normal planteamiento estructurado de
creacin de programas. Es decir en tiempo de diseo no se suelen plantear
macros
>a otra desventaja a comentar,
#os lenguajes modernos &como Fava' no utilizan macros.
Por lo que si nos acostumbramos en e.ceso a su uso" adquiriremos h%bitos que
no son compatibles con esos lenguajes.
Recursividad
#a recursividad es una t)cnica de creacin de funciones en la que una funcin se
llama a s misma. >a que ser mu cauteloso con ella &incluso evitarla si no es
Prof. Mara Anglica Lpez
TEMA I Programacin Modular Programacin I
necesario su uso'" pero permite soluciones mu originales" a veces" mu claras a
ciertos problemas. (e hecho ciertos problemas &como el de las torres de >anoi"
por ejemplo' seran casi imposibles de resolver sin esta t)cnica.
#a idea es que la funcin resuelva parte del problema se llame a s misma para
resolver la parte que queda" as sucesivamente. En cada llamada el problema
debe ser cada vez m%s sencillo hasta llegar a una llamada en la que la funcin
devuelve un -nico valor.
Es fundamental tener en cuenta cu%ndo la funcin debe dejar de llamarse a s
misma" es decir cuando acabar. (e otra forma se corre el riesgo de generar
infinitas llamadas" lo que bloqueara de forma grave el PC en el que trabajamos.
Un bucle infinito utilizando recursividad causa graves inestabilidades en el
ordenador de trabajo.
Como ejemplo vamos a ver la versin recursiva del factorial.
double factorial(int n&'
if(n<=& return ;
else return n$factorial(n"&;
}
#a -ltima instruccin &return n*factoria(n!")) es la que realmente aplica la
recursividad. #a idea &por otro lado m%s humana' es considerar que el factorial de
nueve es nueve multiplicado por el factorial de ochoG a su vez el de ocho es ocho
por el factorial de siete as sucesivamente hasta llegar al uno" que devuelve uno.
Para la instruccin factorial")(* usando el ejemplo anterior" la ejecucin del
programa generara los siguientes pasos,
(1) !e llama a la funcin factorial usando como par%metro el n-mero 0 que ser%
copiado en la variableEpar%metro n
() Como nH:" entonces se devuelve 0 multiplicado por el resultado de la llamada
factorial"+(
(!) #a llamada anterior hace que el nuevo n &variable distinta de la anterior' valga
/" por lo que esta llamada devolver% / multiplicado por el resultado de la llamada
factorial",(
(") #a llamada anterior devuelve 8 multiplicado por el resultado de la llamada
factorial"-(
(#) Esa llamada devuelve :
($) Eso hace que la llamada factorial",( devuelva 8I:" es decir 8
(%) Eso hace que la llamada factorial"+( devuelva /I8" es decir J
(&) Por lo que la llamada factorial")( devuelve 0IJ" es decir ,) 6 ese es a el
resultado final
" ' factorial(!)
! ' factorial()
' factorial(1)
1
Ciclo de llamadas
recursivas
" ' ! ' ' 1
Prof. Mara Anglica Lpez
TEMA I Programacin Modular Programacin I
! ' ' 1
' 1
1
.evolucin de valores /lustracin -, Pasos para reali0ar la recursividad
(ibliotecas
En cualquier lenguaje de programacin se pueden utilizar bibliotecas &tambi)n
llamadas libreras' para facilitar la generacin de programas. Estas bibliotecas en
realidad son una serie de funciones organizadas que permiten realizar todo tipo de
tareas.
Cualquier entorno de programacin en C permite el uso de las llamadas
bibliotecas est%ndar" que son las que incorpora el propio lenguaje de
programacin.
>a varias libreras est%ndar en C. Para poder utilizarlas se debe incluir su archivo
de cabecera en nuestro cdigo" avisando de esa forma al compilador de que se
debe enlazar el cdigo de dicha librera al nuestro para que el programa funcione.
Eso se realizar mediante la directiva de procesador #include seguida del nombre
del archivo de cabecera de la librera. Ese archivo suele tener e.tensin .h
contiene las declaraciones de las funciones de dicha librera.
)*emplo de librer+a estndar, mat-
#at$ es el nombre de una librera que incorpora funciones matem%ticas. Para
poder utilizar dichas funciones ha que aadir la instruccin
#include <ath!h"
al principio del cdigo de nuestro archivo. Cada directiva incude se coloca en una
lnea separada no requiere punto coma al ser una indicacin al compilador no
una instruccin de verdad.
Esta librera contiene las siguientes funciones &se indican los prototipos uso',
Prototipo Descripcin
int abs"int n( (evuelve el valor absoluto del n-mero entero
indicado
int ceil"double n( $edondea el n-mero decimal n obteniendo el menor entero maor o
igual que n. Es decir cei(2.%) devuelve / cei(2.7) tambi)n devuelve /
double cos"double n( Bbtiene el coseno de n &n se e.presa en radianes'
double e'p"double n( Bbtiene en
double fabs"double n( Bbtiene el valor absoluto de n &siendo n un n-mero doube'
int floor"double n( $edondea el n-mero decimal n obteniendo el maor entero menor o
igual que n. Es decir foor(2.%) devuelve 8 foor(2.7) tambi)n devuelve 8
double fmod"double x, double y( Bbtiene el resto de la divisin entera de x&y
double log"double n( (evuelve el logaritmo neperiano de n
double log-1"double n( (evuelve el logaritmo decimal de n
double po2"double base, double exponente( Bbtiene baseexponente
double sin"double n( Bbtiene el seno de n &n se e.presa en radianes'
double s3rt"double n( Bbtiene la raz cuadrada de n
double sin"double n( Bbtiene la tangente de n &n se e.presa en radianes'
Prof. Mara Anglica Lpez
TEMA I Programacin Modular Programacin I
./meros Aleatorios
Btras de las funciones est%ndar m%s usadas son las de manejo de n-meros
aleatorios. Est%n incluidas en stdlib.h.
#a funcin rand"( genera n-meros aleatorios entre ; una constante llamada
456.7859 que est% definida en la propia stdlib.h &normalmente vale /87J7'.
+s el cdigo,
for(i=;i<=!!;i##)
printf(0%d1n0,rand()&;
3enera :;; n-meros aleatorios entre ; $+5(A?+@. Para controlar los n-meros
que salen se usa el operador del mdulo &K' que permite obtener en este caso
n-meros aleatorios en un rango m%s concreto.
Por ejemplo,
for(i=;i<=!!;i##)
printf(0%d1n0,rand(&%!&;
Bbtiene :;; n-meros aleatorios del ; al L. Pero ha un problema" los n-meros
son realmente pseudoaeatorios" es decir la sucesin que se obtiene siempre es
la misma &se basa en una frmula matem%tica'. +unque los n-meros circulan del
; al L con apariencia de falta de orden o sentido" lo cierto es que la serie es la
misma siempre.
#a razn de este problema reside en lo que se conoce como semilla. #a semilla es
el n-mero inicial desde el que parte el programa. Es un primer n-mero que se
pasa a la funcin de generacin de n-meros. !i pasamos siempre la misma
semilla" la sucesin de n-meros generados ser% la misma.
#a semilla se puede generar mediante la funcin srand. #a funcin srand recibe
un n-mero entero que ser% la semilla en la que se inicie la sucesin. !i usamos
semillas distintas en cada ejecucin" tendremos sucesiones de n-meros distintas.
Para que sea impredecible conocer la semilla se usa la e.presin,
srand(tie(#$%%));
Esa e.presin toma un n-mero entero a partir de la fecha hora actual" por lo que
dicho n-mero es impredecible &vara en cada cent)sima de segundo'. +s
realmente el cdigo,
srand(time(:988&&;
for(i=;i<=!!;i##)
printf(%d1n,rand(&%!&;
genera cien n-meros del ; al L que variar%n en cada ejecucin del programa"
siendo considerados n-meros aleatorios debido a que la semilla usa el reloj del
sistema &cuo valor no se puede controlar'.
Prof. Mara Anglica Lpez
TEMA I Programacin Modular Programacin I
0rear nuestras propias librer+as
Majo el paradigma de reutilizar el cdigo" normalmente las funciones interesantes
que crean los usuarios" es conveniente agruparlas en archivos que luego se
pueden reutilizar.
Para ello se hacen los siguientes pasos,
(1) !e crea en un archivo &generalmente con e.tensin .h' las funciones. En esos
archivos se agrupan las funciones seg-n temas. Esos archivos no tendrn
ninguna funcin main" slo se incluen las funciones de nuestra librera
() !e crea el archivo principal con su funcin main correspondiente.
(!) En dicho archivo se utiliza la instruccin incude seguida de la ruta al archivo
que contiene alguna de las funciones que deseamos usar. Esa ruta debe ir entre
comillas dobles &de otra forma se busca el archivo en la carpeta de libreras
est%ndar'. Cada archivo de funciones requiere una instruccin incude distinta.
(") Cada vez que un archivo requiera usar funciones de una librera habr% que
incluir dicho cdigo. Eso puede provocar que se inclua m%s de una vez el cdigo
de las funciones" lo que provocara errores.
(ebido a este -ltimo punto es conveniente que un archivo que es susceptible de
ser incluido m%s de una vez utilice la directiva #ifndef. !e trata de una directiva
que hace que )l cdigo se compile si e.iste la constante a la que hace referencia.
El uso es,
#ifndef constante
cdigo que se ejecuta si la constante no a sido
definida
#endif
El cdigo tras la lnea #ifndef" slo se compila si la constante no ha sido definida
con un Ddefine. Por ello en un archivo que corre el riesgo de ser incluido m%s de
una vez &lo que podemos entender que le podra ocurrir a cualquier archivo de
librera'" se pone el siguiente cdigo &supongamos que se trata del archivo
matematicas8.h',
#ifndef 23>(23>@63;C5E
. . . cdigo del arcivo
#define 23>(23>@63;C5E
#endif
Cuando se inclua este cdigo por primera vez" la constante ?+*E?+*1C+!8A>
no estar% definida" por lo que se incluir% el cdigo del archivo. #a lnea del Ddefine
se traducir% por lo tanto se definir% la constante. !i otro archivo vuelve a incluir a
)ste" el cdigo no se compilar% &por lo tanto se evita el error' a que ahora s
aparece como definida ?+*E?+*1C+!8A>.
Prof. Mara Anglica Lpez

También podría gustarte