Консультация № 178808
01.06.2010, 23:13
45.00 руб.
0 19 2
Здравствуйте. Помогите пожалуйста написать программу на языке Pascal в среде turbo.
просьба такая: использовать в программе модули и динамические переменные.
Задание: Задано m пар не повторяющихся символов, воспринимаемых как скобочные пары, т.е. если (a,b)- одна из пар, то a- левая скобка, b- соответствующая правая скобка. Вводится текст, состоящий из любой последовательности символов и пробела. Текст считается корректным, если соблюдаются скобочные правила: за левой скобкой рано или поздно следует соответствующая правая скобка. Предусмотреть произвольную вложенность скобок. Надо определить корректность любого введенного текста. И текст и пары скобок считать из входных файлов. В программе использовать стек. Проиллюстрировать решение анимацией.

Обсуждение

Неизвестный
02.06.2010, 00:53
общий
Евгений Усков:
Что следует понимать под "анимацией"?
Неизвестный
02.06.2010, 16:40
общий
например выделить цветом результат после прогона, или что бы мигал.
Неизвестный
02.06.2010, 19:40
общий
Andrew Kovalchuk:
Напишите? И стек можно применить (скобки туды ...), когда начинаешь извлекать - тут же и проверяешь на соответствие ...
Неизвестный
03.06.2010, 00:33
общий
это ответ
Здравствуйте, Евгений Усков.

Вот основной модуль программы:
Код:
{
Задано m пар не повторяющихся символов, воспринимаемых как скобочные
пары, т.е. если (a,b) - одна из пар, то a- левая скобка, b-
соответствующая правая скобка. Вводится текст, состоящий из любой
последовательности символов и пробела. Текст считается корректным,
если соблюдаются скобочные правила: за левой скобкой рано или поздно
следует соответствующая правая скобка. Предусмотреть произвольную
вложенность скобок. Надо определить корректность любого введенного
текста. И текст и пары скобок считать из входных файлов. В программе
использовать стек.
}
program q178808;

uses stack;

type
p_bracket_pair = ^t_bracket_pair;
t_bracket_pair = record
next: p_bracket_pair;
left, right: char; { левая и правая скобки }
end;

var
pBrackets: p_bracket_pair; { указатель на список пар скобок }

{ добавление скобок в список с контролем }
procedure addBrackets( left, right: char );
var p: p_bracket_pair;
begin
if (left <> ' ') and (right <> ' ') and (left <> right) then begin
{ проверяем, есть ли уже такие символы в списке }
p := pBrackets;
while p <> nil do begin
if (left = p^.left) or (left = p^.right) or
(right = p^.left) or (right = p^.right)
then
exit; { один из символов уже встречался }

p := p^.next;
end;

{ вставляем новую пару скобок в список }
new( p );
p^.next := pBrackets;
p^.left := left;
p^.right := right;
pBrackets := p;
end;
end;

{ уничтожение списка скобок }
procedure freeBrackets;
var next: p_bracket_pair;
begin
while pBrackets <> nil do begin
next := pBrackets^.next;
dispose( pBrackets );
pBrackets := next;
end;
end;

{ ищем символ в списке скобок
возвращает указатель на пару, к которой относится скобка
или nil, если символ не является скобкой
}
function findBracketPair( ch: char ): p_bracket_pair;
var p: p_bracket_pair;
begin
p := pBrackets;
while p <> nil do begin
with p^ do
if (ch = left) or (ch = right) then begin
findBracketPair := p;
exit;
end;

p := p^.next;
end;
findBracketPair := nil;
end;

{ читаем скобки из файла
в каждой строке файла должно быть не меньше двух символов
первые 2 символа - правая и левая скобки
например:
()
[]
}
procedure readBrackets;
var f: text;
s: string;
begin
assign( f, 'brackets' );
reset( f );
while not eof(f) do begin
readln( f, s );
if length(s) >= 2 then
addBrackets( s[1], s[2] );
end;
close(f);
end;

{ функция читает первую строку из файла и возвращает ее }
function readExpression : string;
var f: text;
s: string;
begin
assign( f, 'expr' );
reset( f );
readln( f, s );
readExpression := s;
close(f);
end;

