Модераторы: Poseidon
  

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> Двоичное дерево. Помогите разобраться. Нужна скорая помощь!!! 
:(
    Опции темы
Joker07
Дата 17.6.2006, 10:45 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 40
Регистрация: 17.6.2006

Репутация: нет
Всего: нет



 Привет люди!!! Помогите разобраться в программке. Ее задача – построение двоичного дерева для заданного арифметического выражения. Т.е. пользователь вводит выражение, и оно представляется в памяти в виде двоичного дерева.
Добавьте пож-та комментарии к указанным строчкам и поправьте мои, если необходимо. Буду очень благодарен.
Код программы:
Код

type
TOperandStyle = (osNumber, osExpression); {что это и для чего?}

TOperand = class
private
FStyle: TOperandStyle; // что это за поле, для чего используется?
FValue: Extended; // что за поле, для чего?
FOperand1: TOperand; // это я так понял левое поддерево
FOperand2: TOperand; // правое поддерево
FAction: Char; {операция (+ - * / ) }
protected
function GetValue(): Extended;
{метод GetValue для чтения, но почему именно в pretected?}
public
property Value: Extended read GetValue write FValue;
{ создание свойства Value с методом чтения GetValue и методом записи FValue }

constructor Create(Expression: string); {конструктор выделяет память для объекта, Expression – это поле для выражения}

destructor Destroy(); override;
{освобождение памяти, но что такое override?}

end;

{ TOperand }

function TOperand.Getvalue(): Extended;
begin
if FStyle = osNumber then
Result := FValue
{для чего?}
else
case FAction of
'+': Result := FOperand1.Value + FOperand2.Value;
'-': Result := FOperand1.Value - FOperand2.Value;
'*': Result := FOperand1.Value * FOperand2.Value;
'/': Result := FOperand1.Value / FOperand2.Value;
{арифметические операции}

else
raise Exception.Create('Unknown action.'); {это что такое? что такое raise? }
end;
end;


constructor TOperand.Create(Expression: string);
var
Index: Integer;
{длина выражения}
BracketCount: Integer;
{если знак + или – вне скобок, BracketCount=0}
OperandExpression1, OperandExpression2: string;
{для чего?}
PassNumber: Integer;
{номер прохода: PassNumber=1, если идет + - , PassNumber=2, если * /}
Completed : Boolean;
{разбор выражения закончен, если Completed=true}
begin
inherited Create();
{ директива inherited вызывает конструктор родительского класса, зачем оно тут? }

FStyle := osNumber;
{что это, зачем?}
Expression := Trim(Expression);
{удаление пробелов}

if Expression[1] = '(' then
if Pos(')', Expression) = Length(Expression) then
Expression := Copy(Expression, 2, Length(Expression) - 2);
{если в начала выражения открывающаяся скобка и если закрывающаяся скобка в конце выражения – тогда копируем в Expression выражение без скобок. Внимание вопрос: почему Length(Expression)-2, а не Length(Expression)-1? }

Completed := False; {дерево не построено}
PassNumber := 1;

while (PassNumber <= 2) and not Completed do
begin
BracketCount := 0;
OperandExpression1 := '';
OperandExpression2 := '';
Index := Length(Expression);
{В Index заносим количество символов выражения}

while (Index > 0) and not Completed do
{пока длина выражения больше нуля и дерево не построено}
begin

case Expression[Index] of
')':
begin
Inc(BracketCount);
end;
{если в выражении есть закрывающаяся скобка, то увеличиваем BracketCount на единицу}

'(':
begin
Dec(BracketCount);
end;
{если в выражении есть открывающаяся скобка, то уменьшаем BracketCount на единицу}

'+', '-', '*', '/':
if (BracketCount = 0)
and ((Expression[Index] in ['+', '-']) or (PassNumber = 2)) then
{если в выражении есть + , - , * , / и если BracketCount равен нулю(т.е. количество закрывающихся и открывающихся скобок совпадает) и (зачем нужно Expression[Index] in ['+', '-']) или PassNumber равен 2}
begin
FStyle := osExpression;
{что и зачем?}
FOperand2 := TOperand.Create(OperandExpression2);
{строим правое поддерево: (а что создается то и как?) }
OperandExpression1 := Copy(Expression, 1, Index - 1);
{ Почему Index-1? }
FOperand1 := TOperand.Create(OperandExpression1);
{ строим левое поддерево: (что создается и как?}
FAction := Expression[Index];
{Заносим символ в FAction. Зачем?}
Completed := True;
{Дерево построено}
end;

end;

OperandExpression2 := Expression[Index] + OperandExpression2;
{Что, зачем и почему? Ничего я не пойму…}
Dec(Index);
{уменьшаем количество символов на единицу}

end; // while Index < Length(s) do

Inc(PassNumber);
{увеличиваем на единицу номер прохода}
end;

if FStyle = osNumber then
{это тут что делает?}
begin
FValue := StrToFloat(Expression);
{Преобразуем строку в вещественное число (Expession – это один символ?) и заносим поле FValue}
end;

end;

destructor TOperand.Destroy(); {освобождение памяти}
begin
if Assigned(FOperand1) then
FOperand1.Destroy();
if Assigned(FOperand2) then
FOperand2.Destroy();
{что значит Assigned?}
inherited;
{ директива inherited вызывает конструктор родительского класса, зачем оно тут? }
end;

procedure TForm1.Button1Click(Sender: TObject);
var
Operand: TOperand;
begin
Operand := TOperand.Create(Edit1.Text);

try
Edit2.Text := FloatToStr(Operand.Value);
except
on EZeroDivide do
begin
ShowMessage('На ноль делить нельзя!!!');
exit;
end;
{если при выполнении преобразования строки в вещественное число получится ошибка – вывести сообщение}

on EConvertError do
begin
ShowMessage(‘Нельзя вводить буквы!!!’);
exit;
end;
{а вот это сообщение почему-то не работает, выводит стандартное делфи-сообщение }

finally
{а вот тут не работает – показывает на finally и пишет: ‘end’ expected but ‘Finally’ found}
{что значит finally?}
Operand.Free();
{освобождение памяти}
end;
end;
 
PM MAIL   Вверх
Mailman
Дата 17.6.2006, 19:31 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 19
Регистрация: 6.6.2006

Репутация: нет
Всего: нет



Эээ. Не знаю. Лично мне очень лениво читать такой большой кусок кода без конкретного вопроса. Я думаю сначала очень желательно прочитать что-либо. На сколько я понял данный код выполняет построение выражения в виде дерева (бинарного - у каждого родителя 0,1 или 2 сына). По этой теме много написано и примеры в инете есть. Это ищи в графе "Способы разбора арифметического выражения".

1) посмотри на этом форуме в разделе алгоритмы, там наверняка уже была подобная тема
2) Почитай литературу в инете по этому поводу. 

