Universidad de Costa Rica
Escuela de Ciencias de la
Computación e Informática
Profesor Adolfo Di Mare
CI-1303
II Semestre 1996
[<=] [home] [<>] [\/] [=>]
CI-1303 Estructuras de Datos y Análisis de Algoritmos

Tarea #3

Artículo comparando Tarea #1 vs Tarea #2

      El objetivo de esta tarea es enfrentarlo a un problema real, en el que usted deba aplicar sus conocimientos de Estructuras de Datos y Análisis de Algoritmos para resolver un problema específico, buscando lograr un implementación eficiente.

      Después de la Privatización Bancaria, el Banco de Costa Rica se ha visto en la necesidad de competir en todos los frentes para subsistir. Primero absorvió al Banco Nacional, que por ser mucho más grande no pudo adaptarse al cambio, y fue luego engullido por su hermano menor, el BCR.

      Ahora el BCR quiere brindar nuevos servicios a sus clientes a través de la plataforma Internet, y para comenzar la Gerencia ha escogido una aplicación muy simple. Lo que el Banco quiere es que sea posible consultar a través de Internet la base de datos de cheques extraviados, en la que están todos los cheques que los cuenta correntistas del banco han reportado como extraviados, robados, o que por alguna razón tienen una orden de no pago.

      El Banco cuenta con 500,000 (medio millón) de cuentas corrientes, pero sólo un pequeñísimo porcentaje de ellas (0.8%) reportan cheques extraviados. Pero lo que sí se sabe es que el 80% de los movimientos de cuenta corriente los hacen sólo el 20% de los cuenta correntistas. Además, lo usual es que cuando un cuenta correntista reporta un cheque extraviado lo siga haciendo con alguna frecuencia después, y como complemento quien nunca ha reportado la desaparción de un cheque tiene una probabilidad muy baja de hacerlo.

      Su trabajo tiene dos partes. Primero debe hacer un estudio teórico sobre las chequeras y los cheques desaparecidos, para estimar cuán grande es el problema. Con base en este estudio teórico, usted propondrá una organización de archivos que permita atender a través de Internet un mínimo de 10 consultas por minuto sobre cheques extraviados. Entre los parámetros de su modelo matemático incluya al menos el tamaño de la cartera (o número de cuentas corrientes), y el porcentaje cheques que son reportados como extraviados. Si lo desea, puede hacer un programa, tal vez en Excel, para mostrar su modelo.

      Eventualmente la idea es que el Sistema de Cheques Extraviados [SCX] corra en algún servidor Internet, por lo que sus programas deberán estar escritos en el lenguaje C (no en C++).

      En su análisis teórico proponga una estructura de datos eficiente para esta aplicación, en el contexto ya descrito. También incluya un análisis de tiempo de respuesta para una cartera de 50,000 cuentas corrientes, y de 5,000,000 (cinco millones).

      En la segunda parte de este trabajo usted implementará el esquema propuesto. Debe construir su programa de forma que corra tanto en la plataform Sun como en una máquina Linux. Use los compiladores de GNU para sus programs, peroa asegúrese de que sean portables entre las dos plataformas.

      Sus programas deben correr como un proceso accesible desde un Servidor Internet, lo que lo obliga a usar la interfaz CGI. Asegúrese de que más de un proceso pueda acceder a la base de datos, pues usted nunca sabrá de que parte de La Red viene el siguiente requerimiento: es posible hasta que haya varios Servidores Internet ofreciendo el mismo servicio de consulta de cheques extraviados.

      Para sus pruebas deberá crear programas que ejerciten al SCX, generando consultas a la base de datos de cheques. Use estos programas para cotegar los resultados teóricos que usted calculó en la primera parte del proyecto.

      Trabaje en grupos de dos personas. Haga un trabajo profesional. Si necesita ayuda sobre CGI consulte con Manuel Cerdas, a quien puede contactar por correo electrónico [mcerdas@chacal.ecci.ucr.ac.cr]. Llame al BCR si necesita información adicional. Comparta sus hallasgos con sus compañeros. Trataremos de que el mejor de los programas pueda ser implementado en el Servidor Internet del BCR.

!No le merme!

::::::::::
cheque.htm
::::::::::
<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML//EN">

<html>

<head>
<title>Verificacion de cheques</title>
</head>

