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

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


cp:obx-filter

Фильтрация и обработка текста

Пример фильтрации текста при помощи сканера (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, Кривохатько С.А.

cp/obx-filter.txt · Последнее изменение: 2021/06/19 15:22 — rbv