Anuncios

Bienvenidos sean a este post, hoy continuaremos con los rangos o scope pero esta vez para las funciones.

Anuncios
Anuncios

En el post anterior hablamos sobre como es el scope o rango de una variable a lo largo del programa pero las funciones tambien tienen un rango como las variables pero lo podemos considerar un poco mas simple que estas, las declaraciones de funciones son muy similares a la declaracion de variables externas, esto es asi porque al igual que las variables deben ser declaradas antes de ser accedidas las funciones deben ser declaradas o por lo menos declarar sus prototipos antes de ser llamadas, y a su vez estas tambien disponen de un rango de archivo, porque pueden ser llamadas desde cualquier parte del archivo una vez declaradas o declarado el prototipo, si bien en algunos casos con simplemente declarar una funcion antes de ser llamada alcanza por esta razon es una buena practica utilizar prototipos al comienzo y luego definirlos, esto nos da la posibilidad de poder garantizar el llamado a la funcion cuando queramos y desde donde queramos sin necesidad de preocuparnos, pero como logramos extenderlo? bueno, eso es facil y sin saberlo ya lo hemos hecho.

Anuncios
Anuncios

Para que una funcion sea accesible desde otros archivos simplemente debemos incluirlo, es decir usar a #include y el archivo en cuestion, por ejemplo cuando nosotros incluimos a stdio.h lo que hacemos es basicamente cargarle los prototipos de las funciones que incluye para que podamos trabajar con ellas, por ejemplo printf, en este post creamos un archivo con funciones externas y a traves de incluirlas pudimos acceder a ellas, esto mismo se aplica a las definiciones de enum y struct realizads por medio de typedef, con esto podemos hacer que todas nuestras funciones sean globales pero podemos restringuir el acceso a solo el archivo? si podemos a continuacion hablaremos sobre ello.

Anuncios

El rango y como esconder informacion

Para limitar al rango de las funciones para solo su unidad de compilacion disponemos de dos formas, comentemos como es la primera.

Anuncios

La primera es simplemente eliminando los prototipos de un archivo de encabezado que no queremos que crucen el limite el rango de linkage, de esta forma cualquier codigo fuente que incluya al archivo de encabezado no tendra al prototipo excluido y sera incapaz de llamarlo, para entenderlo vamos a usar el codigo que vimos en este post, a continuacion les dejo un archivo para descargar el codigo:

Anuncios

Simplemente extraigan todos los elementos, nuestro siguiente paso sera hacer algunas modificaciones, del archivo libs/funciones.h veamos como es la parte de los prototipos:

ListaNombres* CreaListaNombres();
ListaNodo* CrearListaNodo(char* aNombreAgregar);
void AgregarNombre(ListaNombres* aNombres, char* aNombreAgregar);
void BorrarNombre(ListaNombres* aNombres);
bool EstaVacio(ListaNombres* aNombres);
void MostrarNombres(FILE* salidaDesc, ListaNombres* aNombres);
void MasAllaAlmacenamiento();

Anuncios

En este codigo tenemos unos cuantos prototipos que no son necesarios que accedamos desde todo el programa, ya que en realidad las unicas funciones que debemos tener acceso son los siguientes:

  • AgregarNombre
  • BorrarNombre
  • MostrarNombres
Anuncios

Porque estan las funciones que trabajan sobre nuestra lista en el main, el resto solo pertenecen a los procesos internos para trabajar con estas funciones, por lo tanto modifiquemos el codigo de la siguiente manera:

libs/funciones.h

#ifndef _ORDENA_NOMBRES_H_
#define _ORDENA_NOMBRES_H_

#include <stdio.h>
#include <string.h>
#include <stdbool.h>
#include <stdlib.h>

typedef char ListaDatos;

typedef struct _Nodo ListaNodo;
typedef struct _Nodo
{
	ListaNodo* aProximo;
	ListaDatos* aDatos;
} ListaNodo;

typedef struct
{
	ListaNodo* aPrimerNodo;
	int cuentaNodos;
} ListaNombres;

void AgregarNombre(ListaNombres* aNombres, char* aNombreAgregar);
void BorrarNombre(ListaNombres* aNombres);
void MostrarNombres(FILE* salidaDesc, ListaNombres* aNombres);

#endif
Anuncios

Basicamente tomamos el mismo codigo fuente y le sacamos los prototipos que no necesitamos y solamente dejamos los mencionados, tambien se pueden comentar sino quieren borrarlos, pero en todo caso no deben existir en este archivo, nuestro siguiente paso sera tomar el archivo libs/funciones.c y agregaremos los prototipos que eliminamos anteriormente:

