Ultima actualización: Nov 23 de 2005

CONTENIDO:



OBSERVACIONES

Lea detenidamente las deficiones de este taller de tal forma que le queden claros los conceptos.  Desarrolle cada uno de los ejemplos que se plantean, ejecútelos en C y entiéndalos.  No se afane por desarrollar los ejercicios de la parte final. 

1. Funciones


Una función es un conjunto de declaraciones, definiciones, expresiones y sentencias que realizan una tarea específica.

Existen dos tipos de funciones: a) Primitivas, que son las predefinidas para un lenguaje de programación y b)Externas, creadas por el programador.

a) FUNCIONES PRIMITIVAS

El lenguaje de Programación C tiene predefinidas una serie de funciones almacenadas dentro de cada una de las bibliotecas, que resultan de mucha ayuda para el programador, ya que le evita tener que construir todo el módulo para determinada operación.

El estándar ANSI C tiene definido el contenido y la forma de la biblioteca estándar de C. Sin embargo, los desarrolladores elaboran funciones adicionales.  Las funciones de C están organizadas por bibliotecas de la siguiente forma:

- Funciones de entrada y salida: stdio.h, io.h, stdilib.h sys\stat.h, etc.
- Funciones de cadenas
- Funciones matemáticas
- Funciones de fecha, hora y relacionadas con el sistema
- Funciones de asignación de memoria
- Funciones de directorio
- Funciones de control de procesos
- Funciones variadas, entre otras.


El estándar de C define sólo unas pocas palabras reservadas.  Sólo con ellas no puede hacerse un programa "normal'' en la vida real. El programador necesita una serie de funciones y herramientas estándar, que deben estar disponibles en cualquier entorno de programación de C / C++. A este conjunto de funciones se le llama librería estándar. Las funciones se declaran en archivos de cabecera o .h. Las cabeceras contienen única y exclusivamente los prototipos de las funciones. El código o cuerpo de las funciones se incluye en ficheros objeto que son realmente la librería.  Los principales ficheros de cabecera de C  "suelen ser'' los siguientes:


Ejemplo SuperCalculadora. Desarrollar una calculadora científica con los siguientes operadores: Seno, Coseno, Tangente, Logaritmo, Exponente, Potencia, Valor Absoluto, Redondeo, y Raíz Cuadrada, empleando las respectivas funciones. Cada operación debe desarrollarse en funciones separadas, al programa se accede desde un menú de opciones.

Las siguientes funciones son matemáticas, le serán de utilidad, por ello se debe incluir la biblioteca math.h:


La respuesta al problema es (Complete el programa, corríjalo y ejecútelo):

#include<stdio.h>
#include<math.h> //necesaria por las funciones matemáticas
int main()
{
int c, opcion=10; float a,b;
while(opcion!= 0)
{
system("clear"); //Si es bajo windows sería: system("cls");
printf("MENU PRINCIPAL SUPERCALCULADORA\n");
printf("1. Seno\n");
printf("2. Coseno\n");
printf("3. Tangente\n");
printf("4. Logaritmo Natural\n"); //función log()
printf("5. e elevado a una potencia n\n"); //función exp()
printf("6. Base elevada a un exponente);//función pow()
printf("7. Valor Absoluto\n");
printf("8. Logaritmo neperiano de un número\n");//Consulte en Internet la función correspondiente
printf("9. Raiz Cuadrada\n");
printf("0. Salir\n");
printf("Selecciona tu Opción\n");
scanf("%d",&opcion);
switch(opcion)
{
case 1: printf("Digita un número real\n"); scanf("%f",&a);
break;
case 2: printf("Digita un número real\n"); scanf("%f",&a);
break;
//complete aqui los casos que faltan
break;
case 7: printf("Digita un número entero \n"); scanf("%d ",&c);
break;
}
switch(opcion)
{
case 1: printf("El seno de %f es %f\n",a,sin(a));
break;
case 2: printf("El coseno de %f es %f\n",a,cos(a));
break;
case 3: printf("La tangente de %f es %f\n",a,tan(a));
break;
case 4: //complete aquí la instrucción
break;
case 5: //complete aquí la instrucción
break;
//....así sucesivamente
}
getchar();//recibe el enter
getchar();//detiene el programa hasta que se presiona una tecla
}//fin while
printf("Gracias por usar nuestra calculadora, Ciao!\n");
return 0;
}


b) FUNCIONES EXTERNAS

