Ejemplo 9.2

    Se desea diseñar una estructura que contenga la información de operaciones financieras. Esta estructura debe contar con un número de cuenta, una cantidad de dinero, el tipo de operación (deposito=0, retiro de fondos=1, puesta al dia=2 o estado de cuenta=3) y la fecha y hora en que la operaciópn se ha realizado.

    #include <stdio.h>

    #include <conio.h>

    #include <dos.h>

    /*declaracion de las estructuras*/

    struct fecha

    {

    unsigned int mes, dia, anyo;

    };

    struct tiempo

    {

    unsigned int horas, minutos;

    };

    struct registro_operacion

    {

    long numero_cuenta;

    float cantidad;

    int tipo_operacion;

    struct fecha f;

    struct tiempo t;

    };

    struct registro_operacion entrada();

    main()

    {

    struct registro_operacion w;

    w=entrada();

    printf("\n\n operacion realizada\n");

    printf("\t%ld\n", w.numero_cuenta);

    /*ATENCION: note, la forma en la que llamamos a los miembros

    de una estructura anidada*/

    printf("\t%d-%d-%d\n", w.f.dia, w.f.mes, w.f.anyo);

    printf("\t%d:%d\n", w.t.horas, w.t.minutos);

    getch();

    return 0;

    }

    struct registro_operacion entrada()

    {

    struct time t;

    struct date d;

    struct registro_operacion una;

    printf("\nNumero de cuenta:\n");

    scanf("%ld", &una.numero_cuenta);

    puts("\nTipo de Operacion:\n");

    puts("Deposito (0)");

    puts("Retirada de Fondos (1)");

    puts("Puesta al Dia (2)");

    puts("Estado de Cuenta (3)");

    scanf("%d", &una.tipo_operacion);

    /*fecha y tiempo del sistema*/

    gettime(&t);

    una.t.horas=t.ti_hour;

    una.t.minutos=t.ti_min;

    getdate(&d);

    una.f.anyo=d.da_year;

    una.f.mes=d.da_mon;

    una.f.dia=d.da_day;

    return una;

    }

    Explicación

    A fin de realizar el acceso correcto a los campos día, mes y año, así como el tiempo (la hora y los minutos) en que se efectuó la operación, se define una estructura fecha y una estructura tiempo. La estructura registro_operación tiene como miembro una variable (un campo) de tipo fecha, otra variable de tipo tiempo y otras variables para representar los otros campos. La estructura de tipo operación se hace con una variable entera. A continuación se declara tipos, se escribe una función que lee una operación financiera y devuelve la operación leída. La fecha y hora es capturada del sistema. (ejemplo tomado de "Algoritmos y Estructuras de datos, una perspectiva en C", Luis Joyanes Aguilar)

     

 

    Arrays de Estructuras

    Los ejemplos de estructuras que hemos visto hasta el momento, sólo podemos manejar un conjunto de datos a la vez, o podemos declarar varias variables para manejar, por ejemplo, los datos de 5 alumnos de una institución.

    Sin embargo, al igual que los tipos int, float... en c, podemos crear arrays con estructuras.

    Por ejemplo, supongamos que ya tenemos declarada una estructura llamada datos, que contiene los datos personasles de alumnos de cierta institución, y queremos guardar los datos de 100 alumnos, no necesitamos de crear 100 variables de tipo estructura, sino que hacemos esta declaratoria:

    strcut datos alumnos[100];

    Ejemplo 9.3

    Una biblioteca, desea tener un registro de los libros que en ella se encuentran, se sabe que existe un número no mayor a 100 libros, y que los datos que se necesitan registrar son: el nombre del autor, el título del libro y las existencias del mismo. Diseñe una estructura que sea capaz de guardar esa información y luego mandarla a impresión.

    #include <stdio.h>

    #include <conio.h>

    #include <stdlib.h>

    #define N 100

    struct info_libro

    {

    char autor[20];

    char titulo[30];

    int num_ejemplares;

    };

    main()

    {

    struct info_libro libro[N];

    int i=0;

    clrscr();

    printf("\t\tPROGRAMA QUE CONTROLA UN INVENTARIO DE LIBROS\n\n\n");

    for(i=1; i<=N; i++)

    {

    printf("Ingrese los datos del libro %d\n",i);

    printf("Nombre del autor: ");

    scanf("%s", &libro[i].autor);

    printf("El titulo del libro es: ");

    scanf("%s", &libro[i].titulo);

    printf("Las existencias de este libro son:\n");

    scanf("%d", &libro[i].num_ejemplares);

    }

    clrscr();

    printf("\t\t\tLOS DATOS SON LOS SIGUIENTES:\n\n\n");

    for(i=1; i<=N; i++)

    {

    printf("********************************************\n");

    printf("Autor: %s\n", libro[i].autor);

    printf("Titulo: %s\n", libro[i].titulo);

    printf("Existencias: %d\n", libro[i].num_ejemplares);

    }

    getch();

    return 0;

    }

    Lo más resaltante que, debo rescatar es que, a diferencia de los vectores y las matrices, las estructuras no identifican su primer elemento con cero, sino con el número uno, es por ello que nuestro contador, inicia con ese número, además que, para diferenciar un registro por otro, debemos incluir siempre el subíndice, [i].

    Estructuras y Funciones

    Cuando hacemos uso de funciones y de estructuras, debemos tener en cuenta la forma correcta, de cómo enviarle a la función el parámetro deseado, y con las estructuras, no es la excepción, por ejemplo:

    /*declaración de la estructura*/

    struct info_libro

    {

    char autor[20];

    char titulo[30];

    int num_ejemplares;

    };

    /*declaración de las funciones */

    void impresión (struct info_libro *ptr);

    void impresión1 (struct info_libro p);

    /*definición de la estructura*/

    struct info_libro libros;

    /*llamado de la funcion: envío por referencia*/

    impresión(&libros);

    /*¨llamado de la función: envío por valor*/

    impresión (libros);

    Uso del typedef

    Un operador typedef permite al programador crear un sinónimo de tipo definido por el usuario o de un tipo ya exitente. La sintaxis es la siguiente:

    typedef tipo_de_dato nuevotipodedato;

    a partir de la declaració hecha por el typedef se puede hacer uso del nuevo sinónimo del tipo de dato para definir variables, en general donde se utilizan los tipos de datos.

    Veamos un ejemplo donde matemos dos pájaros de un solo tiro, es decir donde se muestren el uso de funciones y el typedef.

    Ejemplo 9.4

    Un médico almacena la siguiente información de sus paciente en un array de registros (como mucho habrá 100 pacientes): Nombre, teléfono, dirección, y si tiene alergias. Escribir un programa con las siguientes opciones (todas ellas diben realizarse con funciones):
    a) Introducir los datos interactivamente. Para saber que ya no se van a introducir más pacientes, el usuario introducirá un 0 al solicitarle el número de teléfono del paciente.
    b) Imprimir por pantalla toda la información.
    c) Listar todos los pacientes con alergias.
    d) Crear una lista con el índice de todos los pacientes que sean de la Comunidad de Madrid (su teléfono comienza por el prefijo 91).
    e) Salir.

    #include <stdlib.h>

    #include <conio.h>

    #include <stdio.h>

    #include <string.h>

    #define TAM_NOM 31

    #define TAM_DIR 41

    #define TAM_ALE 71

    #define TAM_PAC 100

    typedef struct {

    char nombre[TAM_NOM];

    double telefono;

    char direccion[TAM_DIR];

    char alergias[TAM_ALE];

    } reg_paciente;

    void tecla();

    char menu();

    void leerdatos(reg_paciente *pacientes, int *tamano);

    void hayalergias(reg_paciente *pacientes, int tamano);

    void imprimirtodos(reg_paciente *pacientes, int tamano);

    void telefono91(reg_paciente *pacientes, int tamano);

    void main()

    {

    char opcion;

    int tamano;

    reg_paciente pacientes[TAM_PAC];

    system("color f0");

    printf("\n\n\n\n\n\n\n\n\n\t\t\tINICIO DEL PROGRAMA\n\n\n\n\n\n\n\n");

    tecla();

    leerdatos(pacientes,&tamano);

    do {

    opcion=menu();

    switch(opcion) {

    case '1':

    imprimirtodos(pacientes,tamano);

    break;

    case '2':

    hayalergias(pacientes,tamano);

    break;

    case '3':

    telefono91(pacientes,tamano);

    break;

    case '4':

    leerdatos(pacientes,&tamano);

    break;

    case '0':

    printf("\nSaliendo...");

    break;

    }

    tecla();

    } while (opcion!='0');

    printf("\n\n\n\n\n\n\n\t\t\tFIN DEL PROGRAMA\n\n\n\n\n\n\n");

    tecla();

    }

    void tecla()

    {

    printf("\nPresiona cualquier tecla para continuar ");

    getch();

    clrscr();

    return;

    }

    void leerdatos(reg_paciente *pacientes, int *tamano)

    {

    char buffer[15];

    int i;

    for (i=0;i<TAM_PAC;i++) {

    printf("\n\n\n****PACIENTE NUMERO %2d****",i+1);

    printf("\nIntroduzca el nombre (no m…s de %d caracteres)\n\t",TAM_NOM-1);

    do {

    gets(pacientes[i].nombre);

    } while (strlen(pacientes[i].nombre)==0);

    printf("\nIntroduzca su tel‚fono (o 0 o cualquier letra para no introducir m…s datos)\n\t");

    do {

    gets(buffer);

    } while (strlen(buffer)==0);

    pacientes[i].telefono=atof(buffer);

    if (pacientes[i].telefono==0) {

    *tamano=i;

    break;

    }

    printf("\nIntroduzca la direccion (no m…s de %d caracteres)\n\t",TAM_DIR-1);

    do {

    gets(pacientes[i].direccion);

    } while (strlen(pacientes[i].direccion)==0);

    printf("\nIntroduzca la descripcion de la alergias (no m…s de %d caracteres)\n",TAM_ALE-1);

    printf("\n****Escriba \"NO\" si el paciente no tiene ninguna alergia****\n\t");

    do {

    gets(pacientes[i].alergias);

    } while (strlen(pacientes[i].alergias)==0);

    }

    return;

    }

    char menu()

    {

    char respuesta;

    printf("\n\n\n\n\tMENU DEL PROGRAMA");

    printf("\n1.- Imprimir en la pantalla toda la informacion");

    printf("\n2.- Listar los pacientes con alergias");

    printf("\n3.- Crear una lista de los pacientes con el telefono 91-XXXXXXX");

    printf("\n4.- Crear una lista nueva de pacientes");

    printf("\n0.- Salir del programa.\n");

    do {

    respuesta=getch();

    } while (respuesta<'0' || respuesta>'9');

    return respuesta;

    }

     

    void imprimirtodos(reg_paciente *pacientes, int tamano)

    {

    int i,contimpresos=0;

    printf("\n\tÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛ");

    if (tamano>0) {

    for (i=0;i<tamano;i++) {

    printf("\n\tÛÛ%5d\t%20s\t\t%9.0f\tÛÛ",i+1,pacientes[i].nombre,pacientes[i].telefono);

    printf("\n\tÛÛ\t%40s\tÛÛ",pacientes[i].direccion);

    printf("\n\tÛÛ\t%40s\tÛÛ",pacientes[i].alergias);

    contimpresos++;/*CUENTA EL NUMERO DE LOS QUE SE VAN IMPRIMENDO*/

    if ((contimpresos)%10==0) {

    printf("\n\tÛÛ *** Presione cualquier tecla para continuar. *** ÛÛ");

    getch();

    }

    }

    }

    if (contimpresos==0) printf("\nÛÛ\t No hay ningun dato que mostrar en la pantalla.\t ÛÛ");

    printf("\n\tÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛ");

    return;

    }

     

    void telefono91(reg_paciente *pacientes, int tamano)

    {

    int i,contimpresos=0;

    printf("\n\tÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛ");

    if (tamano>0) {

    for (i=0;i<tamano;i++) {

    if (pacientes[i].telefono>=910000000 && pacientes[i].telefono<920000000) {

    printf("\n\tÛÛ%5d\t%20s\t\t%9.0f\tÛÛ",i+1,pacientes[i].nombre,pacientes[i].telefono);

    printf("\n\tÛÛ\t%40s\tÛÛ",pacientes[i].direccion);

    printf("\n\tÛÛ\t%40s\tÛÛ",pacientes[i].alergias);

    contimpresos++;/*CUENTA EL NUMERO DE LOS QUE SE VAN IMPRIMENDO*/

    if ((contimpresos)%10==0) {

    printf("\n\tÛÛ *** Presione cualquier tecla para continuar. *** ÛÛ");

    getch();

    }

    }

    }

    }

    if (contimpresos==0) printf("\nÛÛ\t No hay ningun dato que mostrar en la pantalla.\t ÛÛ");

    printf("\n\tÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛ");

    return;

    }

    void hayalergias(reg_paciente *pacientes, int tamano)

    {

    int i,contimpresos=0;

    printf("\n\tÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛ");

    if (tamano>0) {

    for (i=0;i<tamano;i++) {

    if (strcmp(pacientes[i].alergias,"NO")!=0 && strcmp(pacientes[i].alergias,"no")!=0 && strcmp(pacientes[i].alergias,"No")!=0) {

    printf("\n\tÛÛ%5d\t%20s\t\t%9.0f\tÛÛ",i+1,pacientes[i].nombre,pacientes[i].telefono);

    printf("\n\tÛÛ\t%40s\tÛÛ",pacientes[i].direccion);

    printf("\n\tÛÛ\t%40s\tÛÛ",pacientes[i].alergias);

    contimpresos++;/*CUENTA EL NUMERO DE LOS QUE SE VAN IMPRIMENDO*/

    if ((contimpresos)%10==0) {

    printf("\n\tÛÛ *** Presione cualquier tecla para continuar. *** ÛÛ");

    getch();

    }

    }

    }

    }

    if (contimpresos==0) printf("\nÛÛ\t No hay ningun dato que mostrar en la pantalla.\t ÛÛ");

    printf("\n\tÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛ");

    return;

    }

    (tomado de "Practicas de C" /*Fernando Muñoz Ledesma .Practica 10.Ejercicio 3*/

    Le recuerdo al lector que, el uso del do...while, en programación estructurada, está prohibido, sin embargo, he decidido, no modificar este ejemplo, pues por respeto al escritor y si decidí colocarlo como ejemoplo es por que considero que es un buen código, muy bien desarrollado, además que, para el lector podría ser un reto, el pasarlo a estructurado.

    Uniones

    Hemos visto que las estructuras toman una parte de la memoria y se la reparten entre sus miembros. Cada miembro tiene reservado un espacio para él solo. El tamaño total que ocupa una estructura en memoria es la suma del tamaño que ocupa cada uno de sus miembros.

    Las uniones tienen un aspecto similar en cuanto a cómo se definen, pero tienen una diferencia fundamental con respecto a las estructuras: los miembros comparten el mismo trozo de memoria. El espacio que ocupa en memoria una unión es el espacio que ocupa el campo más grande. Para entenderlo mejor vamos a ver un ejemplo:

    Primero vamos a ver cómo se define una unión:

    union nombre_de_la_union

    {

    miembros de la union;

    };

    El tamaño de la unión corresponde, a la variable de mayor tamaño, por ejemplo, si en una unión tenemos una variable tipo int (2 bytes), uno de tipo float (4 bytes) y un arreglo de 10 elementos (10 bytes), entonces el tamaño de la unión será de 10 bytes.

    Ejemplo 9.5

    Diseñe un programa que lea el nombre y la inicial de una persona y luego lo imprima:

    #include <stdio.h>

    #include <conio.h>

    union _persona

    {

    char nombre[10];

    char inicial;

    } pers;

    main()

    {

    printf("Escribe tu nombre: ");

    gets(pers.nombre);

    printf("\nTu nombre es: %s\n", pers.nombre);

    printf("Tu inicial es: %c\n", pers.inicial);

    getch();

    return 0;

    }

    (Tomado de "Curso C", por Gorka Urrutia. www.elrincondelc.com)

    Cuestionario

    1. ¿Cómo se define una esructura?________________________________________________________________________________________________________________________________________
    2. ¿Cuál es la diferencia entre una declaración y una definición de la estructura?__________________________________________________________________________________________________________________________________________________________
    3. ¿Cómo se determina el tamaño de una estructura? ¿y el de una unión?_______________________________________________________________________________________________________________________________________________________________
    4. ¿En que se diferencia una estructura de una unión?_______________________________________________________________________________________________________________________________________________________________
    5. ¿Para que sirve el typedef?_____________________________________________________________________________________________________________________________________________________________

    Las siguientes líneas de código presentan errores, puedes identificarlas y corregirlos:

    1. Struct nombre

    {

    char nom[10];

    apellido[10];

    int edad[2];

    }

    2. struct nombre[10];

    3. struct nombre *ptr;

    ptr=&b;

    printf("El nombre es %s\n", ptr.nom);

    Ejercicios

    1. Diseñe un programa que lea e imprima una la fecha del sistema. Declare la fecha como una estructura.
    2. Defina una estructura que contenga los elementos de un número racional (numerador y denominador), y permira sumar, restar, multiplicar y dividir, dos números racionales.
    3. En una tienda de perfumes, se desea crear un programa que controle las facturas de las ventas, dichas facturas deben contener los siguientes datos: número correlativo, nombre del cliente, unidades solicitadas, monto total, estado (morosos, atrasados, pagado). El sistema debe generar el listado de los morosos así como también el total de clientes atrasados y en monto por los pagos de los clientes.
    4. un punto en el plano cartesiano, necesita únicamente una coordenada "x" y otra "Y", definir un programa que muestre:
    5. -la distancia entre los dos puntos (D=sqrt((x2-x1)^2+(y2-y1)^2))

      -La ecuación general del plano

      -el punto medio entre los dos puntos (Xm=(x1+x2)/2; Ym=(y1+y2)/2).

    6. Se desea controlar los registros de personas que tienen seguros de auto, casa y de vida, escriba un programa en C, que permita leer los datos indicados y luego los muestre en pantalla, indicando, lo siguiente:

    -cantidad de personas que poseen más de un seguro

    -cantidad de personas que poseen seguro de vida

    -la nómina de las personas que tienen un seguro mayor a una cantidad ingresada por el usuario

    Capítulo X: Tipos Abstractos de Datos (TAD´s) y Pilas

    Dentro de las tantas ventajas que ofrece C, encontramos la potente herramienta de crear nuestros propios tipos de datos, es decir que C, no nos restringe al uso de los tipos de datos que ta trae definidos, sino que el programador, puede ir creando sus propios tipos para hacer las solucines más fáciles, al proceso anterior es al que se le denomina implementación de TAD’s (Tipo Abstracto de Datos)

    Abstracción

    Es la capacidad de manejar un objeto, (tema o idea) como un concepto general sin considerar la enorme cantidad de detallesque pueden estar asociados con dicho objetoel proceso de abstracción presenta dos aspectos importantes:

    1. Destacar los aspectos relevantes
    2. Ignorar aspectos irrelevantes.

    La abtracción de datos es la técnica que permite inventar o definir nuevos tipos de datos (tipos de datos definidos por el usuario), adecuados a la aplicación que se desea realizar.

    Tipos Abstractos de Datos (TAD):

    Es un conjunto de valores y un grupo de operadores que trabajan sobre tales valores.

    Ejemplo:

    Si tenemos los números dígitos (1, 2, 3,...,9) y los operadores (+, -, *,/), podremos sumar, restar, multiplicar, dividir esos valores.

    Un programa, se compone almenos un TAD más un algoritmo de control

    (PROGRAMA= TAD + ALGORITMO DE CONTROL)

    Ventajas de los TAD’s

    1. Mejora la comprensión y la presentación de los programas
    2. Permite gran riqueza conceptual en nuetros programas
    3. Para los sistemas tipificados, optimiza el tiempo de compilación
    4. Permite la modificación de los mismos sin afectar la interfaz al usuario
    5. Un TAD, lo podemos volver a usar, siempre y cuando lo hayamos creado en archivo de tipo cabecera (*.h), el cual podemos invocar desde cualquier otro programa.
    6. Se mantienen casi intactas, las peculiaridades del tipo definido.

    TAD en C

    Las características del lenguaje C que va a permitir la implementación de un TAD son principalmente, las estructuras o registros para representación de los datos , y las funciones para representar las operaciones especificadas. Además en un archivo de inclusión o cabecera se guarda la representación de los datos y el interfaz, prototipos de funciones, etc.

    Ejemplo:

    Se desea especificar el un TAD que manipule números complejos (los números cmplejos están compuestos por una parte real y otra imaginaria a+bi)

    .tupedef struct

    {

    float a;

    int b;

    }complejo;

    La anterior declaración puede hacerse en un archvo .h, y en programa principal, debe espécificarse esa inclusión de la siguiente manera:

    #include "nuevotad.h"

    y con ello, ya podemos hacer uso de nuestro TAD, haciendo declaraciones como la siguiente:

    complejo p1;

    Código

    /*archivo camplejo.h*/

    typedef struct

    {

    float a;

    int b;

    }complejo;

    /*archivo complejo.c*/

    #include <stdio.h>

    #include <conio.h>

    #include "complejo.h"

    main()

    {

    complejo p, q,r;

    clrscr();

    p.a=5.6;

    q.a=6.5;

    p.b=3;

    q.b=8;

    r.a=p.a+q.a;

    r.b=p.b+q.b;

    printf("El n£emero complejo es %.1f + %di\n", r.a, r.b);

    getch();

    return 0;

    }

    Explicación

    El lector debe comprender la importanci, de lo que acabamos de hacer, y es que con la declaración anterior, en cualquier otro de nuestros programas deseamos usar el tipo de dato, complejo, lo único que debemos hacer es incluir la cabecera complejo. H¸que definimos en un archivo .h, algunos escritores, indican que en este tipo de archivos (.h), podemos declarar las funciones que vamos a usar en nuetro programa, lo cual, no está errado, sino que; personalmente considero que, para mantener de una manera fidedigna, el concepto de TAD, debemos únicamente declararlo en el archivo *.h.

    También hay que apuntar que la cabecvera complejo.h, se distingue de las demás por que va entre comillas ("") y no entre signos (<>), y es que, si una cabecera va entre signos mayor y menor que, le estamos indicando al compilador que lo busque en la carpeta de los includes (por lo menos para turbo C), pero si va entre comillas(""), es como decirle al compilador que busque el archivo *.h en la misma carpeta en la que está guardado el archivo *.c que estamos compilando.

    Lo siguiente de lo que hablaremos es, en sencia, la médula central de ésta segunda parte del curso, por tanto, si para el lector, no han quedado claros algunos conceptos de punteros, estructuras, etc; le recomiendo que vuelva a leer los capítulos correspondientes, ya que de lo contrario, le será un poco difícil la comprensión de lo que sigue, puesto que, continuamos con: La Gestión de Memoria Dinámica.

    Para ello, iniciremos hablando de una estrictura muy importante como lo son las:

    Pilas y sus Aplicaciones

    Una pila es un tipo especial de estructura de datos en la que sólo se pueden insertar y eliminar nodos en uno de los extremos de la lista. Estas operaciones se conocen como "push" y "pop", respectivamente "empujar" y "tirar". Además, las escrituras de datos siempre son inserciones de nodos, y las lecturas siempre eliminan el nodo leído.

    Estas características implican un comportamiento de lista LIFO (Last In First Out), el último en entrar es el primero en salir.

    El símil del que deriva el nombre de la estructura es una pila de platos. Sólo es posible añadir platos en la parte superior de la pila, y sólo pueden tomarse del mismo extremo. También una rimera de libros, en la que no se puede acceder a un determinado libro, sino se mueven primero los libros que están encima de él.

    Las pilas se pueden implementar de dos formas:

    ->Como Arreglos

    ->Usando Memoria Dinámica.

    Operaciones con Pilas

    push-> Se utiliza para introducir elementos, ésta función necesita como argumento a la pila y el elemento a introducir.

    pop-> se utiliza para sacar elementos de la pila, Como argumentos, necesita, unicamente a la pila.

    Hemos llenado nuestra pila, llamada "s", con los valores que le insicamos en la función push.

    Ahora si queremos sacar el elemento del tope, basta indicar con la siguiente sentencia:

    Pop(s);

    Pop(s);

    Y la pila quedaría:

    Se debe tener en cuenta que, dentro de las funciones pop y push, puden estar otras funciones inmersas, por ejemplo, si queremos introducir más datos, debemos tener otra función que verifique si la pila, no está llena. Por el contrario si queremos sacar datos, debemos sersiorarnos que la pila no esté vacía, es ahí donde nacen estas otras funciones que deben estar presentes en nuestros programas:

    ->empty, que verifica si la pila está vacía

    ->stacktop->retorna el elemento superior de la pila.

    Representación de Pilas usando arreglos

    Para ésta abstracción consideraremos que nuestra pila, está compuesta por un arreglo de n elementos y una variable que controla el subíndice de la cima de la pila.

    De declaración puede ser la siguiente:

    Typedef struct {

    char elementos[100];

    int top;

    }Pila;

    donde Pila, es el nombre de nuestra estructura.

    Elementos, es el arreglo que contendrá 100 caracteres

    Y top, es la variable, que será inicializada a –1, y que aumentará (o disminuirá) a medida que se agreguen (o eliminen) datos.

    Por ejemplo:

    s.top=-1; /*inicializamos la pila*/

    push(&s, x);

    s.top++; /*ahora top vale 0*/

    push (&s, y);

    s.top++; /*top vale 1*/

    push(&s, k);

    s.top++; /*ahora top vale 2*/

    pop(&s);

    s.top-- /*s.top=1*/

    claro que éste aumento (o decremento) debe hacerse dentro de la función push (o pop), según corresponda.

    Muchas veces un programa puede llevar otras funciones, pero digamos que eso ya es valor agregado por parte del programador, las funciones más importantes son pop y push, y son esas las que vamos a describir a continuación:

    Algoritmo de la función push (para arreglos)

    1. Verificar si la pila no está llena
    2. incrementar en 1 el puntero índice de la pila
    3. almacenar el elemento en la posición del puntero de la pila

    Algoritomo de la función pop (para arreglos)

    1. si la pila está vacía imprimir un mensaje
    2. sino está vacía, leer el elemento de la posición del puntero de la pila
    3. decrementar en uno el puntero de la pila.

    Ejemplo 10.2

    Se desea guardar un aproximado de 100 números enteros en una estructura tipo pila, la cual permita añadir elementos, sacar los elemtos e imprimir los datos contenidos en la pila.

    /*pila en forma de arreglo*/

    #include <stdio.h>

    #include <conio.h>

    /*declaracion de la pila*/

    typedef struct{

    int datos[100];

    int top;

    }Pila;

    /*declaracion de las funciones*/

    void push(Pila *ps, int x); /*Introduce un elemento a la pila*/

    int top (Pila *ps); /*elimina y muestra un elemento de la pila*/

    int empty (Pila *ps);

    /*Programa Pincipal*/

    main()

    {

    Pila pila; /*definicion de la variable pila*/

    int x, opc=5, i, k=0;

    pila.top=-1;

    clrscr();

    while(opc!=4)

    {

    printf("\t\t\t MENU PRINCIPAL\n\n\n");

    printf("\t1. Introducir datos\n");

    printf("\t2. Sacar datos\n");

    printf("\t3.Imprimir la pila\n");

    printf("\t4.Salir\n");

    scanf("%d", &opc);

    switch(opc)

    {

    case 1: if(pila.top==99)

    printf("ERROR, pila llena\a\n");

    else

    {

    printf("Ingrese el dato\n");

    scanf("%d", &x);

    push(&pila, x);

    k++;

    }

    break;

    case 2: printf("El elemento sacado es %d\n\n", pop(&pila));

    k--;

    getch();

    break;

    case 3: if(pila.top>=0)

    {

    printf("Los elementos de la pila son:\n");

    for(i=0; i<k; i++)

    printf("%d->", pila.datos[i]);

    getch();

    }

    else

    printf("No hay datos en la pila\a\n");

    break;

    }

    clrscr();

    }

    printf("Fin del programa\n\n");

    getch();

    return 0;

    }

    /*funcin que agregaun dato a la pila*/

    void push (Pila *ps, int x)

    {

    ps->datos[++(ps->top)]=x;

    }

    /*funcin que elimina y devuelve un elemento de la pila*/

    int pop(Pila *ps)

    {

    int r=NULL;

    if(empty(ps)==1)

    printf("No hay elementos para sacar\a\n");

    else

    r=ps->datos[(ps->top)--];

    return r;

    }

    /*funcion que verifica si la pila esta vac¡a*/

    int empty (Pila *ps)

    {

    int r;

    if(ps->top==-1)

    r=1;

    else

    r=0;

    return r;

    }

    Explicación

    El programa enterio, muestra, en forma sencilla, el uso de las pilas, en forma estática, (usando arreglos), con funciones muy sencillas como pop, push y empty, pero el lector debe recordar que él puede modificar, crear otras funciones (o estas mismas) según sea el problema que se esté resolviendo. Para el caso, en este ejemplo, he usado sintaxis como la siguiente:

    r=ps->datos[(ps->top)--];

    lo cual, podría haberse hecho en más pasos, de la siguiente forma:

    i=ps->top--;

    r=ps->datos[i];

    y así sucesivamente, por tanto se debe encasillar a que la sintaxis anterior es la única solución viable a éste problema. Las instrucciones pueden cambiar, pero lo que debe permanecer siempre invariable, es el algoritmo correspondiente a las funciones anteriores (pop y push).

    También el lector se preguntará, el por que hemos usado una variable auxiliar, identificada como k. Pues bien la respuesta es muy simple, esta variable sirve para controlar el número de impresiones que se harán en la función pertinente es por ello que esa variable crece (en la función push) y decrece (en la función pop).

    Pilas Implementadas con Memoria Dinámica

    Las pilas, que hasta ahora hemos tratado, han sido usando únicamente memoria estática, es decir definimos ciertos espacios, dentro de los cuales guardamos nuestros datos. Pero, que pasaría, si los datos superan el espacio reservado en memoria para ellos?.

    Es aquí donde surge, la importancia que la pila crezca y decrezca dinámicamente, donde el único límite existente es la memoria misma de la pc.

    La forma de declararlo es la siguiente:

    typedef struct _nodo {

    int dato;

    struct _nodo *siguiente;

    } tipoNodo;

    typedef tipoNodo *pNodo;

    typedef tipoNodo *Pila;

     

    tipoNodo es el tipo para declarar nodos, evidentemente.

    pNodo es el tipo para declarar punteros a un nodo.

    Pila es el tipo para declarar pilas.

    Así que sigue siendo muy importante que nuestro programa nunca pierda el valor del puntero al primer elemento, igual que pasa con las listas abiertas.

    Teniendo en cuenta que las inserciones y borrados en una pila se hacen siempre en un extremo, lo que consideramos como el primer elemento de la lista es en realidad el último elemento de la pila.

    Las operaciones básicas siguen siendo las mismas, aunque claro con sus respectivas variantes:

    -push, para igresar nuevos valores en la pila

    -pop, para eliminar lementos de la pila

    Función push (para memoria dinámica)

    1. Supondremos que ya se creó un nodo nuevo (hablaremos de eso después), si la pila está vacía, es decir el puntero que apunta a la pila, está apuntando a NULL.
    2. lo que debemos hacer es que, nodo en su parte de siguiente, apunte a NULL
    3. Y el puntero que apunta a la pila, apunte ahora al nuevo nodo.

    Un nodo, está compuesto del dato (que puede ser entero, real, carácter u otra estructura) y un puntero, que enlazará éste nodo con el siguiente.

    El puntero Pila, apunta a la cima de la pila, cuando no hay datos está inicializada a NULL.

    Si la pila, no está vacía (es decir hay elementos):

    creamos un nuevo nodopara el valor que colocaremos en la pila

    1. hacemos que nodo, en su parte de siguiente, apunte a pila
    2. hacemos que pila, apunte a nodo.

    Función Pop

    Partiremos del supuesto que exiten más de un nodo en la pila, el algoritmo, sería el siguiente:

    1. Hacemos que nodo, apunte al primer elemento de la pila
    2. asignamos a pilala dirección del segundo elemento de la pila
    3. guardamos el contenido del nodo para devolverlo posteriormente
    4. liberamos la memoria del nodo que queremos eliminar.

    (NOTA: las imágenes anteriores han sido tomadas de http://www.conclase.net/c/edd/index.php?cap=002b).

    Si por ejemplo, tenemos sólo un nodo, el proceso serí parecido, sólo que pila, apuntaría ahora a nodo->siguiente, que sería NULL.

    Función push

    void push(Pila *pila, int v)

    {

    pNodo *nuevo;

    nuevo=(pNodo)malloc(sizeof(tiponodo));

    nuevo->valor=v;

    nuevo->siguiente=*pila;

    *pila=nuevo;

    }

    en la función anterior, observamos que, no devuelve ningún valor, que recibe como argumentos, la dirección de la pila y el valor (entero, en éste caso) que vamos a guardar en la pila.

    Posteriomente, declara un nuevo puntero que tendrá la dirección del nodo que vamos a crear.

    nuevo=(pNodo)malloc(sizeof(tiponodo))

    quizá, la línea anterior es una de las más potentes e interesantes que podemos encontrar y es que con esa línea le estamos diciendo al compilador que vamos a crear un nuevo nodo, del tamaño de tiponodo, para ello usamos la instrucción malloc, que sive para pedirle al sistema memoria, sizeof, lo que hace es determinar el tamaño (en bytes), de la variable que le pasamos como argumento y ese valor, es lo que malloc le pide al sistema, y como éste devuelve un puntero del tipo void, por eso es necesario hacer el casting: (pNodo)malloc.

    Función Pop:

    int pop (Pila *pila)

    {

    pNodo nuevo;

    int v;

    nodo=*pila;

    if(!nodo)

    *pila=nodo->siguiente;

    v=nodo->valor;

    free(nodo);

    return (v);

    }

     

    Note que ésta función lo único que recibe es el puntero a la pila. La función free(), sirve para liberar ese espacio de memoria.

    Ejemplo 10.3

    Código completo para el uso de las pilas

    #include <stdio.h>

    #include <conio.h>

    typedef struct nodo{

    int valor;

    struct nodo *siguiente;

    }tiponodo;

    typedef tiponodo *pNodo;

    typedef tiponodo *Pila;

    void push(Pila *pila, int v);

    int pop(Pila *pila);

    main()

    {

    Pila pila=NULL;

    push(&pila, 20);

    push(&pila, 30);

    push(&pila, 40);

    printf("%d", pop(&pila));

    printf"%d", pop(&pila));

    getch();

    return 0;

    }

    void push(Pila *pila, int v)

    {

    pNodo *nuevo;

    nuevo=(pNodo)malloc(sizeof(tiponodo));

    nuevo->valor=v;

    nuevo->siguiente=*pila;

    *pila=nuevo;

    }

    int pop (Pila *pila)

    {

    pNodo nuevo;

    int v;

    nodo=*pila;

    if(!nodo)

    *pila=nodo->siguiente;

    v=nodo->valor;

    free(nodo);

    return (v);

    }

    Explicación.

    La salida, de éste programa no es muy atractiva, pero hagamos un esfuerzo por comprenser que es lo que hemos hecho.

    Y aunque lo que veamos en pantalla, son sólo unos números, que a lo mejor al principio, no tengamos ni idea de donde aparecieron, (igual que yo, la primera vez), debemos estar seguros que éste programita cumple con todas las especificaciones de una pila.

    Por ejemplo, las invocaciones de push, mandamos a la pila, los valores de 20, 30, 40. de los cuales el número 40, es el que se encuentra en la cima de la pila, por eso, al llamar a pop, manda a impresión el número 40. ahora quien está en la cima es 30, y al volver a invocar a pop, es ese valor el que se imprime. El lector puede modificar este programa colocando otros valores en push, agregando más llamadas a pop, etc.

    A pesar que el programa anterior es muy apropiado para exponer el funcionamiento de las pilas, hasta cierto punto, está incompleto, ya que no interactúa mucho que digamos con el usuario.

    Por ello mostramos a continucación otro código que es un poco más completo.

    En el cual no pasamos parámetros a las funciones, por que las variables son de tipo global, éste es un método, para hacer las cosas un poco más fáciles.

    Ejemplo 10.4

    Se desean guadar en una pila, cierta cantidad de nombres, a la vez que el usuario puede eliminar e imprimir el estado de la pila, según lo desee. Diseñe un programa en C, que de soporte a dicho problema, usando pilas implementadas con memoria dinámica.

    /* Ejemplo de una pila. */

    #include <stdio.h>

    #include <conio.h>

    #include <stdlib.h>

    #include <alloc.h>

    void push(void);

    void pop(void);

    void visualizar(void);

    struct pila

    {

    char nombre[20];

    struct pila *ant;

    }*CAB=NULL,*AUX=NULL;

    main( )/* Rellenar, extraer y visualizar */

    {

    char opc=8;

    while(opc!=4)

    {

    clrscr( ); /* borramos la pantalla */

    printf("\t\t1.- Insertar\n");

    printf("\t\t2.- Extraer\n");

    printf("\t\t3.- Visualizar la pila\n");

    printf("\t\t4.- Salir\n\n");

    opc=getch( );

    switch(opc)

    {

    case '1':

    push( );

    break;

    case '2':

    pop( );

    break;

    case '3':

    visualizar( );

    }

    }

    getch();

    }

    void push(void)

    {

    AUX=(struct pila *)malloc(sizeof(struct pila));

    clrscr( );

    printf("Nombre: ");

    gets(AUX->nombre);

    if (CAB==NULL)

    {

    CAB=AUX;

    AUX->ant=NULL;

    }

    else

    {

    AUX->ant=CAB;

    CAB=AUX;

    }

    }

    void pop(void)

    {

    if (CAB==NULL) return;

    AUX=CAB;

    CAB=CAB->ant;

    free(AUX);

    }

    void visualizar(void)

    {

    if (CAB==NULL) return;

    clrscr( );

    AUX=CAB;

    while (AUX!=NULL)

    {

    printf("Nombre: %s\n",AUX->nombre);

    AUX=AUX->ant;

    }

    getch( );

    }

    Explicación

    Éste ejemplo es un poco más completo, ya que le permite al usuario, interactuar, al poder ingresar los datos cómo él los desee, además que, note, que en las funciones (push, pop e insertar) no mandamos parámetros. Ya que éstos son declarados fuera del main(), por tanto se pueden acceder a ellas, por cualquier función dentro del programa. Lo cual puede ser muy útil, cuando estamos trabajando, por ejemplo, con cadenas de caracteres, como en éste caso.

    Evaluciones de Expresiones

    Las expresiones aritméticas que hasta ahora hemos usado, las encontramos en forma infija, es decir usando (), *,/,-,+...

    Ejemplo:

    X=z+(b+c)^(q-m)-(b*c)

    A la expresión anterior también algunos autores la llaman, interfija. Sin embargo las expresiones tienen otras formas de poderlas representar, por ejemplo: la notación posfija o también conocida como polaca inversa (en honor al matemático de origen polaco, que la propuso), y ésta consiste en colocar el operador a continuación de los operandos. Por ejemplo:

    A*b/(c-d) /*infija*/

    A*b/c-d /*quitamos paréntesis*/

    Ab*/cd-/*signo delante de operador*/

    Ab*cd-/ /*posfija*/

    Otro ejemplo:

    A+(B*C)

    A+B*C

    A+BC*

    ABC*+

    Ahora bien, lo anterior podría parecer bastante complejo, y ciertamente lo es, por lo cuala continuación mostramos el algoritmo para pasar una expresión de infija a posfija:

    1. leer la cadena de caracteres, y repetir el paso 2 al 4 por cada carácter
    2. si es un operando, pasarlo a expresión posfija
    3. si es un operador:
      1. si la pila está vacía, meterlo en la pila. Repetir desde 1
      2. si la pila no está vacía:

      -si la prioridad del operador leído es mayor que la prioridad del operador cima de la pila, meterlo en la pila y repetir dede 1

      -si la prioridad del operador es menor o igual que la prioridad del operador de la cima de la pila, sacar operador cima de la pila y pasarlo a la expresión posfija, volver a 3

    4. si es paréntesis derecho:
      1. sacar operador cima de la pila y pasarlo a la expresión posfija
      2. si nueva cima es paréntesis izquierdo suprimir elemento cima
      3. si cima no es paréntesis izquierdo, volver a 4.1
      4. volver a partir de 1

    5. si quedan elementos en la pila pasarlos a la expresión posfija
    6. fin del algoritmo

    (Algoritmo tomado de: "Algoritmos y estructuras de datos, una perspectiva en C". Joyanes Aguilar, Luis. Madris 2004. Pág. 329)

    el código sería el siguiente:

    Ejemplo 10.5

    #include<stdio.h>

    #include<string.h>

    #define n 60

    /* *********** Prototipo de funciones de pila **************** */

    void push(struct pila *p, struct operador num);//meter datos a la pila

    int full(struct pila *p); //devuelve 1 si la pila esta llena

    void clear(struct pila *p); //limpia la pila

    struct operador pop(struct pila *p); //elimina el dato de la cima y lo devuelve

    struct operador ver(struct pila *p); //devuelve el dato de la cima sin eliminarlo

    int empty(struct pila *p); //devuelve 1 si la pila esta vacia

    void tranformacion( char expin[n], char *expos,struct pila *p); //transforma de infija a posfija

    int infija(char expin[n]); //devuelve 1 si la expresion infija es valida

    struct operador asignacion(char i); //devuelve la prioridad de los operadores

    void marco(); //funcion adicional para el marco

    void error(); /*describe las posibles causas de error en la introduccion

    de la expresion infija*/

    /* ***************** Declaracion de la pila ***************** */

    struct operador{

    int prioridad;

    char caracter;

    } ;

    struct pila{

    int tope;

    struct operador vect[n];

    } ;

    /* ********************** Programa Principal************************* */

    void main(void)

    {

    char expin[n],expos[n];/* expin contiene la expresion infija

    expos contiene la expresion posfija */

    int s;

    struct pila pila1; //creacion de la pila

    clrscr();

    clear(&pila1); //inicializacion de la pila

    marco();

    printf("Introduzca una expresion en notacion infija \n");

    scanf("%s",expin); //introduccion de la expresion infija

    clrscr();

    tranformacion( expin,expos,&pila1);

    getch();

    clrscr();

    marco();

    printf("-.Si desea introducir otra expresion presione 1\n");

    printf("-.Otro numero para salir.\n");

    scanf("%i",&s);

    if(s==1)

    main();

    }

    /* *****funciones de ordenamiento de expresion infija a postfija ******** */

    void tranformacion( char expin[n], char expos[n], struct pila *p)

    {

    struct operador auxiliar; /* auxiliar se utiliza para introducir operadores

    a la pila*/

    struct operador comparador;/* comparador se utiliza para contener el valor

    de la cima de la pila */

    int i,j,bandera; /* i y j son variables de cambio , bandera permite

    sacar los operadores de apertura de la pila y

    operadores de menor prioridad al que se introducira*/

    if( infija(expin)== 1) //1.si expresion infija es valida

    {

    for(i=0,j=-1 ;i<=(strlen(expin)-1);i++)//1.evaluacion caracter por caracter

    {

    // 2. si es caracter lo copiara en la expresion posfija

    if (((expin[i]>=65 )&&(expin[i]<=90)) || ((expin[i]>=97 )&&

    (expin[i]<=122)))

    {

    j+=1;

    expos[j]=expin[i];

    }//cierra 2

    else

    { //3 . si es operador de cierre derecho

    if( (expin[i]=='}' )||(expin[i]==']' )||(expin[i]==')' ))

    {

    bandera=1;

    do{

    auxiliar=pop(p); //quite la cima de la pila

    j+=1;

    expos[j]=auxiliar.caracter;/* agregar el operador quitado

    a la expresion posfija */

    comparador=ver(p); //comparador contiene lo que hay en la cima

    if(comparador.prioridad==0)//si la cima de la pila es operador de apertura

    {

    auxiliar=pop(p); //quitar operador de apertura

    bandera=1;

    }

    else

    bandera=0; //si cima de la pila es operador regrese a 3

    }while(bandera==0);

    } //cierra 3

    else // 4 si es operador de apertura o +,/,*,-,^

    {

    bandera=1;

    do{

    auxiliar=asignacion(expin[i]); //asignacion prioridad a operadores

    if (empty(p)==1) // si la pila esta vacia operador entra a la pila

    {

    if(auxiliar.prioridad==6)// si es operador de apretura

    auxiliar.prioridad=0; // en la pila su prioridad es 0

    push(p,auxiliar);

    bandera=1;

    }

    else{ // comparando prioridad de operadores del tope y el entrante

    comparador=ver(p);

    //comparador tiene el valor de la cima

    if(auxiliar.prioridad > comparador.prioridad)

    { if(auxiliar.prioridad==6) //si es operador de apertura

    auxiliar.prioridad=0; //en la pila su prioridad es 0

    push(p,auxiliar);

    bandera=1;

    }

    else

    { //si operado entrante es menor o igula que el de la pila

    auxiliar=pop(p);//sacar operandor de la cima de la pila 4

    j+=1;

    expos[j]=auxiliar.caracter; //agregarlo a expresion posfija

    bandera=0; //volver a evaluar evaluar operador entrante regreso a

    }

    }

    }while(bandera==0);

    }//cierra 4

    }

    }//cierra 1

    while(empty(p)!=1)//sacar todos los operadores sobrantes en pila

    {

    auxiliar=pop(p);

    j+=1;

    expos[j]=auxiliar.caracter;

    }

    //impresion de resultado

    marco();

    printf("\n\nLA EXPRESION EN NOTACION INFIJA ES :\n ");

    printf("%s",expin);

    printf("\n\nLA EXPRESION EN NOTACION POSFIJA ES :\n");

    for(i=0;i<=j;i++) {

    printf("%c",expos[i]);}

    } //cierre de expresion infija valida

    else{ //expresion infija no valida

    marco();

    printf("\n\n\aLA EXPRESION INFIJA ES ERRONEA:");

    error();

    }

    }//cierra funcion transformacion

    //funcion que asigna la prioridad de los operadores

    struct operador asignacion(char i)

    {

    struct operador auxiliar;

    switch(i){ //asignacion de prioridades

    case '^': auxiliar.prioridad=5;

    auxiliar.caracter='^';

    break;

    case '*': auxiliar.prioridad=4;

    auxiliar.caracter='*';

    break;

    case '/': auxiliar.prioridad=3 ;

    auxiliar.caracter='/';

    break;

    case '+': auxiliar.prioridad=2 ;

    auxiliar.caracter='+';

    break;

    case '-': auxiliar.prioridad=1 ;

    auxiliar.caracter='-';

    break;

    case '(': auxiliar.prioridad=6;

    auxiliar.caracter='(';

    break;

    case '[': auxiliar.prioridad=6 ;

    auxiliar.caracter='[';

    break;

    case '{': auxiliar.prioridad=6 ;

    auxiliar.caracter='{';

    break; }

    return auxiliar;

    }

    /* ************ funcion de validacion de la expresion *********************/

    int infija (char expin[n])

    {

    int i,numero[3],parentesis,bandera=1;

    //evaluacion: operando operador operando

    for(i=1;i<=(strlen(expin)-2);i++)

    {

    if((expin[i]=='+')||(expin[i]=='-')||(expin[i]=='*')||

    (expin[i]=='/')||(expin[i]=='^'))

    {

    if(!(((expin[i+1]>=65 )&&(expin[i+1]<=91)) || ((expin[i+1]>=97 )&&

    (expin[i+1]<=123)) ||(expin[i+1]==40) || (expin[i+1]==41 )||

    (expin[i+1]==93) || (expin[i+1]==125 ) ))

    bandera=0;

    if(!(((expin[i-1]>=65 )&&(expin[i-1]<=91)) || ((expin[i-1]>=97 )&&

    (expin[i-1]<=123)) ||(expin[i-1]==40) || (expin[i-1]==41 )||

    (expin[i-1]==93) || (expin[i-1]==125 ) ))

    bandera=0;

    };

    }

    //evaluacion:no deben haberdos operandos juntos

    for(i=0;i<=(strlen(expin)-2);i++)

    {

    if (((expin[i]>=65 )&&(expin[i]<=90)) || ((expin[i]>=97 )&&

    (expin[i]<=122)))

    {

    if (((expin[i+1]>=65 )&&(expin[i+1]<=91)) || ((expin[i+1]>=97 )&&

    (expin[i+1]<=123)) || (expin[i+1]==40 ))

    bandera=0;

    if (((expin[i-1]>=65 )&&(expin[i-1]<=90)) || ((expin[i-1]>=97 )&&

    (expin[i-1]<=122)) || (expin[i-1]==41 )||

    (expin[i-1]==93) || (expin[i-1]==125 ))

    bandera=0;

    }

    }

    // evaluacion: la expresion no comience con operador

    if((expin[0]=='+')||(expin[0]=='-')||(expin[0]=='*')||(expin[0]=='/')||

    (expin[0]=='^'))

    bandera=0;

    // evaluacion: la expresion no termine con operador

    if((expin[strlen(expin)-1]=='+')||(expin[strlen(expin)-1]=='-')||

    (expin[strlen(expin)-1]=='*')||(expin[strlen(expin)-1]=='/')||

    (expin[strlen(expin)-1]=='^'))

    bandera=0;

    //evaluacion: despues de un simbolo de apertura no debe haber operador

    for(i=0;i<=(strlen(expin)-2);i++)

    {

    if((expin[i]=='(')||(expin[i]=='{')||(expin[i]=='['))

    if ((expin[i+1]=='+')||(expin[i+1]=='-')||(expin[i+1]=='*')||

    (expin[i+1]=='/')||(expin[i]=='^'))

    bandera=0;

    };

    //evaluacion: antes de un simbolo de cierre no debe haber operador

    for(i=1;i<=(strlen(expin)-1);i++)

    {

    if((expin[i]==')')||(expin[i]=='}')||(expin[i]==']'))

    if ((expin[i-1]=='+')||(expin[i-1]=='-')||(expin[i-1]=='*')||

    (expin[i-1]=='/')||(expin[i-1]=='^'))

    bandera=0;

    }

    //evaluacion de los parentesis

    parentesis=0; //suma final=0, evita (}, (],[}

    for(i=0;i<=2;i++)

    numero[i]=0; // evita {) ,{],[)

    for(i=0;i<=(strlen(expin)-1);i++)

    {

    switch(expin[i])

    {

    case '(':parentesis+=1;

    numero[0]+=1;

    break;

    case '[':parentesis+=2;

    numero[1]+= 2;

    break;

    case '{':parentesis+=3;

    numero[2]+=3;

    break;

    case ')':parentesis-=1;

    numero[0]-=1;

    if(parentesis<0) bandera=0;

    break;

    case ']':parentesis-=2;

    numero[1]-=2;

    if(parentesis<0) bandera=0;

    break;

    case '}':parentesis-=3;

    numero[2]-=3;

    if(parentesis<0) bandera=0;

    break;

    }

    }

    if(parentesis!=0) // si la suma de los parentesis es <> 0 existe error

    bandera=0;

    for(i=0;i<=2;i++) // debe haber un numero igual operadores

    {if(numero[i]!=0) // de cierre y apetura por cada tipo

    bandera=0;}

    return bandera;

    }//terminacion de función validación expresión

    /* ************************* funciones de la pila ******************* */

    int full (struct pila *p) //funcion full devuelve 1 si la pila esta llena

    {

    if (p->tope==4)

    return 1;

    else

    return 0;

    }

    void push(struct pila *p,struct operador num)//funcion push encargada de

    { //introducir datos a la pila

    if(full(p)==1)

    printf("pila llena");

    else

    {

    p->tope++,

    p->vect[(p->tope)]=num;

    }

    }

    void clear(struct pila *p)//funcion clear encargada de limpia la pila

    {

    p->tope=-1;

    }

    int empty(struct pila *p)// funcion empty devulve 1 si la pila esta vacia

    {

    if (p->tope==-1)

    return 1;

    else

    return 0;

    }

    struct operador pop(struct pila *p) //funcion pop quita el dato que

    { //se encuntre en la cima de la pila

    struct operador auxiliar;

    if (empty(p)==1)

    {

    auxiliar.caracter='0';

    }

    else

    {

    auxiliar= p->vect[p->tope];

    p->tope--;

    };

    return auxiliar;

    };

    struct operador ver(struct pila *p) // funcion ver devuelve el dato

    { // que esta en la cima de la pila

    struct operador auxiliar; // sin removerlo

    auxiliar= p->vect[p->tope];

    return auxiliar;

    };

    /* ***************** funcione adicional ******************** */

    void marco()

    {

    int i;

    for (i=1;i<=79;i++)

    {

    printf("*");

    printf("*");

    }

    printf("\nPROGRAMA QUE CALCULA UNA EXPRESION EN NOTACION POSFIJA\n\n\n");

    }

    void error()

    {

    printf("Posibles razones:\n");

    printf("1-hay dos operadores juntos\n");

    printf("2-hay dos operandos juntos\n");

    printf("3-la expresion comienza con operador\n");

    printf("4-la expresion termina con operador\n");

    printf("5-hay un operador luego de ( ,[ o{ \n");

    printf("6-hay un operador antes de ),] o }\n");

    printf("7-Existe un error en los parentesis\n");

    }

    NOTA: el código anterior fue elaborado por : Nelson Eduardo Najarro Alvarez, para la Asignatura de Programación II, de la Carrera de Ingeniería de Sistemas Informáticos de la Universidad de El Salvador.

    El ejemplo anterior es baste complejo y muy largo, pero decidí colocarlo, por que en muchos libros sólo colocan las funciones o trozos del código, pero como aquí queremos hacer las cosas bien, hemos decidido colocar el código completo.

    Además que en muchas universidades o colegios, dejan como tarea éste código, así creo que te servirá mucho.

    Cuestionario

      1. ¿Qué es un TAD?_____________________________________________________________________________________________________________________________________________
      2. ¿Cuál es la importancia del TAD?___________________________________________________________________________________________
      3. ¿Para que se usan las pilas?__________________________________________________________________________________________________________________________________________
      4. ¿Cómo funcionan las pilas?__________________________________________________________________________________________________________________________________________
      5. Mencione y explique las implementaciones de Pilas en C:______________________________________________________________________________________________

    En las siguientes funciones, descubre donde hay errores, identifícalos y corrígelos.

    1. void push ( ptrNodoPila *ptrCima, int info )

    {

    ptrNodoPila ptrNuevo; /* apuntador al nuevo nodo */

    ptrNuevo = malloc( sizeof( NodoPila ) );

    /* inserta el nodo en la cima de la pila */

    if ( ptrNuevo != NULL ) {

    ptrNuevo->dato = dato;

    ptrNuevo->ptrSiguiente = *ptrCima;

    *ptrCima = ptrNodoPila;

    } /* fin de if */

    else { /* no queda espacio disponible */

    printf( "%d no se inserto. Memoria insuficiente.\n", info );

    } /* fin de else */

    } /* fin de la función empujar */

    2. /* Elimina un nodo de la cima de la pila */

    int pop( ptrNodoPila *ptrCima )

    {

    ptrNodoPila ptrTemp; /* apuntador a un nodo temporal */

    ptrTemp = *ptrCima;

    valorElim = ( *ptrCima )->dato;

    *ptrCima = ( *ptrCima )->ptrSiguiente;

    free( ptrCima);

    return valorElim;

    } /* fin de la función sacar */

    Ejercicios

    1. Un vector en física, puede representarse mediante sus componentes x, y, z; de la siguiente forma: V=2i + 4j –6k. Cuando una de las componente está ausente, simplemente no se escribe (o la podemos representar con un cero: V= 0i + 4j + 6k.) Cree un TAD que lea un vector y luego calcule:
    2. -Su magnitud (||V||=sqrt(a^2+b^2+c^2)). Donde a,b y son los coeficientes

      -Su vector unitario: U=a/||V|| + b/||V|| + c/||V||

    3. los números radicalesse componen de una base y un signo radical, diseñe un programa que sea capaz de implementar un TAD llamado radical y permita:
    4. -sumarlos, restarlos o dividirlos; según lo desee el usuario.

    5. Disñe un TAD que represente un tipo cadena (string), y que permita las siguientes operaciones: leer la cadena, imprimirla, copiarla, determinar el tamaño de la cadena y buscar un carácter específico en la cadena.
    6. se desea transformar un número base10, a binario; utilizando una pila, en la cual se guarden los residuos de las divisiones. A partir de las impresiones generadas por la pila, muestre el número binario equivalente.
    7. A partir de un párrafo ingresado por el usuario, diseñe un programa que, determine el número de consonantes y vocales que están presentes en dicho párrafo.
    8. Diseñe un programa que lea una cadena de caracteres y luego la imprima en forma inversa
    9. Se desea crear una pila en c, que lea cierta cantidad de números enteros y luego muestre:
    10. -La suma de todos los números y el producto de ellos, cuántos son mayores que cero.

    11. una palabra es polindromo si se lee igual por la derecha que por la izquierda, diseñe un programa que lea una palabra, luego imprim esa misma palabra al revés y con un mensaje indique si es o no palíndromo.
    12. En una tienda de repuestos llevan su control de inventarios, mediante el sistema UEPS (últimos en entrar, primeros en salir), el cual puede ser controlado mediante una estructura del tipo Pila; en ésta tiendo necesitan que se registren sus productos, los cuales tendrán los siguientes datos: código, descripción, precio unitario, fecha de ingreso (del sistema). Además de registrar las órdenes de salida y mostrar los siguientes reportes: ventas por fecha, ventas por producto (ingresando el código), cantidad de productos que exceden un precio determinado. El cual será ingresado por el usuario.


 Página anterior Volver al principio del trabajoPágina siguiente 
Monografias.com - Página no encontrada

Discúlpenos.

No hemos podido hallar la página que estaba buscando.
Sin embargo, quizás podamos ayudarlo. Pruebe lo siguiente:

Ir a la página de inicio de Monografias.com.
Ver nuevos trabajos agregados a Monografias.com recientemente.
Si es su primera visita a Monografias.com, consulte la ayuda.
Busque en todo Monografias.com:

Buscar: Avanzada

¿Por qué pudo haber ocurrido esto?

Es probable que Usted haya llegado a esta página a través de:

Un favorito (o bookmark) demasiado antiguo.
Un motor de búsqueda que tiene un listado desactualizado de nuestras páginas.
Una dirección posiblemente mal tecleada.
Un vínculo roto en nuestras páginas.

También es posible que el recurso que Ud. busca haya sido dado de baja por su autor.

¡Ayúdenos a mejorar! Si ha llegado a esta página a través de un vínculo roto
dentro de Monografias.com, por favor escríbanos a webmaster@monografias.com
detallando el problema, para que lo podamos solucionar a la brevedad.

El equipo de www.monografias.com



Nota al lector: es posible que esta página no contenga todos los componentes del trabajo original (pies de página, avanzadas formulas matemáticas, esquemas o tablas complejas, etc.). Recuerde que para ver el trabajo en su versión original completa, puede descargarlo desde el menú superior.


Todos los documentos disponibles en este sitio expresan los puntos de vista de sus respectivos autores y no de Monografias.com. El objetivo de Monografias.com es poner el conocimiento a disposición de toda su comunidad. Queda bajo la responsabilidad de cada lector el eventual uso que se le de a esta información. Asimismo, es obligatoria la cita del autor del contenido y de Monografias.com como fuentes de información.

Iniciar sesión

Ingrese el e-mail y contraseña con el que está registrado en Monografias.com

   
 

Regístrese gratis

¿Olvidó su contraseña?

Ayuda