Ver Mensaje Individual
  #4 (permalink)  
Antiguo 18/08/2003, 09:08
leonardop
 
Fecha de Ingreso: julio-2003
Mensajes: 165
Antigüedad: 21 años, 8 meses
Puntos: 1
(continuación)

Código:
#include <ctype.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>



/*** Macros ***/

#define TAMBUF  1024  /* Tamanyo para bufer de entrada */



/*** Definicion de tipos de datos personalizados ***/

/* Tipo de datos para la gestion del menu del programa */

typedef enum _OpcionMenu OpcionMenu;

enum _OpcionMenu
{
    MENU_LISTAR_DATOS = 1,

    MENU_AGREGAR_DATO,
    MENU_ELIMINAR_DATO,
    MENU_MODIFICAR_DATO,

    MENU_LEER_ARCHIVO,
    MENU_GUARDAR_ARCHIVO,

    MENU_SALIR,

    MENU_FIN  /* Elemento especial para marcar el final de la
               * enumeracion */
};


/* Tipo de datos que almacena valores y descripciones para el menu */

typedef struct _Menu Menu;

struct _Menu
{
    OpcionMenu valor;

    /* Le damos un tamanyo fijo, a sabiendas de que solo el
     * programador puede operar sobre este tipo de
     * estructuras. Asumimos que el programador sabe lo que hace,
     * cierto? */
    char descripcion[81];
};


typedef unsigned char uchar;  /* Alias para unsigned char */



/*** Prototipos de funciones ***/

void arreglar (char *);

void bit_definir   (uchar *, int, int);
int  bit_recuperar (uchar *, int);

int  bits_agregar   (uchar **, int);
int  bits_eliminar  (uchar **, int);
void bits_listar    (uchar *, int);
void bits_modificar (uchar *, int);

void bits_guardar   (uchar *, int);
int  bits_leer      (uchar **);

int leer_entero (void);



/*** Funcion principal ***/

int
main (void)
{
    static Menu datos_menu[] = {
        {MENU_LISTAR_DATOS,    "Listar datos"},
        {MENU_AGREGAR_DATO,    "Agregar dato"},
        {MENU_ELIMINAR_DATO,   "Eliminar dato"},
        {MENU_MODIFICAR_DATO,  "Modificar dato"},
        {MENU_LEER_ARCHIVO,    "Leer datos desde archivo"},
        {MENU_GUARDAR_ARCHIVO, "Guardar datos en archivo"},
        {MENU_SALIR,           "Salir"}};

    OpcionMenu opcion;
    int i;

    uchar *secuencia = NULL;  /* Secuencia de bits */
    int cantidad = 0;  /* Cantidad de bits que se estan manipulando */


    /* Mensaje de introduccion. Se siente un poco mejor cuando el
     * programa le da la bienvenida al usuario, y le dice brevemente
     * de que se trata el asunto. */

    printf ("\n"
"Bienvenido.\n"
"Este programa realiza algunas manipulaciones simples con bits.\n\n"
"Por favor seleccione una opcion:\n\n");


    for (i = 0; i < MENU_FIN - 1; i++)
        printf ("  %d. %s\n", datos_menu[i].valor, datos_menu[i].descripcion);


    do {
        printf ("\nopcion> ");

        opcion = leer_entero ();

        switch (opcion) {
        case MENU_LISTAR_DATOS:
            bits_listar (secuencia, cantidad);
            break;

        case MENU_AGREGAR_DATO:
            cantidad = bits_agregar (&secuencia, cantidad);
            break;

        case MENU_ELIMINAR_DATO:
            cantidad = bits_eliminar (&secuencia, cantidad);
            break;

        case MENU_MODIFICAR_DATO:
            bits_modificar (secuencia, cantidad);
            break;

        case MENU_LEER_ARCHIVO:
            cantidad = bits_leer (&secuencia);
            break;

        case MENU_GUARDAR_ARCHIVO:
            bits_guardar (secuencia, cantidad);
            break;

        case MENU_SALIR:
            break;

        default:
            printf ("\nOpcion invalida.\n");
        }

    } while (opcion != MENU_SALIR);

    printf ("\nAdios pues..\n");

    return 0;
}



/*** Declaracion de funciones ***/


/* arreglar()
 *
 * Sencilla funcion que se encarga de asegurarse de que una cadena
 * solo contenga caracteres validos, de acuerdo a la funcion
 * isgraph(). Todos los caracteres no-validos son eliminados */

void
arreglar (char *cadena)
{
    int i, j;
    int longitud;

    longitud = strlen (cadena);

    for (i = j = 0; i < longitud; i++) {
        if (isgraph(cadena[i])) {
            if (i != j)
                cadena[j++] = cadena[i];
            else
                j++;
        }
    }

    cadena[j] = '\0';
}


/* bit_definir()
 *
 * Define el valor de un bit determinado dentro de una secuencia de
 * bits, que se asume esta en orden little-endian. Recibe en orden: la
 * secuencia de bits, la posicion a definir, y el nuevo valor para el
 * bit */

void
bit_definir (uchar *sec, int pos, int val)
{
    uchar temp = 1 << (7 - (pos % 8));

    sec[pos / 8] = (uchar) (val ? sec[pos / 8] | ((uchar)temp) :
                            sec[pos / 8] & ((uchar)~temp));
}


