Предыдущий пост -
Следующий пост -

Модификация класса выражений для работы с переменными

Рубрика: C++, Дата: 11 March, 2013, Автор:
Tags:

Модифицируйте класс выражений ( http://www.kselax.ru/2013/03/klass-dlya-prostyx-arifmeticheskix-vyrazhenij/) таким образом, чтобы он мог обрабатывать переменные и операцию присваивания. Воспользуйтесь классом таблицы символов из (http://www.kselax.ru/2013/03/klass-tablicy-simvolov-i-klass-ee-elementov/)

Да тяжелая задачка фиг его знает чо делать, с чего начать. Добавить можно объект или указатель на класс таблица символов. Лучше указатель на класс таблица символов. Ну добавим мы ну и чо? Ну фиг его знает, дальше можно например сканировать выражения. Например такого типа. PI=3.14. От есть константа или переменная, то мы ее добавляем в таблицу символов. Наверно добавим функцию addPer() которая будет добавлять переменные. А дальше что? А дальше усовершенствуем конструктор – перевод в постфикс, если встретим константу, то осуществим поиск в таблице символов, и если найдем переменную, то заменим ее если нет, то выход из программы. Да задачка вроде более менее ясна, ничего другого добавлять или усовершенствовать не будем, так что вперед.

Немножко помучившись от, что у меня получилось.

Файл Expr2.h:

//ob69vlenie klacca Expr1.h
#ifndef EXPR1_H
#define EXPR1_H
#include <string>
using std::string;

#include "Table.h"
class Table;

struct Node
{
	Node(string a)
	:nextPtr(0),val(a)
	{
		//pyctoi konctryktor
	}
	string val;//znachenie
	Node* nextPtr;
};

class Expr1
{
	string infix;
	string postfix[100];
	Node* firstPtr;//ykazatel6 na pervui element
	Table* T;//ykazatel6 na tablicy cimvolov
public:
	//konctryktor
	Expr1(string a);
	
	//podcchituvaet vurajenie
	int eval();
	
	//dobavit6 cimvol v tablic6
	void addPer(string s,int a);
	
	//vuvod camogo vurajeni9
	void print();
	
	//zapolnit6 ctek 
	void addS();
	
private:	
	//dobavit6 v konec cpicka
	void add(string a);
	
	//dobavit6 helper
	void addHelper(string &a,Node** ptr);
	
	//vuvod cpicka
	void printS();
	
	//vuvod cpicka helper
	void printSHelper(Node* ptr);
	
	//ydalit6 poclednii element
	void delLast(string&);
	
	//ydalit6 helper //peredaem ykazatel6 na ykazatel6
	void delLastHelper(Node**,string&);
	
	//perevod chicla v ctroky int
	string strNum(int n);

};

#endif

Файл Expr2.cpp

//opredelenie klacca Expr1
#include <cctype>
using std::isdigit;
using std::isalpha;
#include <cstdlib>
using std::exit;
using std::atoi;
#include <iostream>
using std::cout;
using std::endl;

#include "Expr2.h"

//konctryktor
Expr1::Expr1(string a)
:firstPtr(0),infix(a)
{
	//inicializaci9 tablici cimvolov
	T=new Table();
	
	//inicializaci9 postfix
	for(int i=0;i<100;i++)
	{
		postfix[i]="";
	}
	//addS();	
}

//zapolnit6 ctek 
void Expr1::addS()
{
	//perevod v postfix
	//cout <<"perevod v poctfix "<<a<<endl;
	//1.zatolknyt6 v ctek levyyu ckobky
	add("(");
	//printS();
	//exit(1);
	//2. dobavili pravyyu ckobky vkonec
	infix+=')';
	//cout <<"infix= "<<infix<<endl;
	//exit(1);
	int count=0;
	for(int i=0;i<infix.length();i++)
	{
		if(infix[i]==' ')
			continue;
		//cout <<"______________i= "<<i<<endl;
		//cout <<"infix[i]= "<<infix[i]<<endl;
		//ecli cifra, kopirovat6 ego v cledychii element poctfix
		if(isdigit(infix[i]))
		{
			//printS();
			//cout <<"chiclo "<<infix[i]<<endl;
			postfix[count]="";	
			//cout <<postfix[count-1]<<endl;
			postfix[count]+=infix[i];
			for(int j=i+1;j<infix.length();j++)
			{
				if(isdigit(infix[j]))
				{
					postfix[count]+=infix[j];
					i=j;//izmen9em i
				}
				else 
					break;
			}
			//cout <<"postfix[count]= "<<postfix[count]<<endl;
			//printS();
			//exit(1);
			++count;
		}
		//ecli cimvol bykva ot a-z ili A-Z
		else if(isalpha(infix[i]))
		{
			postfix[count]="";
			//cout <<"literal= "<<infix[i]<<endl;
			//cout <<"i= "<<i<<endl;
			string s="";
			s+=infix[i];
			for(int j=i+1;isalpha(infix[j]);j++)
			{
				
				s+=infix[j];
				i=j;
			}
			int n;
			n=T->poick(s);
			//cout <<"n= "<<n<<endl;
			//add(strNum(n));
			postfix[count++]=strNum(n);
			//exit(1);
		}
		
		//ecli leva9 ckobka, zatalknyt6 ee v ctek
		else if(infix[i]=='(')
		{
			//cout <<"leva9 ckobra"<<endl;
			add("(");
			//printS();
			//exit(1);
		}
		
		//ecli znak operacii
		else if(!isdigit(infix[i])&&infix[i]!=')'&&infix[i]!='(')
		{	
			//cout <<"znak operacii"<<endl;
			//vutalkivat6 znaki operacii iz cteka ecli oni tam ect6
			//cout <<"pered"<<endl;
			//cout <<"i= "<<i<<endl;
			//printS();
			string s="";
			delLast(s);
			if(!isdigit(s[0])&&s[0]!='('&&s[0]!=')')//ect6 znaki operacii
			{
				//cout <<"v cteke znak operacii"<<endl;
				//cout <<"s= "<<s<<endl;
				//izvlekaem znaki operacii iz cteka i cravnivaem prioritet
				//poka prioritet raven ili bol6we pomechaem v postfix
				/*for(int k=0;k<4;k++)
					cout <<"postfix= "<<postfix[k]<<endl;*/
				//cout <<"infix[i]= "<<infix[i]<<endl;
				//prover9em prioritet
				if(infix[i]=='-'||infix[i]=='+')//minimal6nui prioritet
				{
					//cout <<"minimum prioritet"<<endl;
					while(s[0]=='+'||s[0]=='-'||s[0]=='*'||s[0]=='/')
					{
						postfix[count++]=s;
						s="";
						//cout <<"s= "<<s<<endl;
						delLast(s);
					}
					add(s);
					string sss="";
					sss+=infix[i];
					add(sss);
					//printS();
					//exit(1);
					
					//vce pomechaem
				}
				else if(infix[i]=='/'||infix[i]=='*')
				{
					//cout <<"ecli * ili /"<<endl;
					if(s[i]=='*'||s[i]=='/')
					{
						//cout <<"dobavl9em * ili /"<<endl;
						postfix[count++]=s;
					}
					else
					{
						add(s);
						string sss="";
						sss+=infix[i];
						add(sss);	
					}
				}
				//exit(1);
			}
			else//nety znakov operacii
			{
				//cout <<"ne znak operacii v cteke"<<endl;
				add(s);//vctavl9em obratno
				string s1="";
				s1+=infix[i];
				add(s1);
				//printS();
			}
			
			
			//exit(1);
		}//konec ecli znak operacii
		
		//prava9 ckobka
		else if(infix[i]==')')
		{
			//cout <<"prava9 ckobka"<<endl;
			//vutalkivat6 znaki operacii iz cteka i pomechat6 ix v postfix
			//poka ne po9vitc9 leva9 ckobka
			string s="";//element dl9 izvlecheni9
			delLast(s);
			while(s[0]!='(')
			{
				//cout <<"s= "<<s<<endl;
				postfix[count++]+=s;
				delLast(s);
			}
		}	
	}
}

//podcchituvaet vurajenie
int Expr1::eval()
{
	//vuchiclit6 poctfix vurajenie.
	int res;
	for(int i=0;postfix[i]!="";i++)
	{
		//cout <<i<<' '<<postfix[i]<<endl;
		//ecli tekychii cimvol cifra, to zatolknyt6 ee znachenie v ctek
		if(isdigit(postfix[i][0]))
		{
			//cout <<"cifra"<<endl;
			add(postfix[i]);//zatalkivaem v ctek
			//printS();
			//exit(1);
		}
		//ecli znak operacii vutolnyt6 dva verxnix elementa iz cteka
		//v x i y i vuchiclit6 y operaci9 x i op9t6 zatolknyt6 v ctek
		else
		{
			//cout <<"znak operacii"<<endl;
			//cout <<postfix[i]<<endl;
			string x,y;
			delLast(y);
			delLast(x);
			//cout <<"ddd "<<atoi(x.data())<<' '<<atoi(y.data())<<endl;
			
			if(postfix[i][0]=='/')
			{	
				//cout <<"/"<<endl;
				res=atoi(x.data())/atoi(y.data());
			}
			else if(postfix[i][0]=='*')
			{
				//cout <<"*"<<endl;
				res=atoi(x.data())*atoi(y.data());
			}
			else if(postfix[i][0]=='-')
			{
				//cout <<"-"<<endl;
				res=atoi(x.data())-atoi(y.data());
			}
			else if(postfix[i][0]=='+')
			{
				//cout <<"+"<<endl;
				res=atoi(x.data())+atoi(y.data());
			}
			//cout <<res<<endl;
			add(strNum(res));
			//printS();
			//exit(1);
		}
	}
	return res;
	//VUCHICLENIE POSTFIX VURAGENI9
	//1.dobavit6 NULL v konec postfix. vurajeni9 ny on i tak tam ect6
	//exit(1);
}

//vuvod camogo vurajeni9
void Expr1::print()
{
	cout <<"infix= "<<infix<<endl;
	
	for(int i=0;postfix[i]!="";i++)
	{
		cout <<i<<' '<<postfix[i]<<endl;
	}
	//string postfix[100];
}

//dobavit6 v konec cpicka
void Expr1::add(string a)
{
	if(firstPtr==0)
	{
		//cout <<"cpicok pyct"<<endl;
		firstPtr=new Node(a);
	}
	else
	{
		//cout <<"cpicok ne pyct"<<endl;
		addHelper(a,&firstPtr->nextPtr);
	}
}

//dobavit6 helper
void Expr1::addHelper(string &a, Node** ptr)
{
	if(*ptr==0)
	{
		//cout <<"pycto"<<endl;
		*ptr=new Node(a);
	}
	else
	{
		//cout <<"req"<<endl;
		addHelper(a,&(*ptr)->nextPtr);
	}
}

//vuvod cpicka
void Expr1::printS()
{
	if(firstPtr==0)
	{
		cout <<"cpicok pyct"<<endl;
	}
	else
	{
		cout <<firstPtr->val<<endl;
		printSHelper(firstPtr->nextPtr);
	}
}

//vuvod cpicka helper
void Expr1::printSHelper(Node* ptr)
{
	if(ptr!=0)
	{
		cout <<ptr->val<<endl;
		printSHelper(ptr->nextPtr);
	}
}

//ydalit6 poclednii element
void Expr1::delLast(string& a)
{
	if(firstPtr==0)
	{
		cout <<"cpicok pyct"<<endl;
	}
	else
	{
		delLastHelper(&firstPtr,a);
	}
}

//ydalit6 helper
void Expr1::delLastHelper(Node** ptr,string& a)
{
	if((*ptr)->nextPtr==0)//naiden poclednii element
	{
		//cout <<"poclednii element"<<endl;
		a=(*ptr)->val;//znachenie elementa
		Node* temp=*ptr;
		*ptr=0;
		delete temp;//vucvobojdaem pam9t6
	}
	else
	{
		//cout <<"req vuzov"<<endl;
		delLastHelper(&(*ptr)->nextPtr,a);//req vuzov
	}
}

//perevod chicla v ctroky int
string Expr1::strNum(int n)
{
    int mass[13]={0};
    for(int i=0;n!=0;n=n/10,i++)
    {
        int r=n%10;
        //cout <<r<<endl;
        mass[i]=r;
    }
    string s="";
    int i=12;
    for(;mass[i]==0;i--);
    for(;i>=0;i--)
    {
        s+=(mass[i]+'0');
        //cout <<mass[i]<<endl;
    }
    //cout <<s<<endl;
    return s;
}

//dobavit6 cimvol v tablic6
void Expr1::addPer(string s,int a)
{
	cout <<s<<' '<<a<<endl;
	T->addSim(s,a);
	T->print();
	cout <<"T->poick(\"PI\")= "<<T->poick("PI")<<endl;
	//exit(1);
}

Файл Table.h:

//declaration Table.h
#ifndef TABLE_H
#define TABLE_H
#include <string>
using std::string;

//tablica cimvolov (yzel)
struct Simbol
{
	Simbol(string a,int b)
	:val(a),nextPtr(0),znach(b)
	{
		//pyctoi konctryktor
	}
	string val;
	int znach;
	Simbol* nextPtr;
};

class Table
{
	Simbol* firstPtr;
public:
	//konctryktor
	Table();
	
	//dobavit6 cimvol
	void addSim(string s,int b);
	
	//vuvecti tablicy
	void print();
	
	//vuvod elementa po znacheniyu ecli nety to return 0;
	int poick(string s);
private:
	//poick helper
	int poickHelper(Simbol** ptr,string& s);
	//dobavit6 cimvol helper //peredaem ykazatel6 na ykazatel6 dl9 izmeneni9
	void addSimHelper(Simbol** ptr,string& s,int& b);
	//vuvecti cimvol
	void printHelper(Simbol* ptr);
};

#endif

Файл Table.cpp:

//definichin klacca Table
#include <cstdlib>
using std::exit;
#include <iostream>
using std::cout;
using std::endl;

#include "Table.h"

//konctryktor
Table::Table()
:firstPtr(0)//inicializaci9
{
	//pyctoi konctryktor
}

//dobavit6 cimvol
void Table::addSim(string s,int b)
{
	if(firstPtr==0)//pycta9 tablica
	{
		cout <<"pycta9 tablica"<<endl;
		firstPtr=new Simbol(s,b);
	}
	else
	{
		cout <<"ne pycta9 tablica"<<endl;
		addSimHelper(&firstPtr->nextPtr,s,b);
		
	}
}

//dobavit6 cimvol helper
void Table::addSimHelper(Simbol** ptr, string &s,int& b)
{
	if(*ptr==0)
	{
		*ptr=new Simbol(s,b);
	}
	else //ne poclednii element
	{
		addSimHelper(&(*ptr)->nextPtr,s,b);
	}
}

//vuvecti tablicy
void Table::print()
{
	if(firstPtr==0)
	{
		cout <<"Table empty"<<endl;
	}
	else
	{
		cout <<firstPtr->val<<' '<<firstPtr->znach<<endl;
		printHelper(firstPtr->nextPtr);
	}
}

//vuvecti cimvol
void Table::printHelper(Simbol* ptr)
{
	if(ptr!=0)
	{
		cout <<ptr->val<<' '<<ptr->znach<<endl;
		printHelper(ptr->nextPtr);
	}
}

//vuvod elementa po znacheniyu ecli nety to return 0;
int Table::poick(string s)
{
	cout <<"s= "<<s<<endl;
	if(firstPtr==0)
	{
		cout <<"cpicok pyct"<<endl;
	}
	else
	{
		cout <<"ne pyct cpicok"<<endl;
		if(firstPtr->val==s)
		{
			return firstPtr->znach;
		}
		else
			return poickHelper(&firstPtr->nextPtr, s);
	}
	exit(1);
}

//poick helper
int Table::poickHelper(Simbol** ptr,string& s)
{
	int res;
	if(*ptr!=0)
	{
		if((*ptr)->val==s)
		{
			res=(*ptr)->znach;
		}
		else
			return poickHelper(&(*ptr)->nextPtr,s);
	}
	
	return res;
}

И файл самой main()

//modificiryite klacc chtobu on mog obrabatuvat6 operaciyu pricvaivani9
//klacc dl9 analizirovani9 pechati i xraneni9 proctux arifmeticheckix vurajenii
#include <iostream>
using std::cout;
using std::endl;

#include "Expr2.h"
//#include "Table.cpp"

int main()
{
	Expr1 a("(6 + 2 ) *5-8/4+PI+3+PI");//34-4+2-1 //31
	cout <<endl;
	a.addPer("PI",3);
	//perevod v postfix
	a.addS();
	a.print();
	cout <<endl;
	cout <<a.eval()<<endl;
	
	return 0;
}

Да, что я еще заметил, так это, то, что программку эту можно улучшать и улучшать, от например я использую целие значения, и у меня получается, что точность до целых чисел, данные теряются, десятые части, можно б было придумать, что нить, чтобы данные например были до сотых либо до десятых, сделать не int, а double. Да можно улучшать ее и улучшать.

Хотите улучшайте, я не буду мне уже надоело ее просто делать.

rss