TEMA 11

Biblioteca stdlib.h

Para usar todas las funciones de ésta biblioteca se debe tener la siguiente directiva

#include

Las funciones de la biblioteca pueden ser agrupadas en tres categorías básicas:

• Aritméticas;
• Números aleatorios; y
• Conversión de cadenas.

El uso de todas las funciones es sencillo. Se consideran dentro del capítulo en forma breve.

FUNCIONES ARITMETICAS

Hay cuatro funciones enteras básicas:

int abs(int j);

long int labs(long int j);

div_t div(int numer, int denom);

ldiv_t ldiv(long int numer, long int denom);


Fundamentalmente hay dos funciones para enteros y para compatibilidad con enteros largos.

• abs() La función regresa el valor absoluto del argumento entero j.
• div() Calcula el valor numer entre denom y devuelve el cociente y el resto en una estructura llamada div_t que contiene dos miembros llamados quot y rem.

La estructura div_t esta definida en stdlib.h como sigue:

typedef struct {
int quot; /* cociente */
int rem; /* residuo */
} div_t;

La estructura ldiv_t es definida de una forma similar.

Se muestra un ejemplo donde se hace uso de la función div_t:

#include

main()
{
int num=8, den=3;
div_t res;

res = div(num,den);

printf("Respuesta:\n\t Cociente = %d\n\t Residuo = %d\n",
res.quot, res.rem);
}

que genera la siguiente salida:

Respuesta:

Cociente = 2
Residuo = 2

NUMEROS ALEATOREOS

Los números aleatorios son útiles en programas que necesitan simular eventos aleatorios, tales como juegos, simulaciones y experimentos. En la práctica ninguna función produce datos aleatorios verdaderos -- las funciones producen números pseudo-aleatorios. Los números aleatorios son calculados a partir de una fórmula dada (los distintos generadores usan diferentes fórmulas) y las secuencias de números que son producidas se repiten. Una semilla (seed) es usualmente inicializada para que la secuencia sea generada. Por lo tanto, si la semilla es siempre inicializada con el mismo valor todo el tiempo, el mismo conjunto será siempre calculado.

Una técnica común para introducir más aleatoriedad en el generador de números aleatorios es usando el tiempo y la fecha para inicializar la semilla, ya que éste siempre estará cambiando.

Hay muchas funciones de números (pseudo) aleatorios en la biblioteca estándar. Todas ellas operan con la misma idea básica pero generan secuencias diferentes de números (basadas en funciones generadoras diferentes) sobre rangos diferentes de números.

El conjunto más simple de funciones es:

int rand(void);

void srand(unsigned int semilla);

• rand() La función devuelve un entero pseudo-aleatorio entre 0 y (RAND_MAX).
• srand() Establece su argumento como la semilla de una nueva serie de enteros pseudo-aleatorios.

Un ejemplo sencillo del uso del tiempo de la fecha es inicializando la semilla a través de una llamada:

srand( (unsigned int) time( NULL ) );

El siguiente programa tarjeta.c muestra el uso de estas funciones para simular un paquete de tarjetas que esta siendo revueltas.

/*
** Se usan numeros aleatorios para revolver las "tarjetas" de la baraja.
** El segundo argumento de la funcion indica el numero de tarjetas.
** La primera vez que esta funcion es llamada, srand es
** llamada para inicializar el generador de numeros aleatorios.
*/

#include
#include
#define VERDADERO 1
#define FALSO 0

void intercambiar( int *baraja, int n_cartas )
{
int i;
static int primera_vez = VERDADERO;

/*
** Inicializar el generador de numeros con la fecha actual
** si aun no se ha hecho.
*/
if( primera_vez ){
primera_vez = FALSO;
srand( (unsigned int)time( NULL ) );
}

/*
** "intercambiar" empleando pares de cartas.
*/

for( i = n_cartas - 1; i > 0; i -= 1 ){
int alguno;
int temp;

alguno = rand() % i;
temp = baraja[ alguno ];
baraja[ alguno ] = baraja[ i ];
baraja[ i ] = temp;
}
}

CONVERSION DE CADENAS

