[C] Calcolatore espressioni

C & C++ , problemi, richieste e progetti.

[C] Calcolatore espressioni

Postby Fabrix on 04 Jul 2008 11:13

Ecco un calcolatore in C , che risolve anche intere espressioni ( esercizio del mio libro (Deitel) )
Per ora ha le 4 operazioni base e l'elevamento a potenza , appena ne ho voglia potrei provare ad aggiungere qaulche funzione tipo coseno , seno ecc...

Code: Select all
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <ctype.h>

struct stackNode {
      char data ;
      struct stackNode * next ;
      };

struct nodoint {
      int data ;
      struct nodoint * next ;
      };
      

typedef struct stackNode StackNode ;
typedef StackNode * StackNodePtr ;

typedef struct nodoint NodoInt ;
typedef NodoInt * NodoIntPtr ;

int  Valute ( char * ) ;
char * convertToPostfix ( char * infix ) ;
int  isOperator ( char  ) ;
int  precedence ( char , char ) ;
void push ( StackNodePtr * , char ) ;
int pushInt ( NodoIntPtr * , int ) ;
int  popInt ( NodoIntPtr * ) ;
char pop ( StackNodePtr * ) ;
char stackTop ( StackNodePtr ) ;
int  isEmpty ( StackNodePtr ) ;
int  calculate ( int , int , char ) ;

int main ( void )
{
   printf ( "Calcolatore C \n\n"
            "<expression> <-p>\n\n"
            "<expression> = Espressione da risolvere \n"
          "<-p> =         Opzionale , visualizza l'espressione in notazione polacca\n\n");
   

    char infix [ 512 ] = "" ;
   int  debug = 0 , polacca = 0 ;
   char * pos ;

while ( 1 ) {
      
    sprintf ( infix , "" ); 
   printf ( "\nEspressione -> " ) ;   
   fflush ( stdin ) ; gets ( infix ) ;
   
    if ( (pos=strstr ( infix , "-p" )) != NULL ){
          strcpy ( pos , "\0" ) ;
          printf ( "\nNotazione polacca : %s\n" , convertToPostfix ( infix ) );
    }

   printf ( "\n==>%d\n", Valute ( convertToPostfix ( infix ) ) ) ;
   
}

    fflush(stdin); getchar();
   return 0;
   
}

void push ( StackNodePtr * s , char c )
{
       StackNodePtr nuovo = ( StackNodePtr ) malloc ( sizeof ( StackNode ) ) ;
       nuovo->data = c ;
       nuovo->next = *s ;
       *s = nuovo ;     
}

int pushInt ( NodoIntPtr * n , int i )
{
    if ( i == EOF ) return EOF ;
    NodoIntPtr nuovo = ( NodoIntPtr ) malloc ( sizeof ( NodoIntPtr ) ) ;
    nuovo->data = i ;
    nuovo->next = *n ;
    *n = nuovo;
}

