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.