Ultima modifica:
@St3ve
PHP:/* questo è per il "risolvere" le singole parentesi... l'ho fatto col più e col meno ma si più facilmente riscrivere * col * e il / * per la potenza è un'altra storia... vedi se è adeguato... * non è neanche completo ma è la linea generale, almeno quella a cui pensavo io*/ #include<iostream> #include<string> #include<vector> using namespace std; int conv_str(string); int main() { /*diamo per scontato che nella parentesi da analizzare le operazioni abbiano tutte la medesima priorità, e * che le priorità siano invece definite tramite le parentesi stesse in modo più rigido. * anzi che 2+5*3-3/1 l'utente dovrà 2+(5*3)-(3/1) * un piccolo sforzo per l'utente, un grandissimo vantaggio per noi! Nonchè la maggiore facilità di gestione * degli errori. * sacrificio accettabile... per me almeno! :P */ string esp, tmp; vector<char> op; vector<int> vals; int ris, i; cout<<"espressione = "; cin>>esp; tmp=esp; //lavoro prima sui numeri con tmp senza rovinare esp e poi con esp sugli operatori for(i=0; i<tmp.size(); i++) { if(tmp[i]=='+' || tmp[i]=='-') { vals.push_back(conv_str(tmp.substr(0, i))); tmp=tmp.substr(i+1, (tmp.size()-1)); i=0; //questa riga mi è costata venti minuti di duro ragionamento! :| } } vals.push_back(conv_str(tmp)); // perchè l'ultimo valore resta escluso... poco male :) //ora abbiamo un vector con i numeri, inseriamo gli operatori nell'ordine giusto e il gioco è fatto! for(i=0; i<esp.size(); i++) { if(esp[i]=='+') op.push_back('+'); else if(esp[i]=='-') op.push_back('-'); } //ora abbiamo un vettore con le operazioni i=0; /*do { if(op[op.size()-i]=='+') ris=vals[vals.size()-1]+vals[vals.size()-2]; else if(op[op.size()-i]=='-') ris=vals[vals.size()-1]-vals[vals.size()-2]; vals.erase(vals.end()-1); vals.push_back(ris); vals.erase(vals.end()-2); i++; } while(vals.size()>1); * qui mi sono bloccato... non so se ti può essere utile ma se riesci a combinare i due vector per risolvere * parentesi di pari priorità e riesci a estrarre di volta il volta le parentesi più esterne dall'espressione iniziale * e a sostituire per ogni parentesi il suo risultato hai fatto... no? * questo è quello che per ora ho scritto... domani mi ci metto di nuovo.*/ cout<<ris<<endl; return 0; } int conv_str(string s) { int num; if(s.size()==1) num=s[0]-48; else if(s.size()==2) num=((s[0]-48)*10)+(s[1]-48); else if(s.size()==3) num=((s[0]-48)*100)+((s[1]-48)*10)+(s[2]-48); else if(s.size()==4) num=((s[0]-48)*1000)+((s[1]-48)*100)+((s[2]-48)*10)+(s[3]-48); return num; }
Grazie mille per l'aiuto! Ti do un paio di consigli visto che ci stai provando pure tu.
Il ragionamento sul push_back alla linea 41 ("perchè l'ultimo valore resta escluso") si può fare e non si può fare: in teoria 1*(2+3) dovrebbe essere una stringa valida e con quel sistema si leggerebbe 3) come un numero unico (amenochè lo step di *rimuovere* le parentesi non si faccia prima) e la tua funzione conv_str lo interpreta effettivamente come tale.
Tralasciando il fatto che per ora il tuo codice non legge le parentesi, secondo me la funzione per separare i numeri dalle operazioni dovrebbe essere più indipendente. Il tuo ragionamento è quello di scansare le operazioni, il numero è la parte che rimane, ma secondo me è più semplice cercare i numeri.
Quello che intendo io è qualcosa di simile:
Codice:
int len = 0;
for(i = 0; i <= tmp.size(); i++)
{
if(tmp[i] >= '0' && tmp[i] <= '9')
len++;
else if(len > 0)
{
vals.push_back(conv_str(tmp.substr(i-len, len))); // di fatto non modifico tmp
len = 0;
}
}
La funzione conv_str funziona meglio così:
Codice:
int conv_str(string s)
{
int num = 0;
for(size_t it = 0; it < s.length(); it++) // rimane completamente indipendente dalla lunghezza della stringa
{
num *= 10; // inizialmente non fa niente (0*10=0), agli step successivi shifta a sinistra il numero in base 10 e fa posto
num += s[it] - '0'; // al numero successivo. s[it] - '0' serve per convertire da ASCII a int un numero formato da una cifra.
} // esempio: s="123" -> 0*0=0 0+1=1 -> 1*10=10 10+2=12 -> 12*10=120 120+3=123
return num;
}
Comunque ci siamo gente, ora il mio programmino riesce a mangiarsi mostri come questo:
Codice:
>> (3+(5.412*2.123-5.12^4+(5!-7!))+10-2*44*(12+3!^2))/3^3!
expression: (3+(5.412*2.123-5.12^4+(5!-7!))+10-2*44*(12+3!^2))/3^3!
sub_expr = 3+(5.412*2.123-5.12^4+(5!-7!))+10-2*44*(12+3!^2)
sub_expr = 5.412*2.123-5.12^4+(5!-7!)
sub_expr = 5!-7!
sub_expr = 12+3!^2
result: -13.452270
Sarebbe per un progetto scolastico, se gli porto lì il codice generato da un compilatore se ne accorgono (senza contare che glielo dovrei commentare oralmente). Comunque non mi serve nemmeno in assembly x86, mi serve in assembly MIPS.In ogni caso per tradurlo in codice ASM puoi fermare il compilatore prima che generi l'eseguibile...
Per il g++ credo che sia
g++ -S nomefile.cpp -o nomefile
No?