ЗЫ Не советую читать Андрееву. Она очень хорошо пишет, но именно в этой теме у неё пример нерабочий (по крайней мере в моём тексте).

И да поможет тебе разобраться в этом поиск.

Добавлено @ 19:33 
Да, возник вопрос. Судя по твоим вопросам ты с программированием не очень дружишь... Задание пожалуй для тебя явно было сложновато. Почитай что-то по теме программирования в делфи! Поможет точно. По крайней мере в вопросах синтаксиса. 
PM MAIL   Вверх
Joker07
Дата 18.6.2006, 16:18 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 40
Регистрация: 17.6.2006

Репутация: нет
Всего: нет



А как ввести запрет на нажатие всех клавиш, кроме 0..9, - + . * ( ) ?
Вот я пишу так:
Код

procedure TForm2.Edit1KeyPress(Sender: TObject; var Key: Char);
begin
if (Key not in ['0'..'9']) then
  begin
    Key := #0;
    Beep;
  end;
end;

Остается добавить арифметические операции и скобки. 
PM MAIL   Вверх
Sunr1se
Дата 18.6.2006, 16:31 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Бывалый
*


Профиль
Группа: Участник
Сообщений: 193
Регистрация: 1.5.2006

Репутация: нет
Всего: 13



Код

procedure TForm1.Edit1KeyPress(Sender: TObject; var Key: Char);
begin
  if not (Key in ['0'..'9', '+', '-', '*', '.', '(', ')']) then
  begin
    Key := #0;
    Beep;
  end;
end;
  

Это сообщение отредактировал(а) Sunr1se - 18.6.2006, 16:32
--------------------
IRC-канал Винграда 
PM MAIL ICQ   Вверх
Guedda
Дата 18.6.2006, 16:52 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Подрывник
****


Профиль
Группа: Завсегдатай
Сообщений: 3137
Регистрация: 27.12.2005
Где: Ростов-на-Дону

