Newsgroup: it.comp.lang.c
Titolo: Calcolare una somma... ma...

 'The Krazy One'   ::--------
->  "To reign is worth ambition, though in hell."   |  UIN: 21267457  <-
-<  "Better to Reign in Hell Than Serve in Heaven"  | ircnet: krazy98 >-
---** Bus error - passengers dumped. **---

formula. Come faccio?
/*********************************************************
 * parse.c - parser di semplici espressioni matematiche. *
 *********************************************************/
#include <stdio.h>
#include <ctype.h>
#include <string.h>
#include <stdlib.h>
#include <math.h>
typedef struct {
                 double num ;
               } tipo_valore ;
typedef struct {
                 char * formula ;
                 int    indice ;
               } oggetto_formula ;
typedef enum { OP_ADDZ,   /* operatore di addizione */
               OP_SOTT,   /* operatore di sottrazione */
               OP_MOLT,   /* operatore di moltiplicazione */
               OP_DIVS,   /* operatore di divisione */
               NOMEFNZ,   /* identificatore di funzione */
               COSTNUM,   /* costante numerica */
               FINEFRM    /* fine formula */
             } tipo_token ;
void errore_sintassi ( oggetto_formula * f )
{
     int i ;
     printf ("errore di sintassi nella formula :\n%s\n", f->formula) ;
     for (i = 0 ; i < f->indice-1 ; i++) putchar(' ');
     printf("^\n");
     exit ( 1 ) ;
}
tipo_token prossimo_token ( oggetto_formula * f, tipo_valore * v )
{
     char cnum[20] ;
     int i = 0 ;
     if ( f->formula[f->indice] )
     {
        if ( isdigit ( f->formula[f->indice] ) )
        {
           while ( isdigit ( f->formula[f->indice] ) && (i < 20) )
                 cnum[i++] = f->formula[f->indice++] ;
           cnum[i] = 0 ;
           v->num = atof ( cnum ) ;
           return COSTNUM ;
        }
        else
        switch ( f->formula[f->indice++] )
        {
               case '+' : return OP_ADDZ ;
               case '-' : return OP_SOTT ;
               case '*' : return OP_MOLT ;
               case '/' : return OP_DIVS ;
               default  : errore_sintassi( f ) ;
        }
     }
     else return FINEFRM ;
}
int atteso ( oggetto_formula * f, const tipo_token t )
{
    int i = f->indice ;
    tipo_valore dummy ;
    tipo_token tk = prossimo_token ( f, &dummy ) ;
    if (tk == t) return 1 ;
    else
    {
       f->indice = i ;
       return 0 ;
    }
}
double termine ( oggetto_formula * f )
{
       tipo_token t ;
       tipo_valore v ;
       double x ;
       extern double espressione( oggetto_formula * f ) ;
       switch ( t = prossimo_token( f, &v ) )
       {
              case COSTNUM : return v.num ;
              default : errore_sintassi( f ) ;
       }
}
double fattore ( oggetto_formula * f )
{
       double op1, op2 ;
       int attesoMOLT, attesoDIVS ;
       op1 = termine ( f ) ;
       while ( (attesoMOLT = atteso ( f, OP_MOLT )) ||
               (attesoDIVS = atteso ( f, OP_DIVS )) )
       {
          op2 = termine ( f ) ;
          if ( attesoMOLT ) op1 = op1 * op2 ;
          else
          if ( attesoDIVS ) op1 = op1 / op2 ;
       }
       return op1 ;
}
double espressione ( oggetto_formula * f )
{
       double op1, op2 ;
       int attesoADDZ, attesoSOTT ;
       op1 = fattore ( f ) ;
       while ( (attesoADDZ = atteso ( f, OP_ADDZ )) ||
               (attesoSOTT = atteso ( f, OP_SOTT )) )
       {
          op2 = fattore ( f ) ;
          if ( attesoADDZ ) op1 = op1 + op2 ;
          else
          if ( attesoSOTT ) op1 = op1 - op2 ;
       }
       return op1 ;
}
void assegna_formula ( oggetto_formula * f, const char * testo )
{
     f->indice = 0 ;
     f->formula = malloc ( strlen(testo) + 1 ) ;
     strcpy ( f->formula, testo ) ;
}
int main ( void )
{
    int counter = 0 ;
    oggetto_formula mia_formula ;
    assegna_formula ( &mia_formula, "12*2+76" );
    printf ( "%f\n", espressione ( &mia_formula ) ) ;
    return 0 ;
}

 'The Krazy One'   ::--------
