Problema Programma in C

di il
14 risposte

Problema Programma in C

Sono disperato.. ho questo programma da fare per l'uni e non ho idea da dove incominciare..
la consegna è questa:
Creare una funzione eval() che prenda in ingresso una stringa come questa "2+3*4*5-2*3" e restituisca il valore intero del'operazione numerica tra i caratteri.
Quindi in questo caso 56.

14 Risposte

  • Re: Problema Programma in C

    Come lo faresti tu a prescindere dalla programmazione?
    prova a descrivere a parole tue come risolverebbe una persona la cosa
  • Re: Problema Programma in C

    Niente! ce l'ho fatta.. non so con che miracolo
  • Re: Problema Programma in C

    Ti va di postare il codice ? perchè anche io l'ho svolto e volevo confrontarlo
  • Re: Problema Programma in C

    Questa è la funzione.. ho incluso la libreria string.h e anche la stdlib.h per la funzione atoi()


    int eval(char *stringa)
    {
    int i,sum=0,j,k=0;
    int subsumX=1;
    int subsum=0;
    int subsumP=0;
    int tempSubsum=0;

    if(stringa[1]=='*')
    subsumX=subsumX*(stringa[0]-48);
    if(stringa[1]=='+' || stringa[1]=='-')
    subsumP=subsumP+(stringa[0]-48);

    //per
    for(i=0;i<strlen(stringa);i++)
    {
    //printf("%d\n",tempSubsum);
    if(stringa=='*')
    {
    subsumX=subsumX*(stringa[i+1]-48);
    if(stringa[i+2]!='*' || stringa[i+2]=='\0')
    {
    for(k=i;(stringa[k+1]!='+' && stringa[k+1]!='-') && k>0;k--)
    {
    //printf("%d\n",k);
    if(stringa[k]=='+' || k==0)
    subsumX=subsumX*(stringa[k+1]-48);
    if(stringa[k]=='-' || k==0)
    subsumX=0-subsumX*(stringa[k+1]-48);
    }
    tempSubsum=tempSubsum+subsumX;
    subsumX=1;
    }
    }
    }

    // più e meno giusti
    for(i=0;i<strlen(stringa);i++)
    {
    if(stringa=='+' && stringa[i+2]!='*')
    subsumP=subsumP+(stringa[i+1]-48);
    if(stringa=='-' && stringa[i+2]!='*')
    subsumP=subsumP-(stringa[i+1]-48);
    }
    return tempSubsum+subsumP;

    }
  • Re: Problema Programma in C

    Però mi pare di capire, alla veloce, che la tua funzione risolve solo le espressioni con numeri minori di 10

    Io ho fatto così:
    
    int eval(char *str)
    {
        float numeri[N];/*vettore di tutti i numeri */
        char simboli[N];/* vettore di tutti gli operatori */
        int i,j,dim,finito,errore;/*indici; i,j ; flag: finito,errore*/
    
        i=0;/*controllo della correttezza della stringa, se erroro uscirà con 0 */
        errore=FALSO;
        while((str[i]!='\0')  && (i+1<N)  &&  (!errore))
        {
            if(isalpha(str[i]))
                errore=VERO;
            if(ispunct(str[i]))
                {
                    if(!isdigit(str[i+1]))
                    errore=VERO;
                }
            i++;
        }
    
        if(!errore)/* passato il test di formato*/
        {
            i=0;/*estrapolazione dei numeri e degli operatori, ordinatamente*/
            j=0;
            finito=FALSO;
            while(!finito)
            {
                sscanf(&str[j],"%f",&numeri[i]);
                j += strcspn (&str[j],"+-*/");
                sscanf(&str[j],"%c",&simboli[i]);
                if(simboli[i]=='\0')
                    finito =VERO;
                i++;
                j++;
            }
            dim=i;/* quantita di valori numerici trovati */
    
    /*svolgo tutti i prodotti e le divisioni , e dopo somme e differenze ,come indicato da http://it.wikipedia.org/wiki/Ordine_delle_operazioni*/
    
    /* eseguo i prodotti e le divisioni spostando gli operatori e i numeri di conseguenza : esempio 
    
    1+2*3*4-2*3+4 diventerà 1+12*4-12+4 poi 1+48-12+4 , spostando i segni e i numeri nel vettore.*/
            finito = FALSO;
            i=0;
            while(!finito)
            {
                if(simboli[i]=='*')
                {
                    numeri[i]=numeri[i]*numeri[i+1];
                    dim--;
    
                    for (j=i+1; j<dim; j++)
                        numeri[j]=numeri[j+1];
                    for(j=i; j<dim; j++)
                        simboli[j]=simboli[j+1];
                    i=0;
                }
                else if(simboli[i]=='/')
                {
                    numeri[i]=numeri[i]/numeri[i+1];
                    dim--;
    
                    for (j=i+1; j<dim; j++)
                        numeri[j]=numeri[j+1];
                    for(j=i; j<dim; j++)
                        simboli[j]=simboli[j+1];
                    i=0;
                }
                else i++;
                if(i>dim)
                    finito=VERO;
            }
    
    
    /* eseguo le somme e le differenze nello stesso modo sopra*/
            finito = FALSO;
            i=0;
            while(!finito)
            {
                if(simboli[i]=='+')
                {
                    numeri[i]=numeri[i]+numeri[i+1];
                    dim--;
    
                    for (j=i+1; j<dim; j++)
                        numeri[j]=numeri[j+1];
                    for(j=i; j<dim; j++)
                        simboli[j]=simboli[j+1];
                    i=0;
                }
                else if(simboli[i]=='-')
                {
                    numeri[i]=numeri[i]-numeri[i+1];
                    dim--;
    
                    for (j=i+1; j<dim; j++)
                        numeri[j]=numeri[j+1];
                    for(j=i; j<dim; j++)
                        simboli[j]=simboli[j+1];
                    i=0;
                }
                else i++;
                if(i>dim)
                    finito=VERO;
            }
        }
        else/* se c'è stato l'errore nella codifica*/
            numeri[0]=0;
    /* restituisce il valore finale del processo oppure l'errore (problema di distinguere i due casi) */
        return (int)numeri[0];
    /* esempio: 2+3*4*5-2*3 -> 2+12*5-12 -> 2+60-6 -> 62-6 -> 56 */
    /*si è preferito usare i float per evitare errori troppo grossi nella elaborazione delle divisioni , restituendo soltanto alla fine un valore intero*/
    }
    
    Penso che esista un modo più semplice ma a me è venuto da fare così
  • Re: Problema Programma in C

    Per estrapolare i dati avevo in mente di eseguire un controllo carattere per carattere, ma non mi andava a genio, perchè avrei poi dovuto elaborare numeri con più cifre... e mi sono arrangiato in quel modo. Se qualcuno non capisce qualcosa del codice lo spiego nel dettaglio
  • Re: Problema Programma in C

    Si si giusto.. ma chiedeva solo numeri a 1 cifra.. ora la fase 2 del problema è quella di mettere le parentesi.. cioè 3+4*(5+3*2)-4=43..
    e questa fase non sono ancora riuscito a farla..

    se vuoi provare
  • Re: Problema Programma in C

    Ho provato il tuo codice.. ma FALSO non è dichiarato e anche VERO.. (hai per caso incluso qualche libreria??) e N immagino che tu abbia fatto un define.. ma quanto vale?
  • Re: Problema Programma in C

    
    #include <stdio.h>
    #include <string.h>
    #include <ctype.h>
    #define N 60
    #define VERO 1
    #define FALSO 0
    
    int eval(char *str);
    
    int main()
    {
        char ingresso[N];
        int ris;
        scanf("%s",ingresso);
        ris=eval(ingresso);
        printf("%d\n",ris);
        return 0;
    }
    
    int eval(char *str)
    {
        float numeri[N];/*vettore di tutti i numeri */
        char simboli[N];/* vettore di tutti gli operatori */
        int i,j,dim,finito,errore;/*indici; i,j ; flag: finito,errore*/
    
        i=0;/*controllo della correttezza della stringa, se erroro uscirà con 0 */
        errore=FALSO;
        while((str[i]!='\0')  && (i+1<N)  &&  (!errore))
        {
            if(isalpha(str[i]))
                errore=VERO;
            if(ispunct(str[i]))
                {
                    if(!isdigit(str[i+1]))
                    errore=VERO;
                }
            i++;
        }
    
        if(!errore)/* passato il test di formato*/
        {
            i=0;/*estrapolazione dei numeri e degli operatori, ordinatamente*/
            j=0;
            finito=FALSO;
            while(!finito)
            {
                sscanf(&str[j],"%f",&numeri[i]);
                j += strcspn (&str[j],"+-*/");
                sscanf(&str[j],"%c",&simboli[i]);
                if(simboli[i]=='\0')
                    finito =VERO;
                i++;
                j++;
            }
            dim=i;/* quantita di valori numerici trovati */
    
    /*svolgo tutti i prodotti e le divisioni come indicato da http://it.wikipedia.org/wiki/Ordine_delle_operazioni*/
    
    /* eseguo i prodotti e le divisioni spostando gli operatori e i numeri di conseguenza : esempio
    
    1+2*3*4-2*3+4 diventerà 1+12*4-12+4 poi 1+48-12+4 , spostando i segni e i numeri nel vettore.*/
            finito = FALSO;
            i=0;
            while(!finito)
            {
                if(simboli[i]=='*')
                {
                    numeri[i]=numeri[i]*numeri[i+1];
                    dim--;
    
                    for (j=i+1; j<dim; j++)
                        numeri[j]=numeri[j+1];
                    for(j=i; j<dim; j++)
                        simboli[j]=simboli[j+1];
                    i=0;
                }
                else if(simboli[i]=='/')
                {
                    numeri[i]=numeri[i]/numeri[i+1];
                    dim--;
    
                    for (j=i+1; j<dim; j++)
                        numeri[j]=numeri[j+1];
                    for(j=i; j<dim; j++)
                        simboli[j]=simboli[j+1];
                    i=0;
                }
                else i++;
                if(i>dim)
                    finito=VERO;
            }
    
    
    /* eseguo le somme e le differenze nello stesso modo sopra*/
            finito = FALSO;
            i=0;
            while(!finito)
            {
                if(simboli[i]=='+')
                {
                    numeri[i]=numeri[i]+numeri[i+1];
                    dim--;
    
                    for (j=i+1; j<dim; j++)
                        numeri[j]=numeri[j+1];
                    for(j=i; j<dim; j++)
                        simboli[j]=simboli[j+1];
                    i=0;
                }
                else if(simboli[i]=='-')
                {
                    numeri[i]=numeri[i]-numeri[i+1];
                    dim--;
    
                    for (j=i+1; j<dim; j++)
                        numeri[j]=numeri[j+1];
                    for(j=i; j<dim; j++)
                        simboli[j]=simboli[j+1];
                    i=0;
                }
                else i++;
                if(i>dim)
                    finito=VERO;
            }
        }
        else/* se c'è stato l'errore nella codifica*/
            numeri[0]=0;
    /* restituisce il valore finale del processo oppure l'errore */
        return (int)numeri[0];
    /* esempio: 2+3*4*5-2*3 -> 2+12*5-12 -> 2+60-6 -> 62-6 -> 56 */
    /*si è preferito usare i float per evitare errori troppo grossi nella elaborazione delle divisioni , restituendo soltanto alla fine un valore intero*/
    }
    
    Scusami , mi sono scordato per le parentesi ci stavo pensando... ma per adesso non mi viene in mente nulla, perchè sto anche preparando un'esame e non ho molto tempo
  • Re: Problema Programma in C

    Stavo pensando di aggiungere le parentesi nel vettore delle operazioni , essendo strettamente legati, salvando anche quelli e modificando la parte delle precedenze in base a quello , ma non ho ancora provato..

    Una cosa del tipo: vedere se nel vettore dei simboli compare una parentesi aperta, finchè non si incontra quella chiusa, elaborare le operazioni interne, spostando come scritto, poi alla fine rimuovere le parentesi e continuare. Bisogna vedere bene i casi N( per trasformare in * .

    Ovviamete bisogna cambiare il controllo della stringa facendo caso a se c'è una parentesi aperta e non chiusa , e come si trattano i casi tipo 1+((4*3))? devo pensarsi su con calma
  • Re: Problema Programma in C

    Oppure fare una ricorsione molto più pratica.... prima di tutto trovi le parentesi più esterne (facendo attenzione) e le fai fare alla stessa funzione (mandando la stringa direttamente) , per tutte le parentesi finche compaiono ... e poi esegui quella finale sulla stringa che ti è rimasta... la ricorsione la puoi praticare facilmente anche nella tua
  • Re: Problema Programma in C

    Capito.. proverò con la ricorsione.. grazie
  • Re: Problema Programma in C

    Ho trovato degli errori nella mia versione ... ho aggiunto la parte delle parentesi:
    
    #include <stdio.h>
    #include <string.h>
    #include <ctype.h>
    #define N 60
    #define VERO 1
    #define FALSO 0
    
    int eval(char *str);
    
    int main()
    {
        char ingresso[N];
        int ris;
        scanf("%s",ingresso);
        ris=eval(ingresso);/* il vettore viene modificato dalla funzione*/
        printf("%d\n",ris);
        return 0;
    }
    
    int eval(char *str)
    {
        char tmp_str[N];/*vettore temporaneo per utilita*/
        float numeri[N];/*vettore di tutti i numeri */
        char simboli[N];/* vettore di tutti gli operatori */
        int i,j; /*indici*/
        int dim;/*serve a memorizzare delle dimensioni*/
        int finito,errore;/*flag per segnalare le due situazioni*/
        int inizio,fine;/*indici di posizione inizio e fine*/
        int tmp;/*intero utile per memorizazzioni di passaggio*/
        errore=FALSO;/* se questo stato cambia la funzione torna 0*/
    
        finito=FALSO;/* per avviare almeno una volta il ciclo */
        while(!finito&&!errore)/*a condizioni soddisfatte continua a chiamare se stessa per eliminare le parentesi */
        {
            i=0;
            finito=VERO;/* se questo rimane vero allora non ci sono più parentesi*/
    
            while((str[i]!=')')&&(str[i]!='\0')&&(!errore))
            {
                /* questo ciclo serve a trovare le parentesi più esterne , e controlla che non ci siano errori di parentesi
                 o di formattazione stringa ( mancato '\0')*/
                if(str[i]=='(')
                {
                    inizio=i;
                    finito=FALSO;
                }
                i++;
                if(i>=N)
                    errore=VERO;
            }
            fine=i;
    /* forma la string da mandare a se stessa per risolvere*/
            if(!finito)
            {
                i=inizio+1;
                j=0;
                while(i<fine)/* prepare la stringa*/
                    {
                        tmp_str[j]=str[i];
                        j++;
                        i++;
                    }
                tmp_str[j]='\0';
    
                tmp=eval(tmp_str);/*mette il risultato in una variabile temporane*/
                sprintf(tmp_str,"%d",tmp);/* trasforma il valore numerico in testo per inserirlo nella stringa attuale data dal chiamante*/
                dim=strlen(tmp_str);
    
                for(i=0; i<dim; i++)/* inserisce il valore trovato */
                    str[inizio+i]=tmp_str[i];
                inizio = (inizio+i);
    
                i=inizio;
                j=fine+1;
                while(str[j]!='\0')/* sposta la parte dopo la parentesi alla destra del risultato*/
                {
                    str[i]=str[j];
                    i++;
                    j++;
                }
                str[i]='\0';
            }
        }
    /* finito questo blocco la stringa non presenta più parentesi */
    
        i=0;/*controllo della correttezza della stringa, se erroro uscirà con 0 */
        while((str[i]!='\0')  && (i+1<N)  &&  (!errore))
        {
            if(isalpha(str[i]))
                errore=VERO;
            if(ispunct(str[i]))
            {
                if(!isdigit(str[i+1]))
                    errore=VERO;
            }
            i++;
        }
    
        if(!errore)/* passato il test di formato*/
        {
            i=0;/*estrapolazione dei numeri e degli operatori, ordinatamente*/
            j=0;
            finito=FALSO;
            while(!finito)
            {
                sscanf(&str[j],"%f",&numeri[i]);
                j += strcspn (&str[j],"+-*/");
                tmp=sscanf(&str[j],"%c",&simboli[i]);
                if(tmp==-1)/*se la scanf fallisce e perchè sono finiti gli operatori e c'è '\0'*/
                    finito=VERO;
                i++;
                j++;
            }
            dim=i;/* quantita di valori numerici trovati */
    
            /*svolgo tutti i prodotti e le divisioni come indicato da http://it.wikipedia.org/wiki/Ordine_delle_operazioni*/
    
            /* eseguo i prodotti e le divisioni spostando gli operatori e i numeri di conseguenza : esempio
    
            1+2*3*4-2*3+4 diventerà 1+12*4-12+4 poi 1+48-12+4 , spostando i segni e i numeri nel vettore.*/
    
            finito = FALSO;
            i=0;
            while(!finito)
            {
                if(simboli[i]=='*')
                {
                    numeri[i]=numeri[i]*numeri[i+1];
                    dim--;
    
                    for (j=i+1; j<dim; j++)
                        numeri[j]=numeri[j+1];
                    for(j=i; j<dim; j++)
                        simboli[j]=simboli[j+1];
                    i=0;
                }
                else if(simboli[i]=='/')
                {
                    numeri[i]=numeri[i]/numeri[i+1];
                    dim--;
    
                    for (j=i+1; j<dim; j++)
                        numeri[j]=numeri[j+1];
                    for(j=i; j<dim; j++)
                        simboli[j]=simboli[j+1];
                    i=0;
                }
                else i++;
                if(i>dim)
                    finito=VERO;
            }
    
    
            /* eseguo le somme e le differenze nello stesso modo sopra*/
            finito = FALSO;
            i=0;
            while(!finito)
            {
                if(simboli[i]=='+')
                {
                    numeri[i]=numeri[i]+numeri[i+1];
                    dim--;
    
                    for (j=i+1; j<dim; j++)
                        numeri[j]=numeri[j+1];
                    for(j=i; j<dim; j++)
                        simboli[j]=simboli[j+1];
                    i=0;
                }
                else if(simboli[i]=='-')
                {
                    numeri[i]=numeri[i]-numeri[i+1];
                    dim--;
    
                    for (j=i+1; j<dim; j++)
                        numeri[j]=numeri[j+1];
                    for(j=i; j<dim; j++)
                        simboli[j]=simboli[j+1];
                    i=0;
                }
                else i++;
                if(i>dim)
                    finito=VERO;
            }
        }
        else/* se c'è stato l'errore nella codifica*/
            numeri[0]=0;
        /* restituisce il valore finale del processo oppure l'errore */
        return (int)numeri[0];
        /* esempio: 2+3*4*5-2*3 -> 2+12*5-12 -> 2+60-6 -> 62-6 -> 56 */
        /*si è preferito usare i float per evitare errori troppo grossi nella elaborazione delle divisioni , restituendo soltanto alla fine un valore intero*/
    }
    
    
  • Re: Problema Programma in C

    Grande!!! grazie millee!! =)
Devi accedere o registrarti per scrivere nel forum
14 risposte