Коды классов, функций и обработчиков событий
Сохраните модуль под именем LR_5, а проект – под именем PR_LR_5.
Достаточно полное представление об интерфейсе можно получить из рис.5.1, рис.5.2 и заголовочного файла LR_5.h (см. ниже). Отметим лишь, что для компонентов Label1,..,8 и Edit1,..,8 установлен шрифт Font = жирный, размер 10, а сконструированное меню представлено на рис.5.2.
Все функции – для работы со стеком и записями арифметических выражений, а также данные для функций поместим в класс Stack, содержание которого представлено на рис.5.3.
Для размещения класса в проекте использован модуль, не связанный с формой. Чтобы создать такой модуль, нужно выполнить команду Файл/Новый/Другое… и открывшемся окне Новые элементы на странице Новый щелкнуть на пиктограмме Модуль. Модулю дано имя f_5. В заголовочном файле этого модуля f_5.hнаходятся объявления структурных типов для стеков и класса, а в файле реализации модуля f_5.cpp – реализация класса (определения функций-элементов класса).
Рис.5.1 – форма по окончании проектирования
Рис.5.2 - видна структура меню Рис.5.3 - структурные типы и классы
Заголовочный файл LR_5.h модуля LR_5
//---------------------------------------------------------------------------
#ifndef LR_5H
#define LR_5H
//---------------------------------------------------------------------------
#include <Classes.hpp>
#include <Controls.hpp>
#include <StdCtrls.hpp>
#include <Forms.hpp>
#include <Menus.hpp>
#include <ActnList.hpp>
#include <ImgList.hpp>
#include <ComCtrls.hpp>
#include <ToolWin.hpp>
//---------------------------------------------------------------------------
class TForm1 : public TForm
{
__published: // IDE-managed Components
TLabel *Label1;
TLabel *Label2;
TEdit *Edit1;
TEdit *Edit2;
TLabel *Label3;
TEdit *Edit3;
TLabel *Label4;
TEdit *Edit4;
TLabel *Label5;
TEdit *Edit5;
TLabel *Label6;
TEdit *Edit6;
TLabel *Label7;
TEdit *Edit7;
TLabel *Label8;
TEdit *Edit8;
TActionList *ActionList1;
TImageList *ImageList1;
TAction *ANew;
TAction *AMod;
TAction *ARun;
TAction *AExit;
TMainMenu *MainMenu1;
TMenuItem *N1;
TMenuItem *N2;
TMenuItem *N3;
TMenuItem *N4;
TMenuItem *N5;
TMenuItem *N6;
TToolBar *ToolBar1;
TToolButton *ToolButton1;
TToolButton *ToolButton2;
TToolButton *ToolButton3;
TToolButton *ToolButton4;
void __fastcall FormCreate(TObject *Sender);
void __fastcall N2Click(TObject *Sender);
void __fastcall N3Click(TObject *Sender);
void __fastcall N4Click(TObject *Sender);
void __fastcall N6Click(TObject *Sender);
private: // User declarations
public: // User declarations
__fastcall TForm1(TComponent* Owner);
};
//---------------------------------------------------------------------------
extern PACKAGE TForm1 *Form1;
//---------------------------------------------------------------------------
#endif
Заголовочный файл f_5.hмодуля f_5
//---------------------------------------------------------------------------
#ifndef f_5H
#define f_5H
//---------------------------------------------------------------------------
//структура для элемента стека операций
struct Node_op
{
char c;
Node_op* p;
};
//---------------------------------------------------------------------------
//структура для элемента стека чисел
struct Node_num
{
float c;
Node_num* p;
};
//---------------------------------------------------------------------------
//перечисление для контроля ошибок при вводе
typedef enum {all_true=1, bad_operands, few_brackets, much_brackets,
few_operands, few_operators}errors;
//---------------------------------------------------------------------------
class Stack
{
public:
char* s; //исходная строка
char* sv; //вспомогательная строка
Node_op* t1; //указатель на вершину стека операций
Node_num* t2; //указатель на вершину стека чисел
void Stack_init(); //задание параметров объекта класса
void check(); //проверка корректности введенного выражения
void revers_before(); //реверсирование входной строки
void revers_after(); //реверсирование постфиксной записи
void bspaces(); //расстановка пробелов в строке
void postfix(); //преобразование в постфиксную запись
float calc(); //вычисление выражения в постфиксной записи
void out_err_code(); //вывод сообщения
errors err_code; //код ошибки
~Stack(); //деструктор класса
private:
int prioritet_stack();//определение приоритета оператора на вершине //стека
bool operand_true(char c); //проверка корректности операнда
void first1(char c); //создание стека операций
void push1(char c); //добавление в стек операций
char pop1(); //выталкивание из стека операций
void first2(float c); //создание стека чисел
void push2(float c); //добавление в стек чисел
float pop2(); //выталкивание из стека чисел
};
#endif
Файл реализации f_5.cppмодуля f_5
//---------------------------------------------------------------------------
#pragma hdrstop
#include "f_5.h"
#include "string.h"
#include "stdlib.h"
//---------------------------------------------------------------------------
#pragma package(smart_init)
void Stack::Stack_init()
{
t1=0;
t2=0;
s=new char[100];
sv=new char[100];
err_code=all_true;
}
//-------------------------------------------------------------------------
Stack::~Stack()
{
delete[] s;
delete[] sv;
}
//---------------------------------------------------------------------------
void Stack::first1(char c)
{
Node_op* pv=new Node_op;
pv->c=c;
pv->p=0;
t1=pv;
}
//---------------------------------------------------------------------------
void Stack::push1(char c)
{
Node_op* pv=new Node_op;
pv->c=c;
pv->p=t1;
t1=pv;
}
//--------------------------------------------------------------------------
char Stack::pop1()
{
char z=t1->c;
Node_op* pv=t1;
t1=t1->p;
delete pv;
return z;
}
//--------------------------------------------------------------------------
void Stack::first2(float c)
{
Node_num* pv=new Node_num;
pv->c=c;
pv->p=0;
t2=pv;
}
//---------------------------------------------------------------------------
void Stack::push2(float c)
{
Node_num* pv=new Node_num;
pv->c=c;
pv->p=t2;
t2=pv;
}
//--------------------------------------------------------------------------
float Stack::pop2()
{
float z=t2->c;
Node_num* pv=t2;
t2=t2->p;
delete pv;
return z;
}
//--------------------------------------------------------------------------
bool Stack:: operand_true(char c)
{
if(c>='0'&&c<='9'||c>='A'&&c<='Z'||
c>='a'&&c<='z'||c=='.') return true;
else return false;
}
//---------------------------------------------------------------------------
int Stack::prioritet_stack()
{
if(t1->c=='(')return 3;
if(t1->c=='+'||t1->c=='-')return 1;
return 2;
}
//---------------------------------------------------------------------------
void Stack::check()
{
int sk=0;
int rang=0;
int l=strlen(s);
int i=0;
if(s[0]==')')
{err_code=much_brackets; return;}
if(s[0]=='*'||s[0]=='/')
{err_code=few_operands; return;}
for(i; i<l; i++)
{
if(s[i]=='(')
{
if(i>0&&operand_true(s[i-1]))
{err_code=few_operators; return;}
if(s[i+1]=='*'||s[i+1]=='/'||s[i+1]==')')
{err_code=few_operands; return;}
sk++; continue;
}
if(s[i]==')')
{ if((i>0)&&(s[i-1]=='*'||s[i-1]=='+'||s[i-1]=='-'||s[i-1]=='/'))
{err_code=few_operands; return;}
if(operand_true(s[i+1])||s[i+1]=='(')
{err_code=few_operators; return;}
sk--; continue;
}
if(s[i]=='*'||s[i]=='/'||s[i]=='+'||s[i]=='-')
{rang++; continue;}
if(operand_true(s[i]))
{
while (operand_true(s[++i]));
i--;
rang--;
}
else
{
err_code=bad_operands;
return;
}
}
s[i]='\0';
if(rang>-1) {err_code=few_operands; return;}
if(rang<-1) {err_code=few_operators; return;}
if(sk>0) {err_code=few_brackets; return;}
if(sk<0) {err_code=much_brackets; return;}
}
//--------------------------------------------------------------------------
void Stack::revers_before()
{
int l=strlen(s);
int i=l-1;
int j=0;
for(i;i>=0;i--)
{
if(s[i]=='(') sv[j++]=')';
else if(s[i]==')')sv[j++]='(';
else sv[j++]=s[i];
}
sv[j]='\0';
strcpy(s,sv);
//а теперь реверсируем операнды
int k;
for (i=0;i<l;i++)
{
if(operand_true(s[i]))
{
k=1;
while (operand_true(s[++i]))k++;
i--;
for(j=0;j<k;j++)
{s[i+1-k+j]=sv[i-j];}
}
}
}
//--------------------------------------------------------------------------
void Stack::revers_after()
{
int i=0;
int l=strlen(s);
int j=l-1;
for(j;j>=0;j--) sv[i++]=s[j];
sv[i]='\0';
strcpy(s,sv);
// а теперь реверсируем операнды
int k;
for (i=0;i<l;i++)
{
if(operand_true(s[i]))
{
k=1;
while (operand_true(s[++i]))k++;
i--;
for(j=0;j<k;j++)
{s[i+1-k+j]=sv[i-j];}
}
}
}
//-------------------------------------------------------------------------
void Stack::bspaces()
{
int l=strlen(s);
int i=0,j=0;
for(i;i<l;i++)
{
if(s[i]>='('&&s[i]<='+'||s[i]=='-'||s[i]=='/')
{ sv[j++]=s[i]; sv[j++]=' '; continue;}
else
{
sv[j++]=s[i];
while(operand_true(s[++i])==1&&s[i]!='\0')
sv[j++]=s[i];
sv[j++]=' ';
}
i--;
}
sv[j]='\0';
}
//--------------------------------------------------------------------------
void Stack::postfix()
{
int i=0,j=0,pr=0;
int l=strlen(s);
for(i;i<l;i++)
{
if(s[i]==' ') {sv[j++]=s[i]; continue;}
if(s[i]>='('&&s[i]<='+'||s[i]=='-'||s[i]=='/')
{
switch(s[i])
{
case '(':
{
if(!t1) {first1(s[i]);}
else {push1(s[i]);}
break;
}
case '*':
case '/':
{
if(!t1) {first1(s[i]); break;}
pr=prioritet_stack();
if(pr==3||pr==1) {push1(s[i]); break;}
if(t1->c=='/') sv[j++]=pop1();
if(t1) {push1(s[i]); break;}
else {first1(s[i]); break;}
}
case '+':
case '-':
{
if(!t1) {first1(s[i]); break;}
pr=prioritet_stack();
if(pr==3) {push1(s[i]); break;}
else
{
while(pr<3&&t1)
{
sv[j++]=pop1();
if(t1) pr=prioritet_stack();
}
}
if(t1) {push1(s[i]); break;}
else {first1(s[i]); break;}
}
case ')':
{
pr=prioritet_stack();
while(pr!=3)
{
sv[j++]=pop1();
pr=prioritet_stack();
}
sv[j]= pop1();
}
}
}
else {sv[j++]=s[i]; continue;}
}
if(t1){ while(t1) sv[j++]=pop1();}
sv[j]='\0';
strcpy(s,sv);
}
//-------------------------------------------------------------------------
float Stack::calc()
{
int i=0,j=0,l=strlen(s);
char sc[10];
float a,b;
for(i;i<l;i++)
{
if(s[i]==' ') continue;
else
if(s[i]=='+'||s[i]=='-'||s[i]=='*'||s[i]=='/')
{
a=pop2();
b=pop2();
switch(s[i])
{
case '+': {a=a+b; break;}
case '-': {a=b-a; break;}
case '*': {a=a*b; break;}
case '/': {a=b/a; break;}
}
if(!t2) {first2(a); }
else {push2(a); }
}
else
{
while(operand_true(s[i])&&s[i]!='\0')
{
sc[j++]=s[i];
i++;
}
sc[j]='\0';
a=atof(sc);
j=0;
if(!t2) {first2(a);}
else {push2(a); }
}
}
return pop2();
}
//-------------------------------------------------------------------------
В файле реализации LR_5.cpp модуля LR_5 разместим обработчики событий – создание формы и щелчки на разделах меню Новое, Преобразование, Преобразование и вычисление, Выход с именами соответственно FormCreate, N2Click, N3Click, N4Click, N6Click. Заметим, что обработчик FormCreate можно вызвать двойным щелчком на форме.
Файл реализации LR_5.cpp модуля LR_5
//---------------------------------------------------------------------------
#include <vcl.h>
#pragma hdrstop
#include "LR_5.h"
#include "f_5.h"
//---------------------------------------------------------------------------
#pragma package(smart_init)
#pragma resource "*.dfm"
TForm1 *Form1;
//---------------------------------------------------------------------------
AnsiString
S1="В выражении есть неверные операнды! Проверьте правильность записи.",
S2="В выражении не хватает скобки! Проверьте правильность записи.",
S3="В выражении лишние скобки! Проверьте правильность записи.",
S4="В выражении недостаточно операндов! Проверьте правильность записи.",
S5="В выражении недостаточно знаков операций! Проверьте правильность записи.";
//---------------------------------------------------------------------------
void Stack::out_err_code()
{ switch(err_code)
{
case bad_operands: {ShowMessage(S1); break;}
case few_brackets: {ShowMessage(S2); break;}
case much_brackets: {ShowMessage(S3); break;}
case few_operands: {ShowMessage(S4); break;}
case few_operators: {ShowMessage(S5); break;}
};
}
//---------------------------------------------------------------------------
__fastcall TForm1::TForm1(TComponent* Owner)
: TForm(Owner)
{
}
//---------------------------------------------------------------------------
Stack S;
void __fastcall TForm1::FormCreate(TObject *Sender)
{
Edit1->Text="";
Edit2->Text="";
Edit3->Text="";
Edit4->Text="";
Edit5->Text="";
Edit6->Text="";
Edit7->Text="";
Edit8->Text="";
}
//--------------------------------------------------------------------------
void __fastcall TForm1::N2Click(TObject *Sender)
{
Edit1->Text="";
Edit2->Text="";
Edit3->Text="";
Edit4->Text="";
Edit5->Text="";
Edit6->Text="";
Edit7->Text="";
Edit8->Text="";
Edit1->SetFocus();
}
//---------------------------------------------------------------------------
void __fastcall TForm1::N3Click(TObject *Sender)
{
Edit2->Text="";
Edit3->Text="";
Edit4->Text="";
Edit5->Text="";
Edit6->Text="";
Edit7->Text="";
Edit8->Text="";
S.Stack_init();
S.s=(Edit1->Text+'\0'+'\0').c_str();
S.check();
if(S.err_code==all_true)
{
Edit2->Text=S.s;
S.bspaces();
S.s=S.sv;
Edit5->Text=S.s;
S.postfix();
Edit3->Text=S.s;
S.s=(Edit5->Text+'\0'+'\0'+'\0').c_str();
S.revers_before();
Edit6->Text=S.s;
S.postfix();
Edit7->Text=S.s;
S.revers_after();
Edit4->Text=S.s;
}
else
S.out_err_code();
}
//---------------------------------------------------------------------------
void __fastcall TForm1::N4Click(TObject *Sender)
{
Edit2->Text="";
Edit3->Text="";
Edit4->Text="";
Edit5->Text="";
Edit6->Text="";
Edit7->Text="";
Edit8->Text="";
S.Stack_init();
S.s=(Edit1->Text+'\0'+'\0').c_str();
S.check();
if(S.err_code==all_true)
{
Edit2->Text=S.s;
S.bspaces();
S.s=S.sv;
Edit5->Text=S.s;
S.postfix();
Edit3->Text=S.s;
S.s=(Edit5->Text+'\0'+'\0'+'\0').c_str();
S.revers_before();
Edit6->Text=S.s;
S.postfix();
Edit7->Text=S.s;
S.revers_after();
Edit4->Text=S.s;
S.s=(Edit3->Text+'\0'+'\0'+'\0').c_str();
float result=S.calc();
Edit8->Text=FloatToStr(result);
}
else
S.out_err_code();
}
//---------------------------------------------------------------------------
void __fastcall TForm1::N6Click(TObject *Sender)
{
exit(0);
}
//---------------------------------------------------------------------------
Подробно остановимся на использовании новых интерфейсных компонентов среды:ImageList – список изображений, ActionList - диспетчер действий, ToolBar – инструментальная панель. Эти компоненты необходимы в технологии программирования, использующей диспетчеризацию действий.
Здесь программирование начинается с составления списка действий, которые будут доступны пользователю через разделы меню, инструментальные панели, кнопки и другие элементы управления. При программировании этот список реализуется в данном случае компонентомActionList, обеспечивающим диспетчеризацию действий. Редактор диспетчера действийActionList позволяет сформировать список действий, написать обработчики (если их еще нет), выполняющие задуманные действия, задать основные свойства будущих интерфейсных элементов – пиктограммы, надписи, быстрые кнопки, тексты подсказок и т.п.
После того, как список действий создан, формируют полосы действий. Это полосы, на которых располагаются интерфейсные компоненты действий – полоса главного меню и инструментальные панели. В нашем случае – полоса главного меню уже создана. При использовании диспетчера действийActionList полосы действий добавляют на форму в виде отдельных компонентов, создают на них инициаторы действий (разделы меню, быстрые кнопки), а затем связывают инициаторы с соответствующими действиями из списка диспетчера действийActionList. При таком связывании свойства, заложенные в действия, автоматически передаются интерфейсным компонентам.
Интерфейсные компоненты действий обычно должны содержать поясняющие их изображения. Изображения собираются в списке изображений – компоненте ImageList. Для нестандартных действий (наш случай) изображения загружаются в ImageListпользователем. А для стандартных действий они загружаются автоматически по мере формирования списка в диспетчере действийActionList.
Дата добавления: 2020-10-14; просмотров: 352;