Репутация: 6
Всего: 78



Хех... А зачем там Beep?  smile 
Код

procedure TForm1.Edit1KeyPress(Sender: TObject; var Key: Char);
begin
  if not (Key in ['0'..'9', '+', '-', '*', '.', '(', ')']) then
  begin
    Key := #0;
  end;
end;
 


--------------------
Ll 2
PM MAIL WWW ICQ Skype GTalk   Вверх
Sunr1se
Дата 18.6.2006, 16:59 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Бывалый
*


Профиль
Группа: Участник
Сообщений: 193
Регистрация: 1.5.2006

Репутация: нет
Всего: 13



Это входит в постановку задачи:

Цитата(Joker07 @  18.6.2006,  16:18 Найти цитируемый пост)

    Key := #0;
    Beep;

smile 
--------------------
IRC-канал Винграда 
PM MAIL ICQ   Вверх
Joker07
Дата 18.6.2006, 19:55 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 40
Регистрация: 17.6.2006

Репутация: нет
Всего: нет



Спасибо. А как насчет добавить backspace? 
PM MAIL   Вверх
Sunr1se
Дата 18.6.2006, 20:16 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Бывалый
*


Профиль
Группа: Участник
Сообщений: 193
Регистрация: 1.5.2006

Репутация: нет
Всего: 13



Код

procedure TForm1.Edit1KeyPress(Sender: TObject; var Key: Char);
begin
  if not (Key in ['0'..'9', '+', '-', '*', '.', '(', ')', Chr(8)]) then
  begin
    Key := #0;
    Beep;
  end;
end;
 
--------------------
IRC-канал Винграда 
PM MAIL ICQ   Вверх
Guedda
Дата 18.6.2006, 20:18 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Подрывник
****


Профиль
Группа: Завсегдатай
Сообщений: 3137
Регистрация: 27.12.2005
Где: Ростов-на-Дону

Репутация: 6
Всего: 78



Код

if not (Key in ['0'..'9', '+', '-', '*', '.', '(', ')', #8]) then
 


--------------------
Ll 2
PM MAIL WWW ICQ Skype GTalk   Вверх
  
Ответ в темуСоздание новой темы Создание опроса
Правила форума "Центр помощи"

ВНИМАНИЕ! Прежде чем создавать темы, или писать сообщения в данный раздел, ознакомьтесь, пожалуйста, с Правилами форума и конкретно этого раздела.
Несоблюдение правил может повлечь за собой самые строгие меры от закрытия/удаления темы до бана пользователя!


  • Название темы должно отражать её суть! (Не следует добавлять туда слова "помогите", "срочно" и т.п.)
  • При создании темы, первым делом в квадратных скобках укажите область, из которой исходит вопрос (язык, дисциплина, диплом). Пример: [C++].
  • В названии темы не нужно указывать происхождение задачи (например "школьная задача", "задача из учебника" и т.п.), не нужно указывать ее сложность ("простая задача", "легкий вопрос" и т.п.). Все это можно писать в тексте самой задачи.
  • Если Вы ошиблись при вводе названия темы, отправьте письмо любому из модераторов раздела (через личные сообщения или report).
  • Для подсветки кода пользуйтесь тегами [code][/code] (выделяйте код и нажимаете на кнопку "Код"). Не забывайте выбирать при этом соответствующий язык.
  • Помните: один топик - один вопрос!
  • В данном разделе запрещено поднимать темы, т.е. при отсутствии ответов на Ваш вопрос добавлять новые ответы к теме, тем самым поднимая тему на верх списка.
  • Если вы хотите, чтобы вашу проблему решили при помощи определенного алгоритма, то не забудьте описать его!
  • Если вопрос решён, то воспользуйтесь ссылкой "Пометить как решённый", которая находится под кнопками создания темы или специальным флажком при ответе.

Более подробно с правилами данного раздела Вы можете ознакомится в этой теме.

Если Вам помогли и атмосфера форума Вам понравилась, то заходите к нам чаще! С уважением, Poseidon, Rodman

 
1 Пользователей читают эту тему (1 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | Центр помощи | Следующая тема »


 




[ Время генерации скрипта: 0.1229 ]   [ Использовано запросов: 21 ]   [ GZIP включён ]


Реклама на сайте     Информационное спонсорство

 
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности     Powered by Invision Power Board(R) 1.3 © 2003  IPS, Inc.