JackYF, если вам просто нужен код какого-нибудь консольного калькулятора, то могу предложить вот это:
| Код | // Calculator.cpp : Defines the entry point for the console application. //
#include "stdafx.h"
using namespace std;
vector<string> oper[3]; // Массив операций рассортированных на приоритеты
// Выделяет из строки лексему // s - исходный текст // i - номер символа с которого начинать сканирование bool Scanner(string &l,int &pr, string &s, bool reload, bool inPoliz) { bool flag = true, fl=true; static int i = 0; bool delim = false;
if(reload) i = 0;
l.clear(); while(flag) { if(l.empty() && s[i]==' ') ++i; // Игнорировать пробелы // Проверить не находятся ли они в начале выражения или после '(', тогда они будут знаком константы... if( s[i]=='+' || s[i]=='-') { if(i==0 || s[i-1]=='(' || (inPoliz && s[i+1]=='0' || s[i+1]=='1' || s[i+1]=='2' || s[i+1]=='3' || s[i+1]=='4' || s[i+1]=='5' || s[i+1]=='6' || s[i+1]=='7' || s[i+1]=='8' || s[i+1]=='9')) { l += s[i++]; fl = false; } } if( s[i]=='0' || s[i]=='1' || s[i]=='2' || s[i]=='3' || s[i]=='4' || s[i]=='5' || s[i]=='6' || s[i]=='7' || s[i]=='8' || s[i]=='9' || s[i]=='.' || s[i]==',') { fl = false; l += s[i]; if(s[i]=='.' || s[i]==',') if(delim) throw logic_error("Bad number format"); else delim = true; } else if(!fl) return false; if(fl) { l += s[i]; for(int j=0; j<3 && flag; j++) { vector<string>::iterator res = find(oper[j].begin(),oper[j].end(),l); if(res!=oper[j].end()) { flag = false; pr = j; } } } ++i; if(fl && flag && s[i]=='#') { l.clear(); throw logic_error("Unknown lexem"); // Ошибка - не найдена лексема } } return true; }
// Перевод выражения source в постфиксный вид. Результат помещается в dest void toPoliz(string &dest, string &source) { stack<pair<string,int> > mag; // Магазин bool flag = true; // Устанавливается в 0 при завершении или ошибке string lex; int pr; bool f = true;
dest.clear();
while(flag) { if(!Scanner(lex,pr,source,f,false)) // Операнд ? { // Да dest += lex + " "; } else { // Операция if(mag.empty()) { if(lex=="#") { flag = 0; } else { if(lex==")") { // Ошибка 1 throw logic_error("Bad parenthesis structure"); } else { mag.push(make_pair<string,int>(lex,pr)); } } } else { if(!pr) { mag.push(make_pair<string,int>(lex,0)); } else { while(!mag.empty() && pr<=mag.top().second) { dest += mag.top().first + " "; mag.pop(); } if(lex==")") { if(mag.top().first=="(") mag.pop(); else { vector<string>::iterator res = find(oper[0].begin(),oper[0].end(),mag.top().first); if(res!=oper[0].end()) // Функция есть в списке? { // Да, выводим в строку результата dest += mag.top().first + " "; mag.pop(); } else { // Ошибка 2 throw logic_error("Bad parenthesis structure"); } } } else { if(lex=="#") { if(mag.empty()) flag = 0; else { // Ошибка 3 throw logic_error("Bad parenthesis structure"); } } else mag.push(make_pair<string,int>(lex,pr)); } } } } f = false; } }
double CalcOper(double &o1, double &o2, string &op) { if(op=="sin(") return sin(o1); if(op=="cos(") return cos(o1); if(op=="tan(") return tan(o1); if(op=="log(") return log(o1); if(op=="exp(") return exp(o1); if(op=="sqrt(") return sqrt(o1); if(op=="+") return o1+o2; if(op=="-") return o1-o2; if(op=="*") return o1*o2; if(op=="/") { if(o2==0) throw logic_error("division by zero"); return o1/o2; } // Возведение в степень if(op=="^") { return pow(o1,o2); } }
double CalculatePoliz(string &source) { string elem; int i=0; bool f = true; int pr; double el, el1; stack<double> mag;
source += "#"; elem.clear();
while(elem!="#") { if(!Scanner(elem,pr,source,f,true)) { // Операнд mag.push(strtod(elem.c_str(),NULL)); } else if(elem!="#") { // Производим вычисления vector<string>::iterator res = find(oper[0].begin(),oper[0].end(),elem); if(res!=oper[0].end()) { // Унарная операция - вызов функции if(mag.empty()) { // Ошибка: лишний знак операции throw logic_error("Too many operators"); } el = mag.top(); mag.pop(); el = CalcOper(el,el,elem); mag.push(el); } else { // Бинарная операция if(mag.empty()) { // Ошибка лишний знак операции throw logic_error("Too many operators"); } el = mag.top(); mag.pop(); if(mag.empty()) { // Ошибка лишний знак операции throw logic_error("Too many operators"); } el1 = mag.top(); mag.pop(); el = CalcOper(el1,el,elem); mag.push(el); } } f = false; } el = mag.top(); mag.pop(); if(!mag.empty()) { // Ошибка: лишний операнд throw logic_error("Too many operands"); } return el; }
void InitializeLexems(void) { oper[0].push_back("("); oper[0].push_back("cos("); oper[0].push_back("sin("); oper[0].push_back("log("); oper[0].push_back("tan("); oper[0].push_back("sqrt("); oper[0].push_back("exp(");
oper[1].push_back("+"); oper[1].push_back("-"); oper[1].push_back(")"); oper[1].push_back("#");
oper[2].push_back("*"); oper[2].push_back("/"); oper[2].push_back("^"); }
int _tmain(int argc, _TCHAR* argv[]) { string source, dest;
InitializeLexems();
cout << "Input expression: "; cin >> source; source += '#'; try{ toPoliz(dest,source); //cout << dest; double res = CalculatePoliz(dest); cout << "The result: "<< res << endl; } catch(logic_error er) { cout << er.what(); } catch(...) { cout << "unkown error"; } getch(); return 0; }
|
Функция Scanner там выполнена из рук вон плохо (хотя и работает), остальное нормально. Моя программка, хотя алгоритм, конечно же не сам придумывал |