<body>
<h1>Verificaci&oacute;n de cheques</h1>
<form action="http://servidor/cgi-bin/scriptverificador.cgi" method="POST">
<p>&nbsp;</p>
<p>N&uacute;mero del cheque: <input type=text size=12 maxlength=12 name="numCheque"></p>
<p>N&uacute;mero de cuenta: <input type=text size=12 maxlength=12 name="numCuenta"></p>
<p align=center><input type=submit name="Aceptar" value="Submit"> <input type=reset name="Limpiar" value="Reset"></p>
</form>
</body>

</html>
::::::::::
comments.c
::::::::::
/* Change this to point to the location where you want
        comments to be kept on your system! The file
        must be writable by the web server. */

#define COMMENT_FILE "/CHANGE/THIS/PATH/comments.txt"

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

/* Global variables */

/* This example can only process up to 100 input fields in
        a single form. Of course, we know that this form
        only has a handful. Change this #define if you
        need more, or use the cgic library, which has
        no such limitations. */

#define FIELDS_MAX 100

char *names[FIELDS_MAX];
char *values[FIELDS_MAX];

int fieldsTotal = 0;

/* Makes sure this request is a form submission */
int VerifyForm();

/* Parses the submitted form data, filling the names[] and values[]
        arrays with useful information */
void ParseForm();

/* Frees the memory associated with the form data. */

void FreeForm();

/* Copies src to dst, unescaping any special characters in the process.
        dst must be at least as large as src in order to ensure that
        there is enough space. */

void UnescapeString(char *dst, char *src);

int main(int argc, char *argv[])
{
        FILE *out;
        int i;
        int nameIndex = -1, emailIndex = -1, commentsIndex = -1;

        printf("Content-type: text/html\n\n");

        printf("<html>\n");
        printf("<head>\n");
        /* Make sure it's a POST-method form submission */
        if (!VerifyForm()) {
                printf("<title>Not a POST Form Submission</title>\n");
                printf("</head>\n");
                printf("<h1>Not a POST Form Submission</h1>\n");
                printf("This page should be accessed only by submitting\n");
                printf("a form using the POST method. Perhaps your\n");
                printf("browser does not support forms.\n");
                printf("</body></html>\n");
                return 0;
        }

        /* OK, it's a form submission, so parse it. */
        ParseForm();

        /* Use the information */

        /* Find the index of each field in the arrays */
        for (i = 0; (i < fieldsTotal); i++) {
                if (!strcmp(names[i], "name")) {
                        nameIndex = i;
                } else if (!strcmp(names[i], "email")) {
                        emailIndex = i;
                } else if (!strcmp(names[i], "comments")) {
                        commentsIndex = i;
                }
        }

        /* If any field is missing, complain! */
        if ((nameIndex == -1) || (emailIndex == -1) || (commentsIndex == -1)) {
                printf("<title>Please fill out all the fields</title>\n");
                printf("</head>\n");
                printf("<h1>Please fill out all the fields</h1>\n");
                printf("Please fill out the name, email address, AND\n");
                printf("comment fields. Back up to the previous page\n");
                printf("to try again.\n");
                printf("</body></html>\n");
                return 0;
        }

        /* OK, we have all the data. Write it to a file in which
                we collect comments from users. Open to append, of course. */

        out = fopen(COMMENT_FILE, "a");
        fprintf(out, "From: %s <%s>\n",
                values[nameIndex], values[emailIndex]);
        fprintf(out, "%s\n", values[commentsIndex]);


        printf("<title>Thank you, %s</title>\n", values[nameIndex]);
        printf("</head>\n");
        printf("<h1>Thank you, %s</h1>\n", values[nameIndex]);
        printf("Thank you for your comments.\n");
        printf("</body></html>\n");
        /* Free the memory we used */
        FreeForm();
        return 0;
}

int VerifyForm()
{
        char *contentType;
        char *requestMethod;
        int bad = 0;
        /* Check the content type of the data we've received */
        contentType = getenv("CONTENT_TYPE");
        if (strcmp(contentType, "application/x-www-form-urlencoded") != 0) {
                bad = 1;
        }

        /* And make sure the POST method was used */
        requestMethod = getenv("REQUEST_METHOD");
        if (strcmp(requestMethod, "POST") != 0) {
                bad = 1;
        }

        return !bad;
}