{ ------------------------------------------------------------- }
const
errIllegalChar = 1; { коды ошибок }
errNotPair = 2;
errUnexpectedEnd = 3;
maxError = 3;

{ сообщения }
msg : array[0..maxError] of string[30] =
(
'Correct expression',
'Illegal character',
'Not a pair',
'Unexpected end of expression'
);
{ ------------------------------------------------------------- }

var
level : integer; { уровень вложенности }

{ показывает очередную скобку со сдвигом по уровню вложенности
dir = 1 - левая скобка (PUSH)
dir = -1 - правая скобка (POP)
}
procedure show( dir: integer; ch: char );
var i : integer;
begin
if dir > 0 then
inc( level );
for i := level downto 1 do
write( ' ' );
writeln( ch );
if dir < 0 then
dec( level );
end;

{ разбор строки как скобочного выражения
возвращает код ошибки, 0 - корректное выражение
}
function parse( s: string ): integer;
var i : integer; { индексация символов в строке }
ch : char; { текуций символ }
stack: TStack; { стек скобок }
p : p_bracket_pair;
begin
stack.init; { инициализируем стек }
level := 0; { начальный уровень }
for i := 1 to length(s) do begin
ch := s[i];
if ch <> ' ' then begin
p := findBracketPair( ch ); { ищем символ в списке скобок }
if p = nil then begin { неверный символ }
show( 0, ch ); { показываем символ для информации }
parse := errIllegalChar;
exit;
end;
if ch = p^.left then begin { левая скобка }
show( 1, ch ); { показываем }
stack.push( p ); { помещаем в стек }
end
else begin { правая скобка }
show( -1, ch ); { показываем }
if p <> stack.pop then begin { непарная скобка, напр. (] }
parse := errNotPair;
exit;
end;
end;
end;
end;
if stack.pop <> nil then { непустой стек - ошибка }
parse := errUnexpectedEnd
else
parse := 0;
end;

var expr: string; { скобочное выражение }

BEGIN
pBrackets := nil;
readBrackets; { читаем скобки }
if pBrackets <> nil then begin
expr := readExpression; { читаем выражение }
writeln( 'Parsing expression:' );
writeln( expr );
writeln( msg[parse( expr )] ); { анализ и сообщение }
end;
END.

В приложении — модуль стека.

Для простоты, имена файлов со скобками и скобочным выражением предопределены — соответственно, brackets и expr.

Пример файла brackets:
Код:
()
[]
{}
<>

Пример файла expr:
Код:
( <> {([] <>) ()} ( [] <[() []]() > ) )


Вывод программы на данном примере:
Код:
Parsing expression:
( <> {([] <>) ()} ( [] <[() []]() > ) )
(
<
>
{
(
[
]
<
>
)
(
)
}
(
[
]
<
[
(
)
[
]
]
(
)
>
)
)
Correct expression


Если нужен какой-то другой вывод (для наглядности), то поясните, пожалуйста, в мини-форуме.
Программа проверена в Borland Pascal 7.0.

Успехов!

Приложение:
{ стек }
Unit Stack;

interface

type
PStackItem = ^TStackItem;
TStackItem = record
next: PStackItem; { указатель на следующий элемент в стеке }
data: pointer; { указатель на данные (или сами данные, }
end; { если возможно приведение типа) }

PTStack = ^TStack;
TStack = object
pTop: PStackItem; { указатель на вершину стека }

constructor Init; { инициализация объекта }
destructor Done; virtual; { освобождение памяти }

procedure push( pData: pointer ); { помещение объекта в стек }
function pop: pointer; { извлечение объекта из стека }

procedure clear; virtual; { очистка стека }
procedure freeData( p: pointer ); virtual; { удаление данных }
end;

implementation

{ инициализация объекта }
constructor TStack.Init;
begin
pTop := nil;
end;

{ освобождение памяти }
destructor TStack.Done;
begin
clear;
end;

{ помещение объекта в стек }
procedure TStack.push( pData: pointer );
var p: PStackItem;
begin
new( p );
p^.data := pData;
p^.next := pTop;
pTop := p;
end;

