Esamina le espressioni matematiche con due valori che hanno parentesi e segni meno

1

Sto cercando di analizzare equazioni come quelle qui sotto, che hanno solo due valori o la radice quadrata di un certo valore, da un file di testo:

100+100

-100-100

-(100)+(-100)

sqrt(100)

tra i segni meno, tra parentesi e il simbolo dell'operatore nel mezzo e la radice quadrata, e non ho idea di come iniziare ... Ho fatto la parte del file e le semplici parti di calcolo tranne che non potevo ottenere il mio programma per risolvere le equazioni di cui sopra.

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

main(){
    FILE *fp;
    char buff[255], sym,sym2,del1,del2,del3,del4;
    double num1, num2;
    int ret;
    fp = fopen("input.txt","r");

    while(fgets(buff,sizeof(buff),fp)!=NULL){
        char *tok = buff;
        sscanf(tok,"%lf%c%lf",&num1,&sym,&num2);

        switch(sym){
            case '+': printf("%lf\n", num1+num2);
                    break;
            case '-': printf("%lf\n", num1-num2);
                    break;
            case '*': printf("%lf\n", num1*num2);
                    break;
            case '/': printf("%lf\n", num1/num2);
                    break;
            default: printf("The input value is not correct\n");
                    break;
        }
    }
    fclose(fp);
}

Questo è ciò che ho scritto per le altre operazioni di base senza parentesi e il segno meno per il secondo valore e funziona benissimo per le semplici. Sto usando un'istruzione switch per calcolare le operazioni add, sub, mul e div, ma non sono sicuro di come usare correttamente la funzione sscanf (se non la sto usando correttamente) o se c'è un altro modo, come usare una funzione come strtok per analizzare correttamente le parentesi e i segni meno. Qualsiasi tipo di aiuto?

    
posta user45921 08.06.2014 - 23:55
fonte

3 risposte

2

Le espressioni di analisi, con parentesi e precedenze di operatori diversi, sono l'esempio di parsing standard in quasi tutti i libri di testo del compilatore esistenti. Le chiamate di funzione non sono USUALMENTE parte di quell'esempio, ma sono abbastanza semplici da aggiungere. Piuttosto che fare tentativi ed errori, la tua vita sarà molto più facile a lungo termine se impari come farlo per davvero.

L'introduzione più accessibile alla creazione di parser costruiti a mano ho visto è "Costruiamo un compilatore" di Jack Crenshaw .

Il libro di testo più accessibile che ho visto sulla compilazione del compilatore è "Costruzione del compilatore" di Wirth . Descrive l'analisi della discesa ricorsiva codificata a mano.

I riferimenti canonici sulla costruzione del compilatore sono i vari libri del drago . Personalmente ho usato il Green Dragon Book e l'ho trovato utilizzabile, sebbene l'attenzione sia sui parser LALR generati meccanicamente piuttosto che su parser codificati a mano.

    
risposta data 14.07.2014 - 17:20
fonte
0

Un approccio migliore Esistono molti modi per analizzare e valutare le espressioni come una struttura di dati ricorsiva. Qualsiasi espressione può essere definita come segue:

espressione - > termine + termine - termine

termine - > Fattore * fattore / fattore
factor - > variatore, numero, espressione come 10 + 5 * B consistono in 2 termini 10, 5 * B.

Il secondo termine contiene 2 fattori 5 e B.

Ecco una sequenza che seguirai

  1. inserisci un'espressione come 9 / 3- (100 5)
  2. il parser ottiene il primo termine 9/3.
  3. ottieni ogni fattore e dividi gli interi il risultato è 3
  4. ottenere il secondo termine (100 56). Inizia analizzando in modo ricorsivo la seconda espressione secondaria.
  5. ottieni ogni termine e aggiungili. Il risultato è 156: ritorna dalla chiamata ricorsiva, 3-156 = 3.

Questo è un concetto complesso che richiede tempo per abituarsi.

Se vuoi un esempio, dimmelo. (Non ho dato l'esempio perché sarà molto lungo). Ma se vuoi un esempio, te ne darò volentieri uno.)

Se ti senti confuso puoi usare google "analisi delle espressioni ricorsive".

    
risposta data 14.07.2014 - 11:27
fonte
0

Dovresti creare AST (Abstract Syntax Tree) . Costruiscilo con rispetto per la precedenza, quindi la moltiplicazione / divisione viene prima della sottrazione o dell'aggiunta. Anche le parentesi dovrebbero essere gestite, ma in teoria suonano complesse.

Il mio parser semplice che ho scritto qualche tempo fa

Come puoi vedere dal codice sorgente sto usando i modelli. Solo semplici elenchi concatenati che mi consentono di distinguere input come VALUE OPERATION VALUE (1 + 2 o 3 * 6).

Quando incontro parentesi come 1+2*(4+5) solo 1+2 e 4+5 corrisponde a un modello, quindi li ridimensiono e ho VAL*(VAL) . Ora OPEN_PAREN VALUE CLOSE_PAREN) corrisponde a un modello e quindi lo ridimensiono in VAL . Ora ho VAL*VAL . E questo è tutto.

Il codice sorgente è stato scritto per scopi di apprendimento da me, quindi ho cercato di tenerlo pulito e piccolo. Nel caso abbiate bisogno di una spiegazione, sentitevi liberi di chiedere nei commenti.

    
risposta data 14.07.2014 - 13:18
fonte

Leggi altre domande sui tag