->  "To reign is worth ambition, though in hell."   |  UIN: 21267457  <-
-<  "Better to Reign in Hell Than Serve in Heaven"  | ircnet: krazy98 >-
---** "Mr. Worf, scan that ship." "Aye Captain. 300 dpi?" **---

Prova anche questo programmino di mia invenzione, nel senso che non conosco
algoritmi standard per la soluzione del problema e quello qui usato l'ho
inventato io.
Esegue le operazioni semplici con la giusta precedenza, e gestisce delle
variabili nella forma Vnn (nn da 0 a 99), cioe' puoi avere un'espressione
del tipo  3*(4+5/V6)-7.
Le operazioni ammesse sono: (in ordine crescente di precedenza)
  |    OR binario        --> precedenza piu' bassa
  ^    XOR binario
  &    AND binario
  <>    Confronti
  +-
  */%
  !~    Negato logico (restituisce 1 o 0),negato binario
  (    Subexpression    --> precedenza piu' alta
ciao
donCiccio
----------------------------------------------------------------------------
--------------
#include "stdio.h"
#include "math.h"
#include "string.h"
#include "ctype.h"
#include "stdlib.h"
#define errore(s)      return printf( "%s",s ),0
#define MAXSTACK       10
double var[100];
struct stack
{
  char   op;
  double val;
};
static struct stack stack[MAXSTACK+1],*top=stack;
static double execute ( struct stack * op )
{
  switch( op[1].op )
  {
  case '+': return( op[0].val+op[1].val );
  case '-': return( op[0].val-op[1].val );
  case '*': return( op[0].val*op[1].val );
  case '/': if( op[1].val ) return( op[0].val/op[1].val );
            else            return( 0 );
  case '<': return( op[0].val<op[1].val );
  case '>': return( op[0].val>op[1].val );
  case '&': return( (long)op[0].val&(long)op[1].val );
  case '|': return( (long)op[0].val|(long)op[1].val );
  case '^': return( (long)op[0].val^(long)op[1].val );
  case '%': if( op[1].val ) return( fmod( op[0].val,op[1].val ) );
            else            return( 0 );
  case '~': return( ~(long)op[1].val );
  case '!': return( !op[1].val );
  case '=': return(  op[1].val );
  }
  return 0;
}
static int  push ( void )
{
  if( (int)(top-stack)>MAXSTACK )   errore("stack full");
  top++;
  return 1;
}
static int  pop ( struct stack * start )
{
  if( top<=start )   return 0;
  top--;
  top[0].val=execute( top );
  return 1;
}
static char * optab[]=
{
  "=",
  "|",
  "^",
  "&",
  "<>",
  "+-",
  "*/%",
  "!~",
  "(",
};
static int  oplev ( char op )
{
  int  lev;
  for( lev=0 ; optab[lev] ; lev++ )
    if( strchr( optab[lev],op ) )
      return( lev );
  return 0;
}
static char * skipdigit ( char * exp )
{
  for( ; isdigit( *exp ) || *exp=='.' ; exp++ );
  return( exp );
}
double expression ( char * exp,double * var )
{
  int    n;
  struct stack * start=top;
  top->val=0;
  top->op ='=';
  push();
  top->op ='+';
  for( ;; )
  {
    for( ; isspace( *exp ) ; exp++ );
    switch( *exp )
    {
    case 'V': top->val=var[atoi( ++exp )]; exp=skipdigit( exp ); break;
    case '.':
    case '0':
    case '1':
    case '2':
    case '3':
    case '4':
    case '5':
    case '6':
    case '7':
    case '8':
    case '9': top->val=atof( exp ); exp=skipdigit( exp ); break;
    case '~':
    case '!':
    case '|':
    case '&':
    case '^':
    case '<':
    case '>':
    case '+':
    case '-':
    case '*':
    case '/':
    case '%':
      while( oplev( *exp )<=oplev( top->op ) && pop( start ) );
      push();
      top->op=*exp++;
      break;
    case '(':
      push();
      top->val=expression( ++exp,var );
      for( n=0 ; *exp ; exp++ )
        if( *exp=='(' )  n++;
        else if( *exp==')' )
          if( n )  n--;
          else     break;
      exp++;
      pop( start );
      break;
    case  0 :
    case ')':
      while( pop( start ) );
      return start->val;
    default : errore(exp);
    }
  }
}
void main ( void )
{
  char s[1000];
  var[0]=100;
  var[1]=-100;
  for( ;; )
  {
    printf( "Scrivi l'espressione da calcolare\n" );
    gets( s );
    if( !*s )  break;
    printf( "\nIl risultato e' : %lf\n",expression( s,var ) );
  }
}