int isEmpty ( StackNodePtr s )
{
   return ( s == NULL ) ? 1 : 0 ;


int isOperator ( char c )
{
   switch ( c ) {
         case '+' :
            case '-' :
            case '*' :
            case '/' :
         case '^' :
               return 1 ;
            break;
            }
   return 0;
}   

int precedence ( char a , char b )
{
   if ( a == '+' || a == '-' ) return 1 ;
   
   if ( a == '*' || a == '/' )
          if ( b == '/' || b == '*' || b == '^' )
              return 1 ;
              
    if ( a == '^' ) return -1 ;
   
   return -1;

}           
             
char stackTop ( StackNodePtr s )
{
    return s -> data ;
}

char pop ( StackNodePtr * s )
{
    StackNodePtr tmp ;
    char pop ;
   
    tmp = *s ;
    pop = (*s)->data;
    *s = (*s)->next ;
    free ( tmp ) ;
   
    return pop ;

}

int popInt ( NodoIntPtr * s )
{
    NodoIntPtr tmp ;
    int pop ;
   
    tmp = *s ;
    pop = (*s)->data;
    *s = (*s)->next ;
    free ( tmp ) ;
   
    return pop ;

}



int calculate ( int a , int b , char c )
{
   int j , res = 1 ;
   
    if ( c == '+' ) return a + b ;
else if ( c == '*' ) return a * b ;
else if ( c == '-' ) return b - a ;
else if ( c == '/' ){
    if ( a == 0 )   
        return EOF ;
    else           
        return b / a ;
    }
else if ( c == '^' ) {
    for ( j = 0 ; j < a ; j++ )
        res *= b ;
        return res ;
}
     
     
}
   
      

char * convertToPostfix ( char * infix )
{
    int tmp , j , k ;
    StackNodePtr stackPtr = NULL ;
     char * postfix = ( char * ) malloc ( strlen ( infix ) ) ;
     sprintf ( postfix , "" ) ;
    strcat ( infix , ")" ) ;
    push ( &stackPtr , '(' ) ;
   
   for ( j = 0 , k = 0 ; !isEmpty ( stackPtr ) ; j++ ){
      
      if ( isdigit ( infix [ j ] ) ){
             for ( ; isdigit  ( infix [ j ] ) ; k++ , j++ )
            postfix [ k ] = infix [ j ] ;   
            postfix [ k++ ] = ' ' ;
          }
      
      if ( infix [ j ] == '(' )
            push ( &stackPtr , '(' ) ;
       
        if ( isOperator ( infix [ j ] ) ) {
             for ( ; precedence ( infix [ j ] , stackTop ( stackPtr ) ) != -1 && isOperator ( stackTop ( stackPtr ) ) ; k++ )
                 postfix [ k ] = pop ( &stackPtr ) ;
           push ( &stackPtr , infix [ j ] ) ;
      }
      
      if ( infix [ j ] == ')' ) {
             for ( ; stackTop ( stackPtr ) != '(' ; k++ )
                 postfix [ k ] = pop ( &stackPtr ) ;
            pop ( &stackPtr ) ;
       }

}
   
    return postfix ; 
   
}

int Valute ( char * postfix )
{
   NodoIntPtr risolvi = NULL ;
   int j , a , tmp ;
   char temporany [ 10 ] = "" ;
   
   
   for ( j = 0 ; postfix [ j ] != '\0' ; j++ ) {
         
         if ( isdigit ( postfix [ j ] ) ){
               for ( sprintf ( temporany , "" ) , a = 0 ; isdigit ( postfix [ j ] ) ; a++ , j++ )
                 temporany [ a ] = postfix [ j ] ;
             temporany [ a++ ] = '\0' ;
               pushInt ( &risolvi , atoi ( temporany ) ) ;
          }
                      

         else if ( isOperator ( postfix [ j ] ) ){
            if ( pushInt ( &risolvi , calculate ( popInt ( &risolvi ) , popInt ( &risolvi ) , postfix [ j ] ) ) == EOF ){
                printf ( "\nErrore : divisione per zero -> Failed\n" ) ;
                return -1;
               }
           }            
     }

   return popInt ( &risolvi ) ;     
}

Fabrix
Newbies
 
Posts: 18
Joined: 30 Jan 2008 21:54

[C] Calcolatore espressioni

Sponsor

Google Adsense

Re: [C] Calcolatore espressioni

Postby k8 on 04 Jul 2008 12:39

Ficata!
Testato e provato, sembra andare!
Free hosting.
Whois
Cerco gente interessata, bloggers,moderatori,programmatori & o scripter per far rinascere il progetto bigbug.
Topic di riferimento: http://forum.big-bug.net/news-dal-web-f7/apertura-nuovo-sito-t1798.html
User avatar
k8
Admin
 
Posts: 2022
Joined: 06 Jun 2006 16:00

Re: [C] Calcolatore espressioni

Postby __GiReX__ on 04 Jul 2008 14:46

Davvero bravo ;)
Lo stesso esercizio scritto con la programmazione ad oggetti sarebbe stato puù "ordinato" ma d'altronde stai studiando il C
non il C++ ;)
User avatar
__GiReX__
Moderatore
 
