Se joku vb lausekkeen laskija innosti ja piti sitten itsekkin tehdä semmonen. Kielenä on c++, mukana myös potenssi (^) ja lausekkeen parserointitapa on melkoisen erilainen, että eiköhän tästäkin vielä jotain hyötyä ole. :) Parserointi vähän bugittaa ainakin lukujen lukemisen osalta (hyväksyy pelkät + tai -, sekä 42...321.3 tyylisiä lukuja), mutta ei jaksanut korjata.
#include <iostream> #include <string> #include <vector> #include <ctype.h> #include <math.h> const string operchars = "+-*/^"; int calcorders[] = { 1, 1, 2, 2, 3 }; class Error { public: Error(const char *p) { position = p; } const char *position; }; double evaluateClause(const char *clause, const char **bracketend=0) { vector<double> numbers; vector<char> operators; /* Parsetetaan vuorotellen numero ja operaattori */ bool nextisnumber = true; while(*clause) { while(isspace(*clause)) clause++; if(nextisnumber) { if(isdigit(*clause) || *clause=='+' || *clause=='-') { string s = string() + *clause; while(isdigit(*(++clause)) || *clause=='.') s += *(clause); numbers.push_back(atof(s.c_str())); } else if(*clause == '(') { numbers.push_back(evaluateClause(clause+1, &clause)); } else throw new Error(clause); } else { if(*clause == ')') { if(!bracketend) throw new Error(clause); *bracketend = clause+1; break; } if(operchars.find(*clause) == string::npos) throw new Error(clause); operators.push_back(*clause); clause++; } nextisnumber = nextisnumber?false:true; // true/false vaihto } if(!*clause && bracketend) throw new Error(clause); // Loppui sulkeessa if(nextisnumber) throw new Error(clause); // Loppuihan varmasti numeroon /* Lasketaan kunnes loppuu operit ja suurimmat laskujärjestykset ensin */ while(operators.size()) { int c = -1, i, p; for(i=0; i<(int) operators.size(); i++) { if(calcorders[operchars.find(operators[i])] > c) { c = calcorders[operchars.find(operators[i])]; p = i; } } switch(operators[p]) { case '+': numbers[p] = numbers[p] + numbers[p+1]; break; case '-': numbers[p] = numbers[p] - numbers[p+1]; break; case '*': numbers[p] = numbers[p] * numbers[p+1]; break; case '/': numbers[p] = numbers[p] / numbers[p+1]; break; case '^': numbers[p] = pow(numbers[p], numbers[p+1]); break; } numbers.erase(numbers.begin()+p+1); operators.erase(operators.begin()+p); } return numbers[0]; } int main(int argc, char *argv[]) { try { if(argc < 2) throw "Ei lauseketta argumenttina"; cout << evaluateClause(argv[1]) << endl; } catch(const char *s) { cerr << s << endl; return -1; } catch(Error *e) { cerr << "Virhe: " << argv[1] << endl; cerr << " "; const char *p = argv[1]; while(p++ != e->position) cerr << " "; cerr << "^" << endl; delete e; return -1; } return 0; }
Hyvän näköistä koodia, huomattavasti lyhyempi kuin omani ;)
Hipo ounake :9
antti, johtunee kielestä
Hienolta näyttää.. pitänee seuraavaksi viritellä lausekkeen laskija asmilla ;)
Hienoa koodia, ja näyttää toimivan (en voi testata kun gcc ei suostu kääntämään c++aa)
eh? djgpp? jos sulla on djgpp asennettu oikein niin kylläpä se kääntää c++ kielisiäkin (gpp on komento muistaakseni)
Ei känny BC++ :-(
Call to undefined function 'sring'
Cannot convert 'int' to 'std::...
Undefined symbol 'numbers'
...
Saisko exenä?
koodi näyttää hienolta.
Aihe on jo aika vanha, joten et voi enää vastata siihen.