lect_30Sept

Anuncio
Programación Estructurada (en C)
Dr. Eric Jeltsch F.
Cuando se invoca a una función, y se tenga solamente acceso a los valores de sus
argumentos, y NO a los argumentos mismos, se dirá que es una llamada por valor.
En C todas las llamadas son por valor, es decir, es imposible que una función llamada
tenga acceso directo a un objeto definido en la función.
Variables locales
Las variables que declaramos justo al principio del cuerpo de una función son variables
locales. Este programa, por ejemplo, declara dos variables locales para calcular la
sumatoria de los primeros 10, nº natural.
#include <stdio.h>
int sumatoria(int a, int b)
{
int i, s; // Variables locales a sumatoria.
s = 0;
for (i=a; i<=b; i++)
s += i;
return s;
}
int main(void)
{
int i; // Variable local a main.
for (i=1; i<=10; i++)
printf ("Sumatorio de los %d primeros n´umeros naturales: %d\n", i,
sumatoria(1, i));
getch();
return 0;
}
Las variables locales i y s de sumatoria() sólo “viven” durante las llamadas a
sumatoria(). Las variables locales sólo son visibles en el cuerpo de la función en la
que se declaran; por tal motivo se dice que ése es su ámbito.
Variables globales
Las variables globales se declaran fuera del cuerpo de cualquier función y son
accesibles desde cualquier punto del programa posterior a su declaración. Este
fragmento de programa, por ejemplo, define una variable global i y una variable local a
main con el mismo identificador:
#include <stdio.h>
int i = 1; // Variable global i.
int doble(void)
{
i *= 2; // Referencia a la variable global i.
return i; // Referencia a la variable global i.
}
int main(void)
{
int i; // Variable local i.
___________________________________________________________________
Escuela Ingeniería en Computación, Universidad de La Serena
1
Programación Estructurada (en C)
Dr. Eric Jeltsch F.
for (i=0; i<5; i++) // Referencias a la variable local i.
printf ("%d\n", doble());//Ojo: el valor corresponde a la i global.
getch();
return 0;
}
Fijarse en la pérdida de legibilidad que supone el uso del identificador i en diferentes
puntos del programa: hemos de preguntarnos siempre si corresponde a la variable local
o global. Por lo mismo, No se aconseja el uso generalizado de variables globales en los
programas.
#include <stdio.h>
int contador ; // Variable global.
void fija(int a)
{
contador = a;
}
int decrementa(int a)
{
contador -= a;
return contador ;
}
void muestra(int contador)
{
printf ("[%d]\n", contador);
}
void cuenta_atras(int a)
{
int contador;
for (contador=a; contador >=0; contador--)
printf ("%d ", contador);
printf ("\n");
}
int main(void) {
int i;
contador = 10;
i = 1;
while (contador >= 0) {
muestra(contador);
cuenta_atras(contador);
muestra(i);
decrementa(i);
i *= 2;
}
getch();
return 0;
}
___________________________________________________________________
Escuela Ingeniería en Computación, Universidad de La Serena
2
Programación Estructurada (en C)
Dr. Eric Jeltsch F.
Funciones sin parámetros
Por otra parte, en el contexto de las funciones, un uso típico de ellas, en donde no es
necesario usar parámetros es por ejemplo, la lectura de datos por teclado que deben
satisfacer una serie de restricciones. Esta función, por ejemplo, lee un número entero de
teclado y se asegura de que sea par:
int lee_entero_par(void)
{
int numero;
scanf ("%d", &numero);
while (numero % 2 != 0) {
printf ("El n´umero debe ser par y %d no lo es.\n", numero);
numero = scanf ("%d", &numero);
}
return numero;
}
int main(void) {
int i; int contador = 10;
i = 1;
while (contador >= 0) {
lee_entero_par();
i *= 2;
}
getch();
return 0;
}
Este otro programa muestra por pantalla los 10 primeros números primos. La función
siguienteprimo() genera cada vez un número primo distinto. Gracias a la variable
global ultimoprimo() la función “recuerda” cuál fue el último número primo
generado.
#include <stdio.h>
int ultimoprimo = 0;
int siguienteprimo(void)
{
int esprimo , i;
do {
___________________________________________________________________
Escuela Ingeniería en Computación, Universidad de La Serena
3
Programación Estructurada (en C)
Dr. Eric Jeltsch F.
ultimoprimo++;
esprimo = 1;
for (i=2; i<ultimoprimo/2; i++)
if (ultimoprimo % i == 0) {
esprimo = 0;
break;
}
} while (!esprimo);
return ultimoprimo;
}
int main(void)
{
int i;
printf ("Los 10 primeros n´umeros primos\n");
for (i=0; i<10; i++)
printf ("%d\n", siguienteprimo());
getch();
return 0;
}
Otro uso típico es la presentación de menús de usuario con lectura de la opción
seleccionada por el usuario:
int menu_principal(void)
{
int opcion;
do {
printf
printf
printf
printf
("1)
("2)
("3)
("4)
Alta usuario\n");
Baja usuario\n");
Consulta usuario\n");
Salir\n");
printf ("Opcion: "); scanf ("%d", &opcion);
if (opcion < 1 || opcion > 4)
printf ("Opcion no valida.\n");
} while (opcion < 1 || opcion > 4);
return opcion;
}
Procedimientos o función o ambas.
Un procedimiento es una función que no devuelve valor alguno. Los procedimientos
provocan efectos laterales, como imprimir un mensaje por pantalla, modificar variables
globales o modificar el valor de sus parámetros. Los procedimientos en C se declaran
como funciones con tipo de retorno void. Por ejemplo:
#include <stdio.h>
void saludos(void)
{
printf ("Hola, mundo.\n");
}
En un procedimiento puedes utilizar la sentencia return, pero sin devolver valor alguno.
Cuando se ejecuta una sentencia return, finaliza inmediatamente la ejecución del
procedimiento.
___________________________________________________________________
Escuela Ingeniería en Computación, Universidad de La Serena
4
Programación Estructurada (en C)
Dr. Eric Jeltsch F.
Paso de parámetros (Parámetros escalares: paso por valor)
Aunque modifique el valor de un parámetro escalar en una función o procedimiento, el
valor de la variable pasada como argumento permanece inalterado. La función bits del
siguiente programa, por ejemplo, modifica en su cuerpo el valor de su parámetro num:
#include <stdio.h>
int bits(unsigned int num )
{
int b = 0;
do {
b++;
num /= 2;
} while (num > 0);
return b;
}
int main(void)
{
unsigned int numero ;
int bitsnumero;
printf ("Introduce un entero positivo: ");
scanf ("%u", &numero );
bitsnumero = bits(numero );
printf ("Hay %d bits en %u.\n", bitsnumero, numero );
getch();
return 0;
}
Al ejecutar el programa y teclear el número 128 se muestra por pantalla lo siguiente:
Introduce un entero positivo: 128
Hay 8 bits en 128.
Como puede ver, el valor de numero permanece inalterado tras la llamada a bits,
aunque en el cuerpo de la función se modifica el valor del parámetro num (que toma el
valor de numero en la llamada). Un parámetro es como una variable local, sólo que su
valor inicial se obtiene copiando el valor del argumento que suministramos. Así pues,
num no es numero, sino otra variable que contiene una copia del valor de numero. Es
lo que se denomina paso de parámetro por valor.
Paso de funciones como parámetros
Hay un tipo de parámetro especial que puedes pasar a una función: ¡otra función!. Esto
en todo caso lo veremos más adelante, para cuando veamos punteros y paso por
referencia, para distinguirse del paso por valor. Veamos un ejemplo. En este fragmento
de programa se definen sendas funciones C que aproximan numéricamente la integral
definida en un intervalo para las funciones matemáticas f(x) = x2 y f(x) = x3,
respectivamente:
#include <stdio.h>
float integra(float a, float b, int n, float (*f)(float))
{
int i;
float s, x;
___________________________________________________________________
Escuela Ingeniería en Computación, Universidad de La Serena
5
Programación Estructurada (en C)
Dr. Eric Jeltsch F.
s = 0.0;
x = a;
for (i=0; i<n; i++) {
s += f(x) * (b-a)/n;
x += (b-a)/n;
}
return s;
}
float cuadrado(float x)
{
return x*x;
}
float cubo(float x)
{
return x*x*x;
}
int main(void)
{
printf ("Integral 1: %f\n", integra(0.0, 1.0, 10, cuadrado ));
printf ("Integral 2: %f\n", integra(0.0, 1.0, 10, cubo ));
getch();
return 0;
}
Finalmente digamos que nunca esta demás el que considere que los #include permiten
usar funciones ya escritas e incluidas en grandes colecciones denominadas librerías. Las
más usuales son:
#include
#include
#include
#include
<stdio.h>
<conio.h>
<stdlib.h>
<math.h>
permite usar printf, scanf, fread, fwrite, fopen,
permite usar clrscr y otras funciones..
permite usar rand
permite usar funciones trigonométricas
___________________________________________________________________
Escuela Ingeniería en Computación, Universidad de La Serena
6
Descargar