/* bit_recuperar()
 *
 * Devuelve el valor de un bit determinado, en una secuencia de bytes
 * dada. Recibe la secuencia de bytes, y la posicion del bit que se
 * desea consultar. Asume que la secuencia esta en orden
 * little-endian. */

int
bit_recuperar (uchar *sec, int pos)
{
    return (int)((sec[pos / 8] >> (7 - (pos % 8))) & 1);
}


/* bits_agregar()
 *
 * Recibe una referencia a una secuencia de bits y la cantidad de bits
 * que contiene. Pide un nuevo valor al usuario y lo agrega al final
 * de la secuencia. Retorna el nuevo numero de elementos de la
 * secuencia. */

int
bits_agregar (uchar **sec, int n)
{
    int nuevo_bit;

    if (n == 0)
        *sec = (uchar *) malloc (sizeof (uchar));
    else if (n % 8 == 0)
        *sec = (uchar *) realloc (*sec, sizeof (uchar) * (n / 8 + 1));

    if (*sec == NULL) {
        printf ("Error de ubicacion de memoria.\n");
        exit (1);
    }

    printf ("\nIngrese el valor del nuevo bit:\n");

    do {
        printf ("> ");
        nuevo_bit = leer_entero ();

        if (nuevo_bit < 0 || nuevo_bit > 1)
            printf ("\nPor favor ingrese 0 o 1.\n");

    } while (nuevo_bit != 0 && nuevo_bit != 1);

    bit_definir (*sec, n, nuevo_bit);

    return n + 1;
}


/* bits_eliminar()
 *
 * Recibe una referencia a una secuencia de bits, y la cantidad de
 * bits que contiene. Esta funcion que pide al usuario una posicion
 * dentro de la secuencia y procede a eliminar el dato en tal
 * posicion. Retorna el nuevo numero de elementos de la secuencia. */

int
bits_eliminar (uchar **sec, int n)
{
    int pos;
    int i;

    if (n < 1) {
        printf ("\nNo hay elementos para eliminar.\n");
        return n;
    }

    else if (n == 1) {
        free (*sec);
        *sec = NULL;

        printf ("\nEl ultimo elemento disponible fue eliminado.\n");
        return 0;
    }

    printf ("\nIngrese la posicion a eliminar (valor entre 0 y %d)\n", n - 1);

    do {
        printf ("> ");
        pos = leer_entero ();

        if (pos < 0 || pos >= n)
            printf ("Ingrese un valor entre 0 y %d\n", n - 1);
    } while (pos < 0 || pos >= n);


    /* Aqui, por sencillez, optaremos por usar nuestras funciones
     * bit_recuperar() y bit_definir(), aunque este proceso de
     * eliminacion podria optimizarse considerablemente usando
     * translaciones directas de bits. */

    for (i = pos + 1; i < n; i++)
        bit_definir (*sec, i - 1, bit_recuperar (*sec, i));

    printf ("\nSe ha eliminado la posicion %d.\n", pos);

    return n - 1;
}


/* bits_listar()
 *
 * Funcion que lista el valor de una secuencia de bits. Recibe la
 * secuencia (en forma de apuntador a ``unsigned char'', y el numero
 * de bits a listar */

void
bits_listar (unsigned char *sec, int n)
{
    int i;

    if (n < 1) {
        printf ("\nNo hay datos en el momento.\n");
        return;
    }

    printf ("\nLa secuencia de bits actual es:\n\n");

    for (i = 0; i < n; i++)
        printf ("%d\t", bit_recuperar (sec, i));

    printf ("\n\nTotal de bits: %d\n", n);
}


/* bits_modificar() Recibe una secuencia de bits y la cantidad de
 * valores en la secuencia. Pide al usuario una posicion a modificar y
 * el nuevo valor para tal posicion, para realizar asi la
 * modificacion. */

void
bits_modificar (uchar *sec, int n)
{
    int nuevo_bit;
    int pos;

    if (n < 1) {
        printf ("\nNo hay datos para modificar.\n");
        return;
    }
    
    if (n == 1)
        pos = 0;
    else {
        printf ("\nIngrese la posicion a modificar (valor entre 0 y %d)\n",
                n - 1);

        do {
            printf ("> ");
            pos = leer_entero ();

            if (pos < 0 || pos >= n)
                printf ("Ingrese un valor entre 0 y %d\n", n - 1);
        } while (pos < 0 || pos >= n);
    }

    printf ("\nIngrese el nuevo valor del bit No. %d:\n", pos);

    do {
        printf ("> ");
        nuevo_bit = leer_entero ();

        if (nuevo_bit < 0 || nuevo_bit > 1)
            printf ("\nPor favor ingrese 0 o 1.\n");

    } while (nuevo_bit != 0 && nuevo_bit != 1);

    bit_definir (sec, pos, nuevo_bit);
}


/* leer_entero()
 *
 * Funcion que se limita a leer un valor entero desde el teclado */

int
leer_entero (void)
{
    char bufer[TAMBUF];

    fgets (bufer, TAMBUF, stdin);

    return atoi (bufer);
}
(continúa)