Posts: 79
Joined: 07 May 2007 21:48

Re: [C] Calcolatore espressioni

Postby Fabrix on 04 Jul 2008 23:30

:) :D :P
Fabrix
Newbies
 
Posts: 18
Joined: 30 Jan 2008 21:54

Re: [C] Calcolatore espressioni

Postby HdS619 on 29 Jul 2008 13:07

Ciao, se ho capito bene questo programma risolve espressioni del tipo
Code: Select all
{98+[2*(3*3-2/1)+(3-1)]}+[1*(10-3)]


Avevo fatto un programma del genere anch'io in C tempo fa, gestiva anche la priorità dei * e / rispetto ai + e -.. Solo che non funziona in tutti i casi ma se la cava anche lui

Code: Select all
*
* "rex.c" (C) HdS619 ( hds619@gmail.com )
*
* This is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3 of the License, or
* (at your option) any later version.
*     
* This is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
* GNU General Public License for more details.
*   
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
* MA 02110-1301, USA.
*/

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

#define ascii_number(c) (( c >= 0x30 && c <= 0x39 ) || c == '.')

struct pos_number
{
  int start;
  int end;
};

typedef enum { false = 0, true } bool;

char *resolve_t(char *);
char *resolve_q(char *);
char *resolve_g(char *);
float resolve(char *);
void pos_back_number(char *, int, struct pos_number *);
void pos_for_number(char *, int, struct pos_number *);
char *build_string(char *, struct pos_number *);

int
string_add_n (char ** start, char * string_add, size_t s)
{
  char *tmp_ptr = NULL;
  size_t add_size, ss = s;

  if (!ss)
    {
      ss = strlen (string_add) + 1;
    }

  if (!(*start))
    {
      *start = malloc (ss);

      if (!(*start))
        {
          return -1;
        }

      strncpy (*start, string_add, ss);

      if (s)
        {
          (*start)[ss] = '\0';
        }
      return 0;
    }

  add_size = strlen (*start);

  tmp_ptr = realloc (*start, (add_size + ss) + 1);

  if (tmp_ptr)
    {

      *start = tmp_ptr;
      strncpy ((*start) + add_size, string_add, ss);
      (*start)[add_size + ss] = '\0';

      return 0;
    }

  return -1;

}

char *strreplace (char * string, char * search_string, char * replace_string)
{
  char *str = NULL, *pos;
  size_t spos;
  int res = 0;

  if (!(pos = strstr (string, search_string)))
    {
      return string;
    }

  if (!(spos = pos - string))
    {
      res += string_add_n (&str, replace_string, 0);
      res += string_add_n (&str, string + strlen (search_string), 0);
    }
  else
    {
      res += string_add_n (&str, string, spos);
      res += string_add_n (&str, replace_string, 0);
      res += string_add_n (&str, string + strlen (search_string) + spos, 0);
    }

  if (!res)
    {
      return str;
    }

  free (str);
  return string;
}

int strpos (char * str, char * substr)
{
  int len = strlen (str), lensub = strlen (substr);
  int i, pos = 0, c;

  for (i = 0; i < len; ++i)
    {
      if (str[i] == *substr)
        {
          pos = i + 1;
          for (c = 0; c < lensub; ++c)
            {
              if (str[i + c] != substr[c])
                {
                  pos = -1;
                  break;
                }
            }
          if (pos)
            break;
        }
    }

  if ( pos == -1 )
       return pos;
       
  return pos - 1;
}

int main(int argc, char *argv[])
{
char *expr;
float result;

if ( argc == 1 ) {
      char *nome;
      if (!(nome = strrchr(*argv, '/') + 1))
           nome = strdup(*argv);
      printf("%s%s%s\n%s%s%s\n",
             "Uso: ", nome, " \"expression\"",
             "Esempio: `", nome, " \"{2+[1*(3-1)]}*4\"`");
      return 0;
}

expr = strdup(argv[1]);

if ( strpos(argv[1], "(") != -1 ) {
      expr = resolve_t(expr);
}
if ( strpos(argv[1], "[") != -1 ) {
      expr = resolve_q(expr);
}
if ( strpos(argv[1], "{") != -1 ) {
      expr = resolve_g(expr);
}

result = resolve(expr);

printf("Risultato: %g\n", result);

return 0;
}

