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