/* Parses the submitted form data, filling the names[] and values[]
        arrays with useful information */

void ParseForm()
{
        char *contentLength = getenv("CONTENT_LENGTH");
        /* The number of characters in the data */
        int length;
        /* The buffer into which we read the data */
        char *buffer;
        /* The current position in the buffer while we search for separators */
        char *p;
        /* Determine the length of the input */
        if (!contentLength) {
                length = 0;
        } else {
                length = atoi(contentLength);
        }
        /* Allocate a buffer to store the input in. Include space
                for one extra character to make the parsing loop simpler. */
        buffer = (char *) malloc(length + 1);
        if (!buffer) {
                /* Uh-oh */
                return;
        }
        /* Read all the data from standard input */
        if (fread(buffer, 1, length, stdin) != length) {
                /* Uh-oh */
                return;
        }
        p = buffer;
        while (length) {
                /* The beginning of the current name */
                char *name;
                /* The beginning of the current value */
                char *value;

                int found;

                /* Make sure we have room for more fields. */
                if (fieldsTotal == FIELDS_MAX) {
                        /* Uh-oh, can't accept any more */
                        return;
                }

                name = p;

                /* First, find an equal sign. */
                found = 0;
                while (length) {
                        if (*p == '=') {
                                /* End the name with a null character. */
                                *p = '\0';
                                p++;
                                found = 1;
                                break;
                        }
                        p++;
                        length--;
                }
                if (!found) {
                        /* A blank or truncated entry. Strange, but web
                                browsers are unpredictable; be tolerant. */
                        break;
                }
                value = p;
                /* Now, find an ampersand. */
                found = 0;
                while (length) {
                        if (*p == '&') {
                                /* End the value with a null character. */
                                *p = '\0';
                                p++;
                                found = 1;
                                break;
                        }
                        p++;
                        length--;
                }
                if (!found) {
                        /* Assume that this is the end of the last entry. */
                        *p = '\0';
                }

                /* Allocate space for the name and value in those
                        arrays, then call UnescapeString to unescape
                        and copy them. Be sure to allow space
                        for the final null character. */
                names[fieldsTotal] = (char *) malloc(strlen(name) + 1);
                if (!names[fieldsTotal]) {
                        /* Uh-oh, no memory. Return with what we do have. */
                        return;
                }
                values[fieldsTotal] = (char *) malloc(strlen(value) + 1);
                if (!values[fieldsTotal]) {
                        /* Uh-oh, no memory. Return with what we do have. */
                        free(names[fieldsTotal]);
                        return;
                }

                /* Copy the strings, un-escaping them in the process. */
                UnescapeString(names[fieldsTotal], name);
                UnescapeString(values[fieldsTotal], value);
                fieldsTotal++;
                /* Continue, finding more pairs. */
        }
        /* Free the buffer we used. */
        free(buffer);
}

void FreeForm()
{
        int i;
        for (i=0; (i < fieldsTotal); i++) {
                free(names[i]);
                free(values[i]);
        }
}

void UnescapeString(char *dst, char *src)
{
        /* Loop over the characters in the string until we
                encounter the null character at the end,
                which tests false. */
        while (*src) {
                char c;
                c = *src;
                /* Handle spaces escaped as + signs */
                if (c == '+') {
                        c = ' ';
                } else if (c == '%') {
                        /* Handle % escapes */
                        char hexdigits[3];
                        int ascii;
                        src++;
                        if (!*src) {
                                /* Digits missing! Ignore escape */
                                break;
                        }
                        hexdigits[0] = *src;
                        src++;
                        if (!*src) {
                                /* Digits missing! Ignore escape */
                                break;
                        }
                        hexdigits[1] = *src;
                        /* Add a terminating null... */
                        hexdigits[2] = '\0';
                        /* Now use the C standard library function sscanf()
                                to read the hex value */
                        sscanf(hexdigits, "%x", &ascii);
                        /* And convert it back to a character */
                        c = ascii;
                }
                *dst = c;
                src++;
                dst++;
        }
        *dst = '\0';
}

[mailto:] Adolfo Di Mare <adolfo@di-mare.com>.
Copyright © 1996
Derechos de autor reservados © 1996
[home] <> [/\]