void pos_back_number(char *s, int x, struct pos_number *p)
{
int i = x;
bool check = false;

for ( ; i >= 0; --i ) {
       if ( ascii_number(s[i]) && !check ) {
            p->end = i;
            check = !check;
       }
       if ( !ascii_number(s[i]) && check )
            break;
}
p->start = i + 1;

}

void pos_for_number(char *s, int x, struct pos_number *p)
{
int i, len = strlen(s);
bool check = false;

p->end = len - 1;
for ( i = x + 1; i < len; ++i ) {
       if ( (s[i] >= 0x30 && s[i] <= 0x39) && !check ) {
            p->start = i;
            check = true;
       }
       if ( !ascii_number(s[i]) && check ) {
            p->end = i - 1;
            break;
       }
}

}

char *build_string(char *s, struct pos_number *p)
{
int i = p->start;
char *str;

if ( p->end < p->start ) {
      fprintf(stderr, "errore: "
                      "impossibile recuperare l'espressione: "
                      "fine prima dell'inizio!\n");
      exit(1);
}

str = (char *) malloc(p->end-p->start);

for ( ; i <= p->end; ++i )
      str[i-p->start] = s[i];

return str;
}

char *resolve_t(char *s)
{
char *lexpr, *expr, *tmp;
struct pos_number p;
float res;

lexpr = strdup(s);

while((p.start = strpos(lexpr, "(") + 1)) {
         if ((p.end = strpos(lexpr, ")") - 1 ) == -1) {
              fprintf(stderr, "errore: "
                              "espressione malformata: %d ( %c ): "
                              "manca la parentesi di chiusura!\n",
                              p.start+1, lexpr[p.start]);
              exit(1);
         }

         expr = build_string(lexpr, &p);
         res = resolve(expr);
         tmp = (char *) malloc(30);
         sprintf(tmp, "%g", res);
         free(expr);
         --p.start;
         ++p.end;
         expr = build_string(lexpr, &p);
         lexpr = strreplace(lexpr, expr, tmp);
}

return lexpr;
}

char *resolve_q(char *s)
{
char *lexpr, *expr, *tmp;
struct pos_number p;
float res;

lexpr = strdup(s);

while((p.start = strpos(lexpr, "[") + 1)) {
         if ((p.end = strpos(lexpr, "]") - 1 ) == -1) {
              fprintf(stderr, "errore: "
                              "espressione malformata: %d ( %c ): "
                              "manca la parentesi di chiusura!\n",
                              p.start+1, lexpr[p.start]);
              exit(1);
         }

         expr = build_string(lexpr, &p);
         res = resolve(expr);
         tmp = (char *) malloc(30);
         sprintf(tmp, "%g", res);
         free(expr);
         --p.start;
         ++p.end;
         expr = build_string(lexpr, &p);
         lexpr = strreplace(lexpr, expr, tmp);
}

return lexpr;
}

char *resolve_g(char *s)
{
char *lexpr, *expr, *tmp;
struct pos_number p;
float res;

lexpr = strdup(s);

while((p.start = strpos(lexpr, "{") + 1)) {
         if ((p.end = strpos(lexpr, "}") - 1 ) == -1) {
              fprintf(stderr, "errore: "
                              "espressione malformata: %d ( %c ): "
                              "manca la parentesi di chiusura!\n",
                              p.start+1, lexpr[p.start]);
              exit(1);
         }

         expr = build_string(lexpr, &p);
         res = resolve(expr);
         tmp = (char *) malloc(30);
         sprintf(tmp, "%g", res);
         free(expr);
         --p.start;
         ++p.end;
         expr = build_string(lexpr, &p);
         lexpr = strreplace(lexpr, expr, tmp);
}

return lexpr;
}