Justamente cuando se requiere que determinado programa desarrolle diferentes operaciones modulares que no se encuentran predefinidas en el lenguaje de programación, el programador debe proceder a implementarlas, constituyendo una función externa. Las funciones se caracterizan por: a) Ofrecer la posibilidad de un único retorno y b) Recepcionar tantos parámetros formales como sea necesario.


El formato general de una función en C es el siguiente:

especificador_de_tipo     nombre_de_función(lista_de_parámetros)
{
variables locales
código de la función

}

El especificador_de_tipo indica el tipo del valor que la función devolverá mediante el uso de return. El valor puede ser de cualquier tipo válido. Si no se específica un valor, entonces la computadora asume por defecto que la función devolverá un resultado entero. No se tienen siempre que incluir parámetros en una función (la lista de parámetros puede estar vacía).

Las funciones terminan y regresan automáticamente al procedimiento que las llamó cuando se encuentra la última llave }, o bien, se puede forzar el regreso antes usando la sentencia return. Ademas del uso señalado la función return se usa para devolver un valor.

Ejemplo. Se examina a continuación un ejemplo que encuentra el promedio de dos enteros:

#include<stdio.h>
float encontprom(int, int);//prototipo de la función

float encontprom(int num1, int num2)
{
float promedio;

promedio = (num1 + num2) / 2.0;
return(promedio);
}

main()
{
int a=7, b=10;
float resultado;

resultado = encontprom(a, b);
printf("Promedio=%f\n",resultado);
}

El siguiente cuadro muestra un resumen completo de la declaración de funciones con su ejemplo respectivo.

Declaración de Función


 [Clase][tipo] identificador(Parám_Formales)
{
    cuerpo

   return [valor];

}


Ejemplos


 int FunX(int a, int b)
{

    int c;

    c=a+b;

    return c;

}

Prototipado de Función

[Clase][tipo] identificador(Parám_Formales);


extern int FunX(int,int);

Invocación de Función

Identificador(Parám_Actuales);


FunX(8,s);

Nota: consultar qué hace cada uno de los especificadores de clase de almacenamiento: extern, static, register y auto.

PASO DE PARÁMETROS

Dependiendo de la lógica de cada función, se hace necesario recibir un simple dato o la dirección de un campo de memoria, hecho que discrimina la forma de remitir los parámetros actuales, hacia los parámetros formales. Si se remite una constante, el contenido de una variable, el resultado de una expresión, o el retorno de otra función, se dice que se hace un envío por valor, mientras que si lo que se manda es la dirección de un campo de memoria, se dice que se hace el envío por referencia.


Paso de parámetros

Declaración por valor