{ извлечение объекта из стека
возвращает указатель на данные }
function TStack.pop: pointer;
begin
if pTop <> nil then begin
pop := pTop^.data;
pTop := pTop^.next;
end
else
pop := nil;
end;

{ очистка стека }
procedure TStack.clear;
var p: pointer;
begin
while true do begin
p := pop;
if p = nil then exit;
freeData( p );
end;
end;

{ удаление данных, вызывается при очистке стека
если нужно удалять данные, то производный объект должен
перекрыть эту функцию
}
procedure TStack.freeData( p: pointer );
begin
end;

begin
end.
5
Неизвестный
03.06.2010, 13:46
общий
это ответ
Здравствуйте, Евгений Усков.
В прикрепленном архиве содержатся:
178808.pas - исходный текст программы
stack.pas - исходный текст модуля с реализацией стека
stack.tpu - скомпилированный из предыдущего файла модуль
pairs.txt - тестовый файл с парами символов для обозначения скобок
checkme.txt - текст для проверки.
Прикрепленные файлы:
5
Неизвестный
03.06.2010, 13:51
общий
Boriss:
Цитата: 422
Напишите? И стек можно применить (скобки туды ...), когда начинаешь извлекать - тут же и проверяешь на соответствие ...

Написал :). Стек пришлось слегка модифицировать, но много переделок не понадобилось.
Неизвестный
03.06.2010, 14:42
общий
Заметил пару ошибок в своем коде:

1. функция Stack.pop не освобождает память. Исправленный код:
Код:
{ извлечение объекта из стека
возвращает указатель на данные }
function TStack.pop: pointer;
var p: PStackItem;
begin
if pTop <> nil then begin
p := pTop; { сохраняем указатель на вершину }
pop := p^.data; { возвращаем данные }
pTop := p^.next; { новая вершина }
dispose( p ); { удаляем извлеченный элемент }
end
else
pop := nil;
end;


2. В основной программе написал процедуру удаления списка скобок, а вызвать ее забыл:
Код:
BEGIN
pBrackets := nil;
readBrackets; { читаем скобки }
if pBrackets <> nil then begin
expr := readExpression; { читаем выражение }
writeln( 'Parsing expression:' );
writeln( expr );
writeln( msg[parse( expr )] ); { анализ и сообщение }
end;
freeBrackets;
END.

Приношу свои извинения.

Исправленные модули целиком:
178808.PAS
Код:
{
Задано m пар не повторяющихся символов, воспринимаемых как скобочные
пары, т.е. если (a,b) - одна из пар, то a- левая скобка, b-
соответствующая правая скобка. Вводится текст, состоящий из любой
последовательности символов и пробела. Текст считается корректным,
если соблюдаются скобочные правила: за левой скобкой рано или поздно
следует соответствующая правая скобка. Предусмотреть произвольную
вложенность скобок. Надо определить корректность любого введенного
текста. И текст и пары скобок считать из входных файлов. В программе
использовать стек.
}
program q178808;

uses stack;

type
p_bracket_pair = ^t_bracket_pair;
t_bracket_pair = record
next: p_bracket_pair;
left, right: char; { левая и правая скобки }
end;

var
pBrackets: p_bracket_pair; { указатель на список пар скобок }

{ добавление скобок в список с контролем }
procedure addBrackets( left, right: char );
var p: p_bracket_pair;
begin
if (left <> ' ') and (right <> ' ') and (left <> right) then begin
{ проверяем, есть ли уже такие символы в списке }
p := pBrackets;
while p <> nil do begin
if (left = p^.left) or (left = p^.right) or
(right = p^.left) or (right = p^.right)
then
exit; { один из символов уже встречался }

p := p^.next;
end;

{ вставляем новую пару скобок в список }
new( p );
p^.next := pBrackets;
p^.left := left;
p^.right := right;
pBrackets := p;
end;
end;

{ уничтожение списка скобок }
procedure freeBrackets;
var next: p_bracket_pair;
begin
while pBrackets <> nil do begin
next := pBrackets^.next;
dispose( pBrackets );
pBrackets := next;
end;
end;

