Esercizio stack C
Salve. Ho trovato questo esercizio per il linguaggio c. Una volta lanciato però non funziona, qualcuno saprebbe aiutarmi???
Nella notazione RPN gli operatori vengono posti dopo gli operandi. Per esempio 1+2*3 verrebbe scritto come 1 2 3 * +. Si può usare la stack per aiutarsi basandosi su queste due regole:
-quando si trova un operando va messo nella stack;
-quando si trova un operatore si prelevano gli ultimi due operansi, si esegue l'operazione tra loro e si rimette il risultato nella stack.
Scrivere un programma che calcoli un'espressione RPN. L'operatore = fa si che venga visualizzato l'elemento in cima alla lista, svuoti la stack e venga richiesta un'altra espressione. Il processo vada avanti finchè non viene immenso un carattere diverso da operatori e operandi. Se la stack va in overflow stampare L'espressione è troppo complessa e uscire dal programma. Se la stack va in underflow, a causa di troppi operatori rispetto agli operandi stampare Non abbastanza operandi e uscire dal programma.
Questo è il mio codice. Spero mi possiate aiutare.
Nella notazione RPN gli operatori vengono posti dopo gli operandi. Per esempio 1+2*3 verrebbe scritto come 1 2 3 * +. Si può usare la stack per aiutarsi basandosi su queste due regole:
-quando si trova un operando va messo nella stack;
-quando si trova un operatore si prelevano gli ultimi due operansi, si esegue l'operazione tra loro e si rimette il risultato nella stack.
Scrivere un programma che calcoli un'espressione RPN. L'operatore = fa si che venga visualizzato l'elemento in cima alla lista, svuoti la stack e venga richiesta un'altra espressione. Il processo vada avanti finchè non viene immenso un carattere diverso da operatori e operandi. Se la stack va in overflow stampare L'espressione è troppo complessa e uscire dal programma. Se la stack va in underflow, a causa di troppi operatori rispetto agli operandi stampare Non abbastanza operandi e uscire dal programma.
Questo è il mio codice. Spero mi possiate aiutare.
#include <stdio.h> #include <stdlib.h> #define STACK_SIZE 100 int contents[STACK_SIZE]; int top=0; char risultato; void make_empty(void); bool is_empty(void); bool is_full(void); void push(char i); char pop(void); void stack_overflow(void); void stack_underflow(void); char operazione(char op_1, char op_2, char segno); int main(void){ char ch, operando_1, operando_2; printf("Immettere un'espressione RPN: \n"); scanf(" %c", &ch); while(('0'<=ch && ch<='9') or ch=='+' or ch=='-' or ch=='*' or ch=='/' or ch=='='){ while(ch!='='){ while('0'<=ch && ch<='9'){ push(ch); } while(ch=='+' or ch=='-' or ch=='*' or ch=='/'){ operando_1=pop(); operando_2=pop(); operazione(operando_1, operando_2, ch); push(risultato); } scanf(" %c", &ch); } printf("Il risultato dell'espressione risulta: %d\n\n", risultato); make_empty(); printf("Immettere un'espressione RPN: \n"); scanf(" %c", &ch); } return 0; } void make_empty(void){ top=0; } bool is_empty(void){ return top==0; } bool is_full(void){ return top==STACK_SIZE; } void stack_overflow(void){ printf("L'espressione è troppo complessa!\n"); exit(EXIT_SUCCESS); } void stack_underflow(void){ printf("Non ci sono abbastanza operandi!\n"); exit(EXIT_SUCCESS); } void push(char i){ if(is_full()) stack_overflow(); else contents[top++]=i; } char pop(void){ if(is_empty()) stack_underflow(); else return contents[--top]; } char operazione(char op_1, char op_2, char segno){ switch(segno){ case '+': return risultato=op_1+op_2; break; case '-': return risultato=op_2-op_1; break; case '*': return risultato=op_1*op_2; break; case '/': return risultato=op_2+op_1; break; } }
Risposte
"Dadde11":
while(('0'<=ch && ch<='9') or ch=='+' or ch=='-' or ch=='*' or ch=='/' or ch=='='){ while(ch!='='){ while('0'<=ch && ch<='9'){ push(ch); } // ... scanf(" %c", &ch); } // ... }
Non capisco il perche' di tutti questi while (in alcuni punti sembra che tu confonda while e if), ma comunque: se ch e' un numero, quando entra nel while piu' interno, come fa ad uscire, visto che ch non cambia mai di valore?
Dovresti invece fare un solo ciclo, e prevedere condizioni di uscita per ogni "eccezione" (operatore non valido, overflow, underflow, etc.).
Ti dispiacerebbe usare il tag code? E magari indentalo.
Qual'è esattamente il problema del tuo programma?
Qual'è esattamente il problema del tuo programma?
Mi dice continuamente errore di overflow. Yoshiharu, mi potresti dare alcune dritte per evitare tutti questi cicli????
"Dadde11":
Mi dice continuamente errore di overflow. Yoshiharu, mi potresti dare alcune dritte per evitare tutti questi cicli????
Ti da errore di overflow perche' continua a push-are ch, visto che non esce mai dal ciclo interno.
Fai un solo ciclo, nella condizione metti solo che l'input non sia l'operatore '='.
Inoltre tieni presente che probabilmente e' piu' utile se la calcolatrice permette di usare numeri di piu' di una cifra, nell'input tu prendi un singolo carattere (e poi fai i test su quello), il che non puo' essere corretto (che succede se immetti un numero a piu' cifre? Il tuo programma lo considera come una sequenza di operandi in cifra singola).
Togli tutti gli altri while.
Quando viene immesso un numero (a piu' cifre!), lo leggi, e lo metti sullo stack (per cui push non puo' avere il prototipo void push(char), dovrai usare almeno push(int) (cambia int col tipo numerico che ti serve) visto che sullo stack finiscono solo i numeri operandi.
Invece di leggere con scanf(), che e' un po' subdola, leggi con fgets, e poi fai il parsing, usando strcmp per vedere se l'input e' uno degli operatori, e se non lo e' verifica che sia un numero e usa sscanf per leggere il numero in input.
Per esempio, una cosa tipo
while(fgets(raw_input,MAXINPUT,stdin)) { sscanf(raw_input,"%s",input); if(!strcmp(input,"op1")) { // ricevi op1, agisci di conseguenza continue; } // molte altre strcmp() if(!verifica(input)) { // notifica che c'e' un errore, l'input non e' ne' un operatore ne' un numero valido continue; // oppure esci lamentandoti che non ci sono piu' gli utenti di una volta } sscanf(input,"%d",&numero); // numero e' una variabile int: cambiare di conseguenza in caso di float etc. push(numero); // tutto e' andato bene, finora }
Spero sia chiaro.
Ti ringrazio davvero per il consiglio. non ho postato tutto il testo per comodità comunque chiede di fare in modo che ogni numero sia formato al massimo da una cifra, e di usare la scanf che ho usato io per fornire il numero. Perche il ciclo iniziale è solo diverso da =? perchè finita un espressione lui continua a chiedertene sempre un'altra, finchè l utente non immette un carattere diverso da un operatore o un operando! per questo avevo fatto piu cicli. prima controllo che l'utente voglia continuare, immettendo u imput valido, poi entro ad analizzare l imput fino all'uguale che mi dice di dare il risultato. questo era il senso del mio codice. Secondo il tuo ragionamento come posso semplificare tutto ciò??? grazie mille!!!
"Dadde11":
Perche il ciclo iniziale è solo diverso da =? perchè finita un espressione lui continua a chiedertene sempre un'altra, finchè l utente non immette un carattere diverso da un operatore o un operando! per questo avevo fatto piu cicli.
Ma anche in questo caso, basta un ciclo solo, se l'input e' un operatore agisci di conseguenza (sollevando eventualmente un'eccezione), se e' un operando lo metti sullo stack, se non e' ne l'uno ne' l'altro lo rifiuti dando errore (e eventualmente continui ignorando l'input). Se l'input e' '=' fai pop, stampi il risultato, e continui col ciclo, considerando '=' un operatore come gli altri (ma unario).
Probabilmente il codice che hai scritto poteva anche andare bene, cambiando alcuni while in if (praticamente tutti quelli interni...).
C'e'un motivo per cui questo genere di cose si chiama "Read Evaluate and Print LOOP" (notare il singolare)

Alcuni commenti.
La libreria standard ctype.h fornisce delle utili funzioni per verificare che tipo di caratteri sono stati inseriti. Per esempio per verificare che un carattere c è una cifra basta usare isdigit(c). È buona norma usarle. Se usi scanf direi che hai quasi solo bisogno di quello mentre se carichi elemento per elemento con getchar() e permetti anche numeri a più cifre hai bisogno di usarne di più.
Comunque serve certamente un solo ciclo, con qualche if interni.
La libreria standard ctype.h fornisce delle utili funzioni per verificare che tipo di caratteri sono stati inseriti. Per esempio per verificare che un carattere c è una cifra basta usare isdigit(c). È buona norma usarle. Se usi scanf direi che hai quasi solo bisogno di quello mentre se carichi elemento per elemento con getchar() e permetti anche numeri a più cifre hai bisogno di usarne di più.
Comunque serve certamente un solo ciclo, con qualche if interni.