float resolve(char *s)
{
enum { X = 0, Y, N };
char *lexpr, *num[N], *tmp, *tmp2;
struct pos_number x, y, p;
float res = 0.0;
bool check = false;

lexpr = (char *) malloc(strlen(s));
strcpy(lexpr, s);

while(strpos(lexpr, "*") != -1) {
       if ( !check ) {
            pos_back_number(lexpr, strpos(lexpr, "*"), &x);
            num[X] = build_string(lexpr, &x);
       }
       
       pos_for_number(lexpr, strpos(lexpr, "*"), &y);
       num[Y] = build_string(lexpr, &y);
       
       if ( !check ) {
            res = atof(num[X]) * atof(num[Y]);
            check = !check;
       }
       else res *= atof(num[Y]);
       
       tmp = (char *) malloc(30);
       sprintf(tmp, "%g", res);
       
       p.start = x.start;
       p.end   = y.end;
       tmp2 = build_string(lexpr,&p);
       
       lexpr = strreplace(lexpr, tmp2, tmp);
       free(tmp2);
}
check = false;
while(strpos(lexpr, "/") != -1) {
       if ( !check ) {
            pos_back_number(lexpr, strpos(lexpr, "/"), &x);
            num[X] = build_string(lexpr, &x);
       }
       
       pos_for_number(lexpr, strpos(lexpr, "/"), &y);
       num[Y] = build_string(lexpr, &y);
       
       if ( !check ) {
            res = atof(num[X]) / atof(num[Y]);
            check = !check;
       }
       else res /= atof(num[Y]);
       
       tmp = (char *) malloc(30);
       sprintf(tmp, "%g", res);
       
       p.start = x.start;
       p.end   = y.end;
       tmp2 = build_string(lexpr,&p);
       
       lexpr = strreplace(lexpr, tmp2, tmp);

       free(tmp2);
}
check = false;
while(strpos(lexpr, "+") != -1) {
       if ( !check ) {
            pos_back_number(lexpr, strpos(lexpr, "+"), &x);
            num[X] = build_string(lexpr, &x);
       }
       
       pos_for_number(lexpr, strpos(lexpr, "+"), &y);
       num[Y] = build_string(lexpr, &y);
       
       if ( !check ) {
            res = atof(num[X]) + atof(num[Y]);
            check = !check;
       }
       else res += atof(num[Y]);
       
       tmp = (char *) malloc(30);
       sprintf(tmp, "%g", res);
       
       p.start = x.start;
       p.end   = y.end;
       tmp2 = build_string(lexpr,&p);
   
       lexpr = strreplace(lexpr, tmp2, tmp);
       free(tmp2);
}
check = false;
while(strpos(lexpr, "-") > 0) {
       if ( !check ) {
            pos_back_number(lexpr, strpos(lexpr, "-"), &x);
            num[X] = build_string(lexpr, &x);
       }
       
       pos_for_number(lexpr, strpos(lexpr, "-"), &y);
       num[Y] = build_string(lexpr, &y);
       
       if ( !check ) {
            res = atof(num[X]) - atof(num[Y]);
            check = !check;
       }
       else res -= atof(num[Y]);
       
       tmp = (char *) malloc(30);
       sprintf(tmp, "%g", res);
       
       p.start = x.start;
       p.end   = y.end;
       tmp2 = build_string(lexpr,&p);
       
       lexpr = strreplace(lexpr, tmp2, tmp);
       free(tmp2);
}

return res;
}


Ciauz ;)
User avatar
HdS619
Newbies
 
Posts: 5
Joined: 08 May 2008 21:06

Re: [C] Calcolatore espressioni

Postby Fabrix on 01 Aug 2008 15:04

Si HdS però le parentesi solo ( o ) cioè questa

{98+[2*(3*3-2/1)+(3-1)]}+[1*(10-3)]

diventa così

(98+(2*(3*3-2/1)+(3-1)))+(1*(10-3))
Fabrix
Newbies
 
Posts: 18
Joined: 30 Jan 2008 21:54


Return to C/C++

Who is online

Users browsing this forum: No registered users and 1 guest

cron