home *** CD-ROM | disk | FTP | other *** search
/ CD Multi Review 1994 November / CDMR_0.ISO / pc / program / amiga / csource / calc201.lha / Calc.c next >
Encoding:
C/C++ Source or Header  |  1990-06-03  |  7.1 KB  |  221 lines

  1. /* **************************************************************
  2.  
  3. Programma ...... Calc.c
  4. Versione ....... 2.01, 1 Maggio 1990
  5. Scopo .......... Calcolo di espressioni ASCII con numeri f.p.
  6. Autore ......... Luigi Callegari
  7. Sintassi ....... Calc [expr] || Calc [nomefile]
  8. Hardware ....... Amiga standard 500/2500, Kickstart V1.2/1.3/1.4
  9. Software ....... Lattice C V5.04, Aztec C V5.0a
  10. Make Lattice ... LC -cusf -vbr -Lntvm -O -fi Calc
  11. Make Aztec ..... CC -fa -sb -so Calc, LN calc -lma -lc
  12.  
  13. ************************************************************** */
  14.  
  15. #define MAXOPL 5  /* Massimo numero di livelli */
  16. #define MAXELE 50 /* Massimo numero di operandi aritmetici */
  17. #define NOP 0     /* Token di "nessuna operazione" */
  18. #define ADD 1     /* Token di somma aritmetica */
  19. #define SUB 2     /* Token di sottrazione aritmetica */
  20. #define MUL 3     /* Token di moltiplicazione aritmetica */
  21. #define DIV 4     /* Token di divisione aritmetica */
  22. #define POW 5     /* Token di elevazione a potenza */
  23. #define PRIOR POW /* Operazione prioritaria per importanza */
  24.  
  25. #define isoper(c) (c=='+'||c=='-'||c=='/'||c=='*'||c=='^')
  26.  
  27. #include <string.h>        /* Funzioni di gestione stringa */
  28. #include <stdlib.h>        /* Funzioni di libreria standard */
  29. #include <ctype.h>         /* Funzioni isxxxx() */
  30. #include <stdio.h>         /* I/O Standard */
  31. #include <math.h>          /* Matematica */
  32. #include <libraries/dos.h> /* Gestione AmigaDOS */
  33.  
  34. #ifdef LATTICE
  35. #  include <proto/all.h>
  36. #else
  37. #  include <functions.h>
  38. #endif
  39.  
  40. double num[ MAXELE ];          /* Matrice Operandi */
  41. int op[ MAXELE ][ MAXOPL ];    /* Matrice Operatori aritmetici */
  42. int lev;                       /* Livello operatori */
  43. int nop;                       /* Numero effettivo operatori */
  44. int nel;                       /* Numero effettivo operandi */
  45. char *buf;                     /* Buffer per elaborazione batch */
  46. BPTR lucc;                     /* Lock di file */
  47.  
  48. /* ******** Uscita da errore con messaggio di postmortem ****** */
  49.  
  50. void die( char *s )  /* Puntatore a messaggio di errore */
  51. {
  52.    if ( lucc ) UnLock( lucc );
  53.    fprintf( stderr, "\n%s\n", s );
  54.    exit( 10L );
  55. }
  56.  
  57. /* Ritorna lunghezza in caratteri di una stringa ASCII rappresentante
  58. un numero in virgola mobile, con eventuale notazione esponenziale */
  59.  
  60. int luncifra( char *s )
  61. {
  62.    int j = 0;
  63.    
  64.    while ( isdigit( s[ j ] ) ) ++j;    /* Salta parte intera */
  65.    if ( s[ j ] == '.' )
  66.       {
  67.       ++j;
  68.       while ( isdigit( s[ j ] ) ) ++j; /* Salta eventuali decimali */
  69.       }
  70.    
  71.    if ( s[ j ] == 'e' || s[ j ] == 'E' )
  72.       {
  73.       ++j;                             /* Salta parte esponenziale */
  74.       if ( s[ j ] == '+' || s[ j ] == '-' )
  75.          ++j;
  76.       while( isdigit( s[ j ] ) ) ++j;
  77.       }
  78.  
  79.    return( j );
  80. }
  81.  
  82. /* ************ Corregge matrici dopo una operazione ********** */
  83.  
  84. void compr( int *k ) /* Puntatore a posizione di operando usato */
  85. {
  86.    unsigned short int j, i; /* Variabili di lavoro */
  87.   
  88.    --nop;  --nel;    /* Aggiusta contatori di operatori e operandi */
  89.   
  90.    for ( j=*k ; j<nel ; j++ ) /* Elimina operando usato */
  91.      num[ j+1 ] = num[ j+2 ];
  92.  
  93.    for ( i=0 ; i<MAXOPL ; i++ ) /* Elimina operatore usato */
  94.       for ( j=*k ; j<nop ; j++ )
  95.          op[ j ][ i ] = op[ j+1 ][ i ];
  96.      
  97.    *k -= 1; /* Riporta puntatore scansione a posizione corretta */
  98.    return;
  99. }
  100.  
  101. /*************** Memorizza operandi ed operatori ***************/
  102.  
  103. void parse( char *s ) /* Stringa ASCII dell'espressione */
  104. {
  105.    int c;                  /* Carattere da esaminare */
  106.    int j;                  /* Variabili di lavoro */
  107.    short operation;        /* Operazione da eseguire */
  108.   
  109.    for ( j=0 ; j<strlen(s) ; j++ ) {
  110.       c = s[ j ];
  111.      
  112.       if ( c == ')' && --lev < 0 )
  113.          die( "Troppe parentesi chiuse!" );
  114.     
  115.       else if ( c == '(' && ++lev == MAXOPL )
  116.          die( "Troppe parentesi aperte!" );
  117.     
  118.       else if ( isoper( c ) ) {       /* Memorizza operatore */
  119.          switch( c ) {
  120.             case '^' : operation = POW; break;
  121.             case '+' : operation = ADD; break;
  122.             case '-' : operation = SUB; break;
  123.             case '*' : operation = MUL; break;
  124.             case '/' : operation = DIV; break;
  125.             default  : operation = NOP; break;
  126.             }                          /* end switch(c) */
  127.          op[ nop++ ][ lev ] = operation;
  128.          }                             /* end else if() */
  129.      
  130.       else if ( isdigit( c ) ) {       /* Memorizza operando */
  131.          num[ nel++ ] = (double) atof( &s[ j ] ); 
  132.          if ( nel >= MAXELE )
  133.             die( "Troppi operandi!" );
  134.             
  135.          j += luncifra( &s[ j ] ) - 1; /* Salta numero inserito */
  136.          }                             /* end else if  */
  137.       }                                /* end for (j) */
  138.    return;
  139. }                                      /* end parse() */
  140.  
  141. /************ Esegue materialmente i calcoli ***************/
  142.  
  143. double calc( char *s ) /* Puntatore a stringa di espressione */
  144. {
  145.    int j, i;
  146.  
  147.    (void)parse( s ); /* Crea matrici operandi e operatori */
  148.  
  149.    for ( lev=MAXOPL-1 ; lev>=0 ; lev-- ) /* Da livello massimo */
  150.       {
  151.       for ( j=PRIOR ; j >= ADD ; j-- ) /* Da oper. prioritaria */
  152.          for ( i=0 ; i < nop; i++ )      /* Da primo operatore */
  153.             if ( op[ i ][ lev ] == j )
  154.                {
  155.                switch( op[ i ][ lev ] ) {
  156.                   case DIV: num[ i ] /= num[ i+1 ]; break;
  157.                   case MUL: num[ i ] *= num[ i+1 ]; break;
  158.                   case ADD: num[ i ] += num[ i+1 ]; break;
  159.                   case SUB: num[ i ] -= num[ i+1 ]; break;
  160.                   case POW: num[ i ] = pow(num[i],num[i+1]);break;
  161.                   default :                         break;
  162.                   } /* end switch */
  163.  
  164.                   compr( &i );      /* Aggiorna matrici */
  165.             }                       /* end if */
  166.       }                             /* end for (lev) */
  167.    return( num[ 0 ] );
  168. }
  169.  
  170. /* ********** Funzione trasferimento file in buffer ************ */
  171. char *makebuf( char *s )
  172. {
  173.    struct FileInfoBlock *fib;
  174.    char *ptr;
  175.    LONG lunfile;
  176.    BPTR fileh;
  177.    
  178.    if (!(lucc=Lock(s, ACCESS_READ) ) )
  179.       die("Locking impossibile!");
  180.  
  181.    if (!(fib=(struct FileInfoBlock*)malloc(sizeof(struct FileInfoBlock))))
  182.       die( "Manca memoria per FIB" );
  183.  
  184.    if ( ! Examine( lucc, (BPTR) fib ) )
  185.       die( "Non esamino file!" );
  186.    
  187.    lunfile = fib -> fib_Size; UnLock( lucc );
  188.    lucc = (BPTR) NULL;
  189.    
  190.    if ( ! (ptr = (char *) malloc( lunfile ) ) )
  191.       die("Manca memoria");
  192.    
  193.    if ( ! (fileh=Open( s, MODE_OLDFILE )))
  194.       die("Non si apre il file");
  195.  
  196.    if ( Read( fileh, ptr, lunfile ) != lunfile)
  197.       die("Errore di I/O");
  198.  
  199.    Close( fileh );
  200.    
  201.    return( ptr );
  202. }
  203.  
  204. /************ Funzione principale *****************/
  205.  
  206. void main( int argc, char *argv[] )
  207. {  
  208.    if ( argc != 2 ) {            /* Sintassi errata */
  209.       printf( "\nSintassi: %s [expr|nomefile]\n", argv[ 0 ] );
  210.       exit( 10L );
  211.       }
  212.  
  213.    if ( isalpha( argv[1][0] ))   /* Dato un nome di file */  
  214.       printf("File %s = %.8g\n", argv[1], calc(makebuf(argv[1])));
  215.  
  216.    else                          /* Data un'espressione */
  217.       printf( "%s = %.8g\n", argv[ 1 ], calc( argv[ 1 ] ) );
  218.  
  219.    exit( 0L );
  220. }
  221.