libs/funciones.c

#include "funciones.h"

ListaNombres* CreaListaNombres();
ListaNodo* CrearListaNodo(char* aNombreAgregar);
void MasAllaAlmacenamiento();
bool EstaVacio(ListaNombres* aNombres);

ListaNombres* CrearListaNombres()
{
	ListaNombres* aLN = (ListaNombres*)calloc(1,sizeof(ListaNombres));
	if (aLN == NULL) MasAllaAlmacenamiento();
	return aLN;
}

ListaNodo* CrearListaNodo(char* aNombreAgregar)
{
	ListaNodo* aNuevoNodo = (ListaNodo*)calloc(1,sizeof(ListaNodo));
	if(aNuevoNodo == NULL) MasAllaAlmacenamiento();
	aNuevoNodo->aDatos = (char*)calloc(1,strlen(aNombreAgregar)+1);
	if(aNuevoNodo->aDatos == NULL) MasAllaAlmacenamiento();
	strcpy(aNuevoNodo->aDatos, aNombreAgregar);
	return aNuevoNodo;
}

void AgregarNombre(ListaNombres* aNombres, char* aNombreAgregar)
{
	ListaNodo* aNuevoNombre = CrearListaNodo(aNombreAgregar);

	if(EstaVacio(aNombres))
	{
		aNombres->aPrimerNodo=aNuevoNombre;
		(aNombres->cuentaNodos)++;
		return;
	}

	(aNombres->cuentaNodos)++;
	ListaNodo* actual;
	ListaNodo* previo;
	actual=previo=aNombres->aPrimerNodo;
	while(actual)
	{
		if(strcmp(aNuevoNombre->aDatos, actual->aDatos) < 0)
		{
			if(actual==aNombres->aPrimerNodo)
			{
				aNombres->aPrimerNodo = aNuevoNombre;
				aNuevoNombre->aProximo = actual;
			} else {
				previo->aProximo = aNuevoNombre;
				aNuevoNombre->aProximo = actual;
			}
			return;
		}
		previo = actual;
		actual = previo->aProximo;
	}
	previo->aProximo = aNuevoNombre;
}

void MostrarNombres(FILE* salidaDesc, ListaNombres* aNombres)
{
	ListaNodo* actual=aNombres->aPrimerNodo;
	while(actual)
	{
		fputs(actual->aDatos, salidaDesc);
		fputc('\n', salidaDesc);
		actual=actual->aProximo;
	}
}

void BorrarNombre(ListaNombres* aNombres)
{
	while(aNombres->aPrimerNodo)
	{
		ListaNodo* temp=aNombres->aPrimerNodo;
		aNombres->aPrimerNodo=aNombres->aPrimerNodo->aProximo;
		free(temp->aDatos);
		free(temp);
	}
}

bool EstaVacio(ListaNombres* aNombres)
{
	return aNombres->cuentaNodos==0;
}

void MasAllaAlmacenamiento()
{
	fprintf(stderr, "### FATAL RUNTIME ERROR ### Sin memoria");
	exit(EXIT_FAILURE);
}
Anuncios
Anuncios

Basicamente lo que hicimos fue agregar los prototipos eliminados al comienzo de este archivo, el resto sigue sin alteraciones, esto lo hacemos asi porque recuerden que las funciones deben estar declaradas antes de ser llamadas y con el prototipo cubrimos esta necesidad, recuerden que de esta forma la funcion quedo solamente dentro de la unidad de compilacion pero si en algun momento necesitan que las funciones se utilicen en todo el programa deben mover los prototipos a los archivos de encabezado, por eso decimos que hasta cierto punto delimitar el acceso a las funciones es mas simple que en las variables, si se lo preguntan el programa deberia seguir funcionando de la misma forma porque no tocamos nada que altere al codigo del main y debe funcionar de la siguiente manera como se ve en este video

Anuncios

En resumen, hoy hemos visto el scope o rango para las funciones, como se puede superar los limites y hacerlo global, asi como tambien limitarlo para que solo trabaje en la unidad de compilacion, para ello tomamos un ejemplo que vimos en este post e hicimos las modificaciones necesarias, espero les haya sido de utilidad sigueme en tumblr, Twitter o Facebook para recibir una notificacion cada vez que subo un nuevo post en este blog, nos vemos en el proximo post.

Anuncios

Donación

Es para mantenimento del sitio, gracias!

$1.50