{ ищем символ в списке скобок
возвращает указатель на пару, к которой относится скобка
или nil, если символ не является скобкой
}
function findBracketPair( ch: char ): p_bracket_pair;
var p: p_bracket_pair;
begin
p := pBrackets;
while p <> nil do begin
with p^ do
if (ch = left) or (ch = right) then begin
findBracketPair := p;
exit;
end;

p := p^.next;
end;
findBracketPair := nil;
end;

{ читаем скобки из файла
в каждой строке файла должно быть не меньше двух символов
первые 2 символа - правая и левая скобки
например:
()
[]
}
procedure readBrackets;
var f: text;
s: string;
begin
assign( f, 'brackets' );
reset( f );
while not eof(f) do begin
readln( f, s );
if length(s) >= 2 then
addBrackets( s[1], s[2] );
end;
close(f);
end;

{ функция читает первую строку из файла и возвращает ее }
function readExpression : string;
var f: text;
s: string;
begin
assign( f, 'expr' );
reset( f );
readln( f, s );
readExpression := s;
close(f);
end;

{ ------------------------------------------------------------- }
const
errIllegalChar = 1; { коды ошибок }
errNotPair = 2;
errUnexpectedEnd = 3;
maxError = 3;

{ сообщения }
msg : array[0..maxError] of string[30] =
(
'Correct expression',
'Illegal character',
'Not a pair',
'Unexpected end of expression'
);
{ ------------------------------------------------------------- }

var
level : integer; { уровень вложенности }

{ показывает очередную скобку со сдвигом по уровню вложенности
dir = 1 - левая скобка (PUSH)
dir = -1 - правая скобка (POP)
}
procedure show( dir: integer; ch: char );
var i : integer;
begin
if dir > 0 then
inc( level );
for i := level downto 1 do
write( ' ' );
writeln( ch );
if dir < 0 then
dec( level );
end;

{ разбор строки как скобочного выражения
возвращает код ошибки, 0 - корректное выражение
}
function parse( s: string ): integer;
var i : integer; { индексация символов в строке }
ch : char; { текуций символ }
stack: TStack; { стек скобок }
p : p_bracket_pair;
begin
stack.init; { инициализируем стек }
level := 0; { начальный уровень }
for i := 1 to length(s) do begin
ch := s[i];
if ch <> ' ' then begin
p := findBracketPair( ch ); { ищем символ в списке скобок }
if p = nil then begin { неверный символ }
show( 0, ch ); { показываем символ для информации }
parse := errIllegalChar;
exit;
end;
if ch = p^.left then begin { левая скобка }
show( 1, ch ); { показываем }
stack.push( p ); { помещаем в стек }
end
else begin { правая скобка }
show( -1, ch ); { показываем }
if p <> stack.pop then begin { непарная скобка, напр. (] }
parse := errNotPair;
exit;
end;
end;
end;
end;
if stack.pop <> nil then { непустой стек - ошибка }
parse := errUnexpectedEnd
else
parse := 0;
end;

var expr: string; { скобочное выражение }

BEGIN
pBrackets := nil;
readBrackets; { читаем скобки }
if pBrackets <> nil then begin
expr := readExpression; { читаем выражение }
writeln( 'Parsing expression:' );
writeln( expr );
writeln( msg[parse( expr )] ); { анализ и сообщение }
end;
freeBrackets;
END.


STACK.PAS
Код:
{ стек }
Unit Stack;

interface

type
PStackItem = ^TStackItem;
TStackItem = record
next: PStackItem; { указатель на следующий элемент в стеке }
data: pointer; { указатель на данные (или сами данные, }
end; { если возможно приведение типа) }

PTStack = ^TStack;
TStack = object
pTop: PStackItem; { указатель на вершину стека }

constructor Init; { инициализация объекта }
destructor Done; virtual; { освобождение памяти }

procedure push( pData: pointer ); { помещение объекта в стек }
function pop: pointer; { извлечение объекта из стека }

procedure clear; virtual; { очистка стека }
procedure freeData( p: pointer ); virtual; { удаление данных }
end;

implementation

{ инициализация объекта }
constructor TStack.Init;
begin
pTop := nil;
end;

{ освобождение памяти }
destructor TStack.Done;
begin
clear;
end;

