Kirjautuminen

Haku

Tehtävät

Keskustelu: Koodit: C++: Lausekkeen laskija

Sivun loppuun

Hipo [28.09.2002 19:24:31]

#

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;
}

Antti Laaksonen [29.09.2002 13:44:07]

#

Hyvän näköistä koodia, huomattavasti lyhyempi kuin omani ;)

Kossu [29.09.2002 17:38:59]

#

Hipo ounake :9

Jaakko [29.09.2002 18:28:30]

#

antti, johtunee kielestä

thefox [30.09.2002 12:30:28]

#

Hienolta näyttää.. pitänee seuraavaksi viritellä lausekkeen laskija asmilla ;)

(nimetön) [03.10.2002 19:27:59]

#

Hienoa koodia, ja näyttää toimivan (en voi testata kun gcc ei suostu kääntämään c++aa)

Toni-S [29.04.2003 08:05:51]

#

eh? djgpp? jos sulla on djgpp asennettu oikein niin kylläpä se kääntää c++ kielisiäkin (gpp on komento muistaakseni)

Olli Vanhoja [05.02.2004 20:44:12]

#

Ei känny BC++ :-(
Call to undefined function 'sring'
Cannot convert 'int' to 'std::...
Undefined symbol 'numbers'
...

Olli Vanhoja [05.02.2004 20:49:14]

#

Saisko exenä?

Gary534 [08.05.2005 21:59:43]

#

koodi näyttää hienolta.


Sivun alkuun

Vastaus

Aihe on jo aika vanha, joten et voi enää vastata siihen.

Tietoa sivustosta