Инструменты пользователя

Инструменты сайта


cp:obx-filter

Различия

Показаны различия между двумя версиями страницы.

Ссылка на это сравнение

cp:obx-filter [2021/06/19 15:22] (текущий)
rbv создано
Строка 1: Строка 1:
 +====== Фильтрация и обработка текста ======
  
 +Пример фильтрации текста при помощи сканера (TextMappers.Scanner) и вывода результата в новое окно.
 +
 +===== Задача =====
 +
 +Подсчитать количество целых чисел и их сумму в выделенном тексте активного текстового документа (АТД). Результаты показать в новом документе.
 +
 +===== Алгоритм =====
 +==== Основной ====
 +
 +Построение алгоритма методом пошагового уточнения начинается с одного единственного шага "решить задачу", который мы запишем так:
 +
 +<code componentpascal>
 +Обработать АТД
 +Вывести результаты
 +</code>
 +
 +Обработка АТД, по условию задачи, заключается в обработке выделенного текста. При этом нужно учесть, что АТД не всегда есть:
 +
 +<code componentpascal>
 +Если есть АТД, то
 +  Получить АТД;
 +  Обработать выделенный текст;
 +  Вывести результаты
 +Конец
 +</code>
 +
 +Соображения касательно обработки выделенного текста аналогичные:
 +
 +<code componentpascal>
 +Если есть АТД, то
 +  Получить АТД;
 +  Если есть выделение, то
 +    Получить границы выделения;
 +    Обработать текст пределах этих границ;
 +    Вывести результаты  
 +  Конец
 +Конец
 +</code>
 +
 +==== Обработка участка текста документа ====
 +
 +Обработка текста документа в заданном диапазоне выполняется на основе стандартной схемы цикла - полного прохода по элементам последовательности с фильтрацией:
 +
 +<code componentpascal>
 +Получить первый элемент;
 +Пока элемент получен, выполнять
 +  Если элемент удовлетворяет условию отбора (проходит через фильтр), то
 +    Обработать элемент
 +  Конец;
 +  Получить следующий элемент
 +Конец
 +</code>
 +
 +В нашем случае последовательность представляет собой значения различных типов (целые, вещественные, строковые и т. п.), записанные в указанном промежутке текста. Условие отбора - тип значения - целое.
 +
 +==== Вывод результатов ====
 +
 +Вывод результатов - обычный линейный алгоритм:
 +<code componentpascal>
 +Создать новый текстовый документ;
 +Записать количество чисел;
 +Записать сумму чисел;
 +Показать документ в новом окне
 +</code>
 +
 +===== Реализация =====
 +
 +==== Вариант 1 ====
 +
 +<code componentpascal>
 +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.
 +</code>
 +
 +==== Вариант 2 ====
 +
 +<code componentpascal>
 +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
 +*)
 +</code>
 +
 +//Авторы: Slava, Темиргалеев Е.Э. Правки: PGR, Кривохатько С.А.//
cp/obx-filter.txt · Последнее изменение: 2021/06/19 15:22 — rbv