Existen unas cuantas funciones para convertir cadenas a enteros, enteros largos y valores flotantes. Estas son:

• double atof(const char *cadena) Convierte una cadena a un valor flotante.
• int atoi(const char *cadena) Convierte una cadena a un valor entero.
• int atol(const char *cadena) Convierte una cadena a un valor entero largo.
• double strtod(const char *cadena, char **finap) Convierte una cadena a un valor de punto flotante.
• double strtol(const char *cadena, char *finap, int base) Convierte una cadena a un entero largo de acuerdo a una base dada, la cual deberá estar entre 2 y 36 inclusive.
• unsigned long strtoul(const char *cadena, char *finap, int base) Convierte una cadena a un entero largo sin signo.

Varias de las funciones se pueden usar en forma directa, por ejemplo:

char *cad1 = "100";
char *cad2 = "55.444";
char *cad3 = " 1234";
char *cad4 = "123cuatro";
char *cad5 = "invalido123";
char *cad6 = "123E23Hola";
char *cad7;

int i;
float f:

i = atoi(cad1); /* i = 100 */
f = atof(cad2); /* f = 55.44 */
i = atoi(cad3); /* i = 1234 */
i = atoi(cad4); /* i = 123 */
i = atoi(cad5); /* i = 0 */
f = strtod(cad6, &cad7); /* f=1.230000E+25 y cad7=hola*/

Nota:

• Los caracteres en blanco son saltados.
• Caracteres ilegales son ignorados.
• Si la conversión no puede ser hecha se regresa cero y errno es puesta con el valor ERANGE.

BUSQUEDA Y ORDENAMIENTO

La biblioteca stdlib.h tiene dos funciones útiles para hacer búsqueda y ordenamiento de datos de cualquier tipo. La función qsort() ya fue vista previamente en la sección 10.3.

Para completar la lista se anota el prototipo, pero para ver un ejemplo pasar al capítulo indicado.

La función qsort de la biblioteca estándar es muy útil, ya que esta diseñada para ordenar un arreglo por un valor llave de cualquier tipo en orden ascendente, con tal de que los elementos del arreglo sean de un tipo fijo.

El prototipo de la función de acuerdo a stdlib.h es:

void qsort(void *base, size_t nmiemb, size_t tam,

int (*compar)(const void *, const void *));

Similarmente, hay una función para búsqueda binaria, bsearch() la cual tiene el siguiente prototipo en stdlib.h como:

void *bsearch(const void *key, const void *base, size_t nmemb,

size_t size, int (*compar)(const void *, const void *));

A continuación se muestra un ejemplo que hace uso de la función bsearch():

#define TAM 10
#include
#include

typedef struct {
int llave;
char informacion[30];
} Registro;

int compara_registro(void const *i, void const *j)
{
int a, b;

a = ((Registro *) i)->llave;
b = ((Registro *) j)->llave;
return a - b;
}

main()
{

Registro llave;
Registro *resp;
Registro arreglo[TAM];
int long_arreglo = TAM;

arreglo[0].llave = -43; arreglo[1].llave = -9; arreglo[2].llave = 0;
arreglo[3].llave = 3; arreglo[4].llave = 4; arreglo[5].llave = 9;
arreglo[6].llave = 10; arreglo[7].llave = 12; arreglo[8].llave = 30;
arreglo[9].llave = 203;

printf("Introduce el valor de la llave que se buscara en el arreglo: ");
scanf("%d",&llave.llave); /* valor del indice que sera buscado */
resp = (Registro *) bsearch(&llave, arreglo, long_arreglo, sizeof(Registro),
compara_registro);
if (resp != NULL )
printf("Se localizo la llave %d\n",resp->llave);
else
printf("No se localizo ningun elemento con la llave %d\n", llave.llave);
}

La función bsearch() regresa un apuntador al registro que coincide con la llave dada, o bien, el valor NULL si no encuentra el registro.

Observar que el tipo del argumento de la llave debe ser del mismo tipo que la del arreglo de los elementos (en nuestro caso Registro).

REGRESAR ARRIBA


REGRESAR A LA PAGINA INICIAL