martes, 4 de enero de 2011

Kernighan_Ritchie_1.24

1.24 Escriba un programa para revisar los errores de sintaxis rudimentarios de un programa en C, como paréntesis, llaves y corchetes no alineados. No olvide las comillas ni los apóstrofos, las secuencias de escape y los comentarios. (Este programa es difícil si se hace completamente general.)


     /* Este programa verifica que las entradas de  un programa  no contengan
    errores de sintaxis elementales, como verificar que las llaves,
    corchetes y parentesis se cierren correctamente
    */

    // Definicion de constantes simbolicas y encabezados

   # define OK 0
   # define ERROR -1
   # define FALSO 0
   # define VERDADERO 1
   # define LLENA 1
   # define PILAMAX 100
   # define ADENTRO 1
   # define AFUERA 0
   # include <stdio.h>

   int superior = -1;   // Un par de variables externas

   int pila[PILAMAX];

   empujar( int nuevo )

   // La funcion empujar tiene mete elementos en la pila

   {              // abre la funcion empujar


   if ( superior + 1 >= PILAMAX )

   return( LLENA);


   pila[ ++superior ] = nuevo;

   return( OK);


   }             // Cierra la funcion empujar


   int extraer()
   {                // La funcion extrae  elementos de la pila

   return( pila[superior--] );

   }                // Cierra la funcion extraer


   int vacio()


  {              // Abre vacio

  if( superior < 0 )
  return(VERDADERO);

  return(FALSO);

  }                  // Cierra vacio


   // Aqui se define la funcion a la que se hara referencia
   // Esta funcion realiza la tarea fundamental de revisar que los
   // parentesis se cierren adecuadamente

   int Revisa_Parentesis( int datos[])

   {     // ABre la funcion Revisa_Parentesis

   int i;
   int comentario = AFUERA;

   /* Esta variable se usa para tener en cuenta siempre si se esta o no dentro de un
    comentario, en caso de estarlo, no debe realizarse nada mas que seguir leyendo
    los caracteres hasta que se encuentre la secuencia de terminacion de comentario
    De entrada se empieza fuera de un comentario */

   for ( i = 0; datos[i] !=  0; i++ )

     // En C++ si es posible declarar la variabl int en la primera parte
     // de for; en C la declaracion no puede hacerse en el ciclo

    // Este ciclo for pasa por alto los caracteres que no sean parentesis
    // Los parentesis de apertura se guardan en una pila


    {                 // ABre for

     switch( datos[i])

     {              // ABre switch

     case '{':

     case '[':

     case '(':



     if ( AFUERA == comentario )

     {
     empujar( datos[i]);

     break;

     }

     case '}':

     if ( AFUERA == comentario )

     {

     if (vacio() || extraer() != '{')

     return (ERROR);
     break;

     }

     case ']':

     if ( AFUERA == comentario )

     {

     if (vacio() || extraer() != '[')

     return (ERROR);
     break;

     }

     case ')':

     if ( AFUERA == comentario )

     {

     if (vacio() || extraer() != '(')

     return (ERROR);
     break;

     }


     case '/':

     if ( AFUERA == comentario )

     {

     if ( '*' == datos[i + 1]  )

     comentario = ADENTRO;

     }

     if (ADENTRO == comentario)

     if ( '*' == datos[ i - 1])

     comentario = AFUERA;

     break;

     }             // Cierra switch

    }                    // Cierra for

    if ( ADENTRO == comentario )

    // Es decir, si nunca se cerro un inicio de comentario, entonces es un errror

    return (ERROR);

    if ( vacio())

    return (OK);

    return (ERROR);

   }          // Cierra la funcion Revisa_Parentesis


   int main()

   {             // Abre main


   int cadena[PILAMAX];

   int c;
   int x = 0;

   int j;
   
   printf("\nEste programa funciona como una especie de preprocesador. ");
   printf("\nPor favor introduzca una cadena con comentarios y le dire si ");
   printf(" los parentesis, corchetes, llaves o comentarios estan bien cerrados o no.\n");
   
   
   while( (c = getchar()) != EOF )

   cadena[ x++ ] = c;

   j = Revisa_Parentesis( cadena);

   if ( OK == j  )
   printf("\nLos parentesis estan bien escritos.\n");

   else

   if( ERROR == j )

   printf("\nLos parentesis estan mal escritos.\n");

   }               // Cierra main


 /* Defectos del programa: En realidad el programa incluye varias partes,
 las cuales no pueden ser tratadas de igual manera. Lo mas sencillo es revisar
 si los parentesis (, [, { se cierran de manera adecuada. La manera de hacerlo
 es un ejemplo tipico del poder de las pilas, este programa incluye partes de los
 ejemplos que vienen en el libro de Bowman ( Algoritmos y Estructuras de D    atos.
 Una Aproximacion en C) ademas la parte principal ( la funcion Revisa_Parentesis)
 es una modificacion de la que se presenta en ese libro. El siguiente punto es
 la revision de los comentarios. Para eso se introdujo la variable comentario,
 que indica si se esta o no dentro de uno. Si se esta entonces no vale apilar
 parentesis ni nada mas, lo unico importante es ver si en algun momento aparece
 la condicion de cierre. Se ha utilizado solamente la forma de /* porque es la
 tipica de el lenguaje C, sin embargo, deberia tambien incluirse el caso de //,
 el cual es la forma de comentario en C++ pero que tambien es valido en C,
 para este caso la condicion de
 terminacion es '\n'. Este programa no considera el caso de las comillas ni los
 apostrofos ni las secuencias de escape. Las secuencias de escape tienen validez
 dentro de una cadena, esto, por lo menos en la forma en que se me ocurre,implica
 crear una variable cadena a la que se le asigne ADENTRO o AFUERA. Sin embargo,
 no es posible apilar las comillas porque en cualquier punto el programa no sabe
 si esta es de apertura o de cierre, hay que atender ese problema con otra
 variable. Si se esta dentro de una cadena, es necesario atender las entradas \
 y ver que siga alguna secuencia de escape. El problema es mas o menos el mismo
 para los apostrofos. En el caso de un compilador, este debe ademas indicar la
 linea y el caracter en el que aparece el problema, ademas de decir exactamente
 cual de todas las secuencias no se cerro de manera adecuada, para esto tambien
 hay que introducir nuevas variables.....

 Solo se me ocurre decir, con Kernighan y Ritchie: "Este programa es dificil si
 se hace completamente general"
 */

No hay comentarios:

Publicar un comentario

Related Posts Plugin for WordPress, Blogger...