====== Фильтрация и обработка текста ======
Пример фильтрации текста при помощи сканера (TextMappers.Scanner) и вывода результата в новое окно.
===== Задача =====
Подсчитать количество целых чисел и их сумму в выделенном тексте активного текстового документа (АТД). Результаты показать в новом документе.
===== Алгоритм =====
==== Основной ====
Построение алгоритма методом пошагового уточнения начинается с одного единственного шага "решить задачу", который мы запишем так:
Обработать АТД
Вывести результаты
Обработка АТД, по условию задачи, заключается в обработке выделенного текста. При этом нужно учесть, что АТД не всегда есть:
Если есть АТД, то
Получить АТД;
Обработать выделенный текст;
Вывести результаты
Конец
Соображения касательно обработки выделенного текста аналогичные:
Если есть АТД, то
Получить АТД;
Если есть выделение, то
Получить границы выделения;
Обработать текст пределах этих границ;
Вывести результаты
Конец
Конец
==== Обработка участка текста документа ====
Обработка текста документа в заданном диапазоне выполняется на основе стандартной схемы цикла - полного прохода по элементам последовательности с фильтрацией:
Получить первый элемент;
Пока элемент получен, выполнять
Если элемент удовлетворяет условию отбора (проходит через фильтр), то
Обработать элемент
Конец;
Получить следующий элемент
Конец
В нашем случае последовательность представляет собой значения различных типов (целые, вещественные, строковые и т. п.), записанные в указанном промежутке текста. Условие отбора - тип значения - целое.
==== Вывод результатов ====
Вывод результатов - обычный линейный алгоритм:
Создать новый текстовый документ;
Записать количество чисел;
Записать сумму чисел;
Показать документ в новом окне
===== Реализация =====
==== Вариант 1 ====
MODULE ExamplesFilterInText;
IMPORT TextControllers, TextMappers, TextModels, TextViews, Views;
PROCEDURE GetInts*;
VAR
c: TextControllers.Controller;
atd, sel: TextModels.Model; (* активный текстовый документ, копия выделенного текста *)
beg, end: INTEGER; (* положение выделения в тексте [beg, end) *)
num: INTEGER; (* кол-во считанных чисел *)
sum: INTEGER; (* их сумма *)
PROCEDURE ProcessText;
VAR
s: TextMappers.Scanner;
BEGIN
s.ConnectTo(sel); (* подключаем сканер к тексту *)
(* Читаем и обрабатываем целые из последовательности значений в тексте *)
sum := 0; num := 0;
s.Scan; (* получаем первый элемент *)
(* Пока получен (не конец текста) *)
WHILE s.type # TextMappers.eot DO
IF s.type = TextMappers.int THEN (* отбираем целые *)
(* Обрабатываем *)
sum := sum + s.int;
INC(num)
END;
s.Scan (* получаем следующий элемент *)
END
END ProcessText;
PROCEDURE PrintResults;
VAR
t: TextModels.Model;
f: TextMappers.Formatter;
BEGIN
t := TextModels.dir.New(); (* создаем новый текстовый документ *)
(* Пишем результат *)
f.ConnectTo(t); (* подключаем к тексту форматтер *)
f.WriteString("Найдено целых чисел: "); f.WriteInt(num); f.WriteLn;
f.WriteString("Их сумма равна: "); f.WriteInt(sum); f.WriteLn;
Views.OpenView(TextViews.dir.New(t)) (* открываем документ в новом окне *)
END PrintResults;
BEGIN
c := TextControllers.Focus(); (* получаем контроллер, связанный с АТД *)
IF c # NIL THEN (* если есть контроллер (значит есть и АТД) *)
atd := c.text; (* берем АТД *)
IF c.HasSelection() THEN (* если есть выделение *)
c.GetSelection(beg, end); (* получаем границы выделения *)
sel := TextModels.dir.New(); (* создаем новый текстовый документ *)
sel.InsertCopy(0, atd, beg, end); (* копируем выделенный текст из АТД *)
ProcessText; (* обрабатываем (выделенный) текст *)
PrintResults (* печатаем результат *)
END
END
END GetInts;
END ExamplesFilterInText.
==== Вариант 2 ====
MODULE ExamplesFilterInText;
IMPORT TextControllers, TextMappers, TextModels, TextViews, Views;
PROCEDURE GetInts*;
VAR
s: TextMappers.Scanner;
beg, end: INTEGER;
sum, num: INTEGER;
PROCEDURE ConnectScanner;
VAR
c: TextControllers.Controller;
BEGIN
s.ConnectTo(NIL);
c := TextControllers.Focus();
IF (c # NIL) & c.HasSelection() THEN
c.GetSelection(beg, end);
s.ConnectTo(c.text);
ASSERT(s.rider # NIL)
END
END ConnectScanner;
PROCEDURE PrintSum;
VAR
f: TextMappers.Formatter;
t: TextModels.Model;
BEGIN
t := TextModels.dir.New();
f.ConnectTo(t);
f.WriteString("Найдено целых чисел:");
f.WriteInt(num);
f.WriteLn;
f.WriteString("Их сумма равна:");
f.WriteInt(sum);
f.WriteLn;
Views.OpenView(TextViews.dir.New(t))
END PrintSum;
BEGIN
ConnectScanner;
IF s.rider # NIL THEN
sum := 0;
num := 0;
s.SetPos(beg);
s.Scan;
WHILE (s.type # TextMappers.eot) & (s.Pos() - 1 <= end) DO
IF s.type = TextMappers.int THEN
INC(sum, s.int);
INC(num)
END;
s.Scan
END;
PrintSum
END
END GetInts;
END ExamplesFilterInText.
(*
@ExamplesFilterInText.GetInts
1 2 3 4 5 6 7 8 9
Mister Jack paid 99.99$ for 10 balls
11 12 13 14
*)
//Авторы: Slava, Темиргалеев Е.Э. Правки: PGR, Кривохатько С.А.//