{ помещение объекта в стек }
procedure TStack.push( pData: pointer );
var p: PStackItem;
begin
new( p );
p^.data := pData;
p^.next := pTop;
pTop := p;
end;

{ извлечение объекта из стека
возвращает указатель на данные }
function TStack.pop: pointer;
var p: PStackItem;
begin
if pTop <> nil then begin
p := pTop; { сохраняем указатель на вершину }
pop := p^.data; { возвращаем данные }
pTop := p^.next; { новая вершина }
dispose( p ); { удаляем извлеченный элемент }
end
else
pop := nil;
end;

{ очистка стека }
procedure TStack.clear;
var p: pointer;
begin
while true do begin
p := pop;
if p = nil then exit;
freeData( p );
end;
end;

{ удаление данных, вызывается при очистке стека
если нужно удалять данные, то производный объект должен
перекрыть эту функцию
}
procedure TStack.freeData( p: pointer );
begin
end;

begin
end.


Для того, чтобы нормально смотрелось в редакторе, установите Tab size=4
Неизвестный
03.06.2010, 17:17
общий
добрый день уважаемые эксперты. благодарю вас за проделанную вами работу, прошу пояснить некоторые моменты:

amnick, в основной программе 178808.PAS выдает ошибку "неизвестный идентификатор" и указывает курсором на эту строчку: stack: TStack; { стек скобок }

при запуске главной программы что нужно делать с файлом STACK.PAS ?


Andrew Kovalchuk, к вам вопрос такой:pairs.txt, checkme.txt эти два файла ясно зачем, но в тексте программы упоминание о файле с названием "F" , мне его самому нужно создать? что в него нужно поместить?



Неизвестный
03.06.2010, 17:29
общий
Евгений Усков:
Цитата: 329545
Andrew Kovalchuk, к вам вопрос такой:pairs.txt, checkme.txt эти два файла ясно зачем, но в тексте программы упоминание о файле с названием "F" , мне его самому нужно создать? что в него нужно поместить?
Если вы имеете в виду
Код:
Var
... f: text;
то это лишь переменная для работы с файлом. Файл с таким именем создавать не нужно. Соответственно и помещать в него ничего не требуется.
Если вы не получили ответа на интересующий вас случай - процитируйте кусочек кода, к которому требуются пояснения.

Если после корректного выполнения подготовительных действий вы не получаете ошибок в результате выполнения программы и видите на экране надпись Done. Press any key... значит работа программы успешно завершена.
Неизвестный
03.06.2010, 17:35
общий
прошу пояснить эту процедуру, как раз здесь и идет речь об этом файле F

procedure initPairs;
begin
Opens := [];
Closes := [];
PairArCount := 0;
Assign(f, pairs);
Reset(f); ----------------------------здесь при прогоне выдается ошибка "файл не найден"
while not eof(f) do begin
readln(f, st);
ch := st[1];
Include(Opens, ch);
ch := st[2];
Include(Closes, ch);
Inc(PairArCount);
PairAr[PairArCount] := st;
end;
Close(f);
Неизвестный
03.06.2010, 17:45
общий
Евгений Усков:
Вам нужно поместить оба файла (178808.PAS и STACK.PAS) в один каталог, загрузить файл 178808.PAS в среду Turbo (Borland) Pascal и скомпилировать.
Поскольку имена файлов модуля стека (STACK.PAS) у Andrew Kovalchuk и у меня одинаковые, Вам нужно создать отдельные каталоги для его и моего решений.
Неизвестный
03.06.2010, 17:56
общий
amnick, спасибо за пояснение. программа заработала и дала нужный результат.
Неизвестный
03.06.2010, 18:19
общий
Евгений Усков:
Цитата: 329545
Assign(f, pairs);
Reset(f); ----------------------------здесь при прогоне выдается ошибка "файл не найден"

Assign - связывает файловую переменную (f) с именем файла (pairs)
Reset(f) - открывает файл, с которым связана файловая переменная f, для чтения
Неизвестный
03.06.2010, 19:03
общий
Евгений Усков:
Цитата: 329545
Assign(f, pairs);
Reset(f); ----------------------------здесь при прогоне выдается ошибка "файл не найден"
файлы с данными, которые нужны для работы программы, должны быть помещены в тот же каталог в котором находится и исходный ее текст.
Неизвестный
03.06.2010, 19:30
общий
понял, спасибо :-)
Неизвестный
03.06.2010, 20:59
общий
Вариант контроля с использованием множеств при добавлении скобок в моей программе (изменения выделены цветом):
Код:
var
pBrackets: p_bracket_pair; { указатель на список пар скобок }
used_chars : set of char; { множество символов, используемых как скобки }

{ добавление скобок в список с контролем }
procedure addBrackets( left, right: char );
var p: p_bracket_pair;
begin
if (left <> ' ') and (right <> ' ') and (left <> right) and
{ проверяем, есть ли уже такие символы в списке }
not (left in used_chars) and not (right in used_chars) then
begin
include( used_chars, left );
include( used_chars, right );


{ вставляем новую пару скобок в список }
new( p );
p^.next := pBrackets;
p^.left := left;
p^.right := right;
pBrackets := p;
end;
end;

Это не исправление, а один из возможных вариантов реализации.
При поиске скобок в функции findBracketPair можно использовать это множество для быстрой проверки - является ли символ скобкой. Но поскольку при положительном результате все равно просматривается список, это не сильно полезно, скорее - наоборот.
Неизвестный
04.06.2010, 23:20
общий
Евгений Усков:
По Вашей просьбе добавил в программу выделение цветом:
Код:
{
Задано m пар не повторяющихся символов, воспринимаемых как скобочные
пары, т.е. если (a,b) - одна из пар, то a- левая скобка, b-
соответствующая правая скобка. Вводится текст, состоящий из любой
последовательности символов и пробела. Текст считается корректным,
если соблюдаются скобочные правила: за левой скобкой рано или поздно
следует соответствующая правая скобка. Предусмотреть произвольную
вложенность скобок. Надо определить корректность любого введенного
текста. И текст и пары скобок считать из входных файлов. В программе
использовать стек.
}
program q178808;

uses crt, stack;

type
p_bracket_pair = ^t_bracket_pair;
t_bracket_pair = record
next: p_bracket_pair;
left, right: char; { левая и правая скобки }
attr: byte; { цвет для вывода на экран }
end;

t_attr_array = array[1..255] of byte;

const { предопределенные атрибуты }
attr : array[0..5] of byte = ( 15, 14, 13, 11, 10, 9 );

var
pBrackets: p_bracket_pair; { указатель на список пар скобок }
used_chars : set of char; { множество символов, используемых как скобки }
nextAttr : integer; { индекс атрибутов для следующей пары скобок }

{ добавление скобок в список с контролем }
procedure addBrackets( left, right: char );
var p: p_bracket_pair;
begin
if (left <> ' ') and (right <> ' ') and (left <> right) and
{ проверяем, есть ли уже такие символы в списке }
not (left in used_chars) and not (right in used_chars) then
begin
include( used_chars, left );
include( used_chars, right );

{ вставляем новую пару скобок в список }
new( p );
p^.next := pBrackets;
p^.left := left;
p^.right := right;
p^.attr := attr[nextAttr mod sizeof(attr)] or { цвет текста }
( (nextAttr div sizeof(attr)) shl 4 ); { цвет фона }
pBrackets := p;
inc( nextAttr );
end;
end;

{ уничтожение списка скобок }
procedure freeBrackets;
var next: p_bracket_pair;
begin
while pBrackets <> nil do begin
next := pBrackets^.next;
dispose( pBrackets );
pBrackets := next;
end;
end;

{ ищем символ в списке скобок
возвращает указатель на пару, к которой относится скобка
или nil, если символ не является скобкой
}
function findBracketPair( ch: char ): p_bracket_pair;
var p: p_bracket_pair;
i: integer;
begin
i := 0;
p := pBrackets;
while p <> nil do begin
with p^ do
if (ch = left) or (ch = right) then begin
findBracketPair := p;
exit;
end;
inc( i );
p := p^.next;
end;
findBracketPair := nil;
end;

{ читаем скобки из файла
в каждой строке файла должно быть не меньше двух символов
первые 2 символа - правая и левая скобки
например:
()
[]
}
procedure readBrackets;
var f: text;
s: string;
begin
assign( f, 'brackets' );
reset( f );
while not eof(f) do begin
readln( f, s );
if length(s) >= 2 then
addBrackets( s[1], s[2] );
end;
close(f);
end;

{ функция читает первую строку из файла и возвращает ее }
function readExpression : string;
var f: text;
s: string;
begin
assign( f, 'expr' );
reset( f );
readln( f, s );
readExpression := s;
close(f);
end;

{ ------------------------------------------------------------- }
const
errIllegalChar = 1; { коды ошибок }
errNotPair = 2;
errUnexpectedEnd = 3;
maxError = 3;

{ сообщения }
msg : array[0..maxError] of string[30] =
(
'Correct expression',
'Illegal character',
'Not a pair',
'Unexpected end of expression'
);
{ ------------------------------------------------------------- }

var
level : integer; { уровень вложенности }

{ показывает очередную скобку со сдвигом по уровню вложенности
dir = 1 - левая скобка (PUSH)
dir = -1 - правая скобка (POP)
}
procedure show( dir: integer; ch: char; attr: byte );
var i : integer;
begin
if dir > 0 then
inc( level );
for i := level downto 1 do
write( ' ' );
TextAttr := attr;
writeln( ch );
if dir < 0 then
dec( level );
end;

{ разбор строки как скобочного выражения
возвращает код ошибки, 0 - корректное выражение
заполняет массив eattr цветовыми атрибутами для вывода результата
}
function parse( s: string; var eattr: t_attr_array ): integer;
var i : integer; { индексация символов в строке }
ch : char; { текуций символ }
stack: TStack; { стек скобок }
p : p_bracket_pair;
begin
stack.init; { инициализируем стек }
level := 0; { начальный уровень }
for i := 1 to length(s) do begin
ch := s[i];
if ch <> ' ' then begin
p := findBracketPair( ch ); { ищем символ в списке скобок }
if p = nil then begin { неверный символ }
eattr[i] := 12;
show( 0, ch, 12 ); { показываем символ для информации }
parse := errIllegalChar;
exit;
end;
eattr[i] := p^.attr; { атрибут для отображения }
if ch = p^.left then begin { левая скобка }
show( 1, ch, p^.attr ); { показываем }
stack.push( p ); { помещаем в стек }
end
else begin { правая скобка }
show( -1, ch, p^.attr ); { показываем }
if p <> stack.pop then begin { непарная скобка, напр. (] }
eattr[i] := 12; { заменяем на ярко-красный }
parse := errNotPair;
exit;
end;
end;
end;
end;
if stack.pop <> nil then { непустой стек - ошибка }
parse := errUnexpectedEnd
else
parse := 0;
end;

{ вывод результата с выделением цветом }
procedure coloredResult( var expr: string; var eattr: t_attr_array );
var i : integer;
begin
for i := 1 to length(expr) do begin
TextAttr := eattr[i];
write( expr[i] );
end;
writeln;
end;

var expr: string; { скобочное выражение }
eattr: t_attr_array; { атрибуты для каждого символа expr }
iResult : integer;

BEGIN
nextAttr := 0;
pBrackets := nil; { никакие скобки пока не заданы }
used_chars := [];
{ атрибут по умолчанию - светло-серый на черном }
fillchar( eattr, sizeof(eattr), 7 );

readBrackets; { читаем скобки }
if pBrackets <> nil then begin
expr := readExpression; { читаем выражение }
writeln( 'Parsing expression:' );
writeln( expr );
iResult := parse( expr, eattr );
if iResult = 0 then
TextAttr := 10 { ярко-зеленый }
else
TextAttr := 12; { ярко-красный }

writeln( msg[iResult] ); { анализ и сообщение }
coloredResult( expr, eattr );
freeBrackets;
end;
END.
Неизвестный
05.06.2010, 02:00
общий
еще раз огромное спасибо вам и всем экспертам!
Неизвестный
05.06.2010, 10:36
общий
Как администратор отмечу, что "спасибо" сказали, а пятерку не поставили ...
Форма ответа