int funcion1(int a, char b){

Nótese que a y b son variables simples que reciben un dato

Declaración por referencia

int funcion1(int *a, char b){

Nótese que el parámetro a se recibió como apuntador

Invocación por valor

funcion1(50, c){

Supóngase que la variable c es de tipo char

Invocación por referencia

funcion1(&s, ‘R’){

Nótese que se envía la dirección de la variable entera s

Al término los cambio que sufran las variables a y b dentro de funcion1 no afectarán particularmente a la variable c

Al término los cambio que se hagan sobre el contenido de lo que apunta a dentro de funcion1, afectarán a la variable s


Ejemplo (Parámetros por Valor)

Diseñar un programa que permita realizar la suma entre dos números enteros leídos. Para ello implemente el siguiente pseudocódigo:

Entero sumar(entero n1,entero n2); //Prototipo


Programa_Principal()
inicio
Haga var a,b: entero
Lea a,b
Escriba a,"+",b,"=",sumar(a,b) //Invocación
Retorne 0
Fin Principal


Entero sumar(entero n1,entero n2) //Declaración
inicio
Haga var res:entero
res= n1 + n2
retorne res
fin funcion




2. Funciones void

Las funciones void dan una forma de emular, lo que en otros lenguajes se conocen como procedimientos (por ejemplo, en PASCAL). Se usan cuando no requiere regresar un valor.  Se muestra un ejemplo que imprime los cuadrados de ciertos números. 

Ejemplo,

#include<stdio.h>
void cuadrados(); //prototipo de la función

void cuadrados()
{
int contador;

for( contador=1; contador<10; contador++)
printf("%d\n",contador*contador);
}

main()
{
cuadrados();//invoca al procedimiento
getchar();
return 0;

}

En la función cuadrados no esta definido ningún parámetro, y por otra parte tampoco se emplea la sentencia return para regresar de la función (porque es de tipo void).

3. Funciones y arreglos

NOTA: El tema de arreglos será estudiado más adelante, por ahora lea la teoría solo como información general.

Cuando se usa un arreglo como un argumento a la función, se pasa sólo la dirección del arreglo y no la copia del arreglo entero. Para fines prácticos podemos considerar el nombre del arreglo sin ningún índice como la dirección del arreglo.

Considerar el siguiente ejemplo en donde se pasa un arreglo a la función imp_rev, observar que no es necesario especificar la dimensión del arreglo cuando es un parámetro de la función.

#include<stdio.h>
#include<string.h>//es necesario incluir esta para que funcione strlen

void imp_rev(char []);//prototipo de la función

void imp_rev(char s[])
{
int t;

for( t=strlen(s)-1; t>=0; t--)
printf("%c",s[t]);
}

main()
{
char nombre[]="Facultad";

imp_rev(nombre);//invoca al procedimiento
getchar();
return 0;
}

Observar que en la función imp_rev se usa la función strlen para calcular la longitud de la cadena sin incluir el terminador nulo. Por otra parte, la función imp_rev no usa la sentencia return ni para terminar de usar la función, ni para regresar algún valor.

Se muestra otro ejemplo,

#include<stdio.h>
float enconprom(int, float []);//prototipo de la función

float enconprom(int tam, float lista[])
{
int i;
float suma = 0.0;

for ( i=0; i<tam; i++)
suma += lista[i];
return(suma/tam);
}

main()
{
float numeros[]={2.3, 8.0, 15.0, 20.2, 44.01, -3.0, -2.9};

printf("El promedio de la lista es %f\n", enconprom(7,numeros) );
getchar();
return 0;
}

Para el caso de que se tenga que pasar un arreglo con más de una dimensión, no se indica la primera dimensión pero, el resto de las dimensiones deben señalarse. Se muestra a continuación un ejemplo:

void imprtabla(int tamx,int tamy, float tabla[][5])
{
int x,y;

for ( x=0; x<tamx; x++ )
{
for ( y=0; y<tamy; y++ )
printf("t[%d][%d]=%f",x,y,tabla[x][y]);
printf("\n");
}
}

4. Prototipos de funciones

Antes de usar una función C debe tener conocimiento acerca del tipo de dato que regresará y el tipo de los parámetros que la función espera.

El estándar ANSI de C introdujó una nueva (mejor) forma de hacer lo anterior respecto a las versiones previas de C.

La importancia de usar prototipos de funciones es la siguiente:

Lo anterior es hecho, dependiendo del alcance de la función.  Básicamente si una función ha sido definida antes de que sea usada (o llamada), entonces se puede usar la función sin problemas.

Si no es así, entonces la función se debe declarar. La declaración simplemente maneja el tipo de dato que la función regresa y el tipo de parámetros usados por la función.

Es una práctica usual y conveniente escribir el prototipo de todas las funciones al principio del programa, sin embargo esto no es estrictamente necesario.

Para declarar un prototipo de una función se indicará el tipo de dato que regresará la función, el nombre de la función y entre paréntesis la lista del tipo de los parámetros de acuerdo al orden que aparecen en la definición de la función. Por ejemplo:

int longcad(char []);

Lo anterior declara una función llamada longcad que regresa un valor entero y acepta una cadena como parámetro.  Los prototipos de las funciones se declaran en la zona de declaraciones globales, antes del main().

5. Ejercicios


NIVEL 1

1. Desarrolle un programa que implemente una función que encuentre el mayor de dos números enteros.

2. Desarrolle un programa que implemente una función que calcule x elevado a la n, x variable real y n entera.

3. Crear una funcion booleana Digito que determine si un caracter es uno de los dígitos 0 a 9.

4. Crear una función salario que calcule los salarios de los trabajadores para un número dado de horas trabajadas y un salario hora.  Las horas que superan las 40 horas semanales se pagarán como extras con un salario hora 1.5 veces el salario ordinario.

5. Desarrolle un programa que implemente una función que intercambie los valores de dos variables A y B (debe utilizar paso de parámetros por referencia necesariamente).


Ejemplo,

A   B
1   20

Despues de ejecutar la función:

A   B
20  1

6. Desarrolle un programa que implemente una función que calcule el factorial de un número.

7. Complete y entregue el ejemplo de la superCalculadora.

8. Diseñar un programa que implemente una función que permita realizar la suma entre dos números enteros.


NIVEL 2

1. Desarrolle un programa que implemente un subprograma que realice la conversión de cordenadas polares a cordenas cartesianas. x = r.cos(J)   y = r.sen(J).

2. El número de combinaciones de m elementos tomados de n en n es:

m  =           m!     
n            n!(m-n)!

Crear un programa que permita calcular el número combinatorio (m/n) utilizando funciones.

3. Desarrolle un programa en el que sea posible leer tan solo caracteres alfabéticos, mientras no se digite el caracter ‘.’ y a cada uno de ellos, lo reemplaza por su complementario ya sea mayúsculo a minúsculo, empleando funciones primitivas. En el caso de leer la ‘a’, se imprimirá ‘A’. Nota: Requerirá consultar las funciones del archivo biblioteca ctype.h, específicamente las funciones toupper() y tolower().


NIVEL 3

1. Desarrolle un programa que implemente una función que calcule el MCD de dos números pasados como parámetros.

2.
Desarrolle un programa que implemente una función que acepte un número de mes, un número de día y un número de año y los visualice en el formato:  aaaa/mm/dd siempre y cuando la fecha esté correcta.

3.
Desarrolle un programa que implemente una función que reciba dos números enteros como parámetros y devuelva como resultado los números pero simplificados.  Por ejemplo, si se pasa el 5 y el 10, la función debe devolver 1 y 2.

4. Desarrolle un programa que simule el lanzamiento de los dados, suponga que existen dos competidores, cada uno de ellos lanzará sus dados y finalizará el juego cuando alguno de ellos haya completado 50 puntos. Consultar funciones primitivas para el manejo y generación de números aleatorios (rand o random) en un rango determinado. Debe además, tener funciones externas.  NOTA: Este programa vale por dos de nivel 3, es decir, si hace este ejercicio no necesita presentar otro de nivel 3.

FUNCIONES Y ARREGLOS

NOTA:
Si Usted es una persona pila y autodidacta puede consultar por su cuenta el tema de arreglos en C y hacer los siguientes ejercicios.

5. Escribir una función "reemplaza", la cual toma una cadena como parámetro, le reemplaza todos los espacios de la cadena por un guión bajo, y devuelve el número de espacios reemplazados.
	char cadena[] = "El gato  negro";
n = reemplaza(cadena);
deberá devolver:
	cadena convertida "El_gato__negro"
n = 2

6. Escribir un programa que lea una línea de texto en un buffer (una cadena de caracteres) usando la función gets y calcule la longitud de la línea (NO usar la función strlen()).

¿Qué debe entregar? 

De este taller elabore 2 programas de nivel 1, 2 programas de nivel 2 y 2 programas de nivel 3 (6 en total).  Si se detectan programas copiados entre grupos, serán anulados.  Por favor, ser leales y éticos, el objetivo es aprender y no debe reinar la ley del menor esfuerzo.  Espero que de esa amplia variedad de programas cada grupo tome programas diferentes.

Fecha de entrega: Diciembre 9 de 2005.  Grupos de 2 personas máximo ó individual.  El disquete debe ser entregado en la oficina del docente (401)entre las 9:00 a.m y 12:00 p.m.

Forma de entrega
: los programas  se deben entregar en un disquete bueno, etiquetado con los nombres del grupo, formateado y revisado de tal forma que no tenga sectores defectuosos (Si el disquete no abre la nota será de 0.0, formatearlo y ver que en la estadística diga 0 sectores defectuosos).  En el disquete no deben haber más archivos que los de este taller y organizados de tal forma que sea fácil detectar los ejercicios por cada nivel.  Para ello organícelos  en UNA SOLA carpeta asi: nivel1_NoDel Ejercicio.c, nivel2_NoDel Ejercicio.c, nivel3_NoDelEjercicio.c.   Por ejemplo, si elaboró el ejercicio del número combinatorio deberá colocarle el siguiente nombre:  nivel2_ejercicio2.c. (Los programas con extensión .cpp no serán calificados).

Recuerde indentar adecuadamente los programas (menos dos puntos de la nota si no indenta adecuadamente - Luego no se queje que no sabía!!) y crear una interfaz lo más agradable e intuitiva para el usuario, utilice su creatividad e imaginación (Este concepto se le conoce como usabilidad).





Bibliografía: