Форум программистов «Весельчак У»
  *
Добро пожаловать, Гость. Пожалуйста, войдите или зарегистрируйтесь.
Вам не пришло письмо с кодом активации?

  • Рекомендуем проверить настройки временной зоны в вашем профиле (страница "Внешний вид форума", пункт "Часовой пояс:").
  • У нас больше нет рассылок. Если вам приходят письма от наших бывших рассылок mail.ru и subscribe.ru, то знайте, что это не мы рассылаем.
   Начало  
Наши сайты
Помощь Поиск Календарь Почта Войти Регистрация  
 
Страниц: [1]   Вниз
  Печать  
Автор Тема: Парсинг блоков только с разделителем  (Прочитано 277 раз)
0 Пользователей и 1 Гость смотрят эту тему.
Shouldercannon
Постоялец

ru
Offline Offline

« : 02-01-2017 11:20 » 

Есть файл, в котором есть данные вида
Код: (PHP)
--->---
Понедельник (2012-07-21 21:51:13)
Заметки
---<---
Вторник (2012-07-22 00:44:49)
Заметки
Заметки
Заметки
--->---
Среда (2012-07-22 11:31:18)
Заметки
---<---
Четверг (2012-07-22 12:55:59)
--->---
Пятница (2012-12-03 16:38:24)

где --->--- исходящий, ---<--- входящий
Всё это загружается в StringList.

Дальше вывожу в RichEdit
Код: (Delphi)
procedure TForm1.Button1Click(Sender: TObject);
var
  SL: TStringList;
  I, Style: Integer;
  procA: Boolean;
  s: String;
begin
  // Очищаем
  RichEdit1.Clear;

    Style := -1;
    procA := False;
    I := 0;
    // Парсинг
    while I < SL.Count do
    begin
      s := SL[I];
      procA := procA or (s = '--->---') or (s = '---<---');

      if (s = '--->---') then Style := 3
      else if (s = '---<---') then Style := 2
      else
      begin
        if procA then
        begin
          procA := False;
          RichEdit1.Lines.Add('------------------------------');
          RichEdit1.Lines.Add(s);
        end
        else
        begin
          RichEdit1.Lines.Add(s);
        end;
      end;

      Inc(I);
    end;

  FreeAndNil(SL);
end;
Не у всех блоков есть разделитель. Такие блоки не надо выводить. Как это сделать?
Записан
Aether
Опытный

ru
Offline Offline
Пол: Мужской

« Ответ #1 : 02-01-2017 13:59 » 

Какой разделитель?

Я так понял: запись вида
--->--- или ---<---
День (Дата : Время)
Строки заметок
- это блок.

В RichEdit нужно вывести:
без --->--- и ---<---, но с учётом стилей входящих и исходящих сообщений,
все остальные поля блока.

Вообще, немного избыточно и запутано, например, procA, как понял, служит флагом добавления разделителя, хотя он не нужен, проще добавить там, где, например, Style := 3, блок вида begin Style:=3; RichEdit.Lines.Add("-----"); end; Имхо.
Записан
Shouldercannon
Постоялец

ru
Offline Offline

« Ответ #2 : 02-01-2017 17:17 » 

Какой разделитель?

Я так понял: запись вида
--->--- или ---<---
День (Дата : Время)
Строки заметок
- это блок.

В RichEdit нужно вывести:
без --->--- и ---<---, но с учётом стилей входящих и исходящих сообщений,
все остальные поля блока.

Вообще, немного избыточно и запутано, например, procA, как понял, служит флагом добавления разделителя, хотя он не нужен, проще добавить там, где, например, Style := 3, блок вида begin Style:=3; RichEdit.Lines.Add("-----"); end; Имхо.
Про блок поняли верно. В RichEdit нужно вывести только то, что имеет перед названием дня недели разделитель (--->--- и ---<---). Если один из дней недели не имеет такого разделителя, то мы пропускаем этот блок и переходим к поиску следующих разделителей и вывода данные идущие за ними (разделители).
Записан
Aether
Опытный

ru
Offline Offline
Пол: Мужской

« Ответ #3 : 02-01-2017 17:56 » 

То есть нужен контроль синтаксиса от ситуаций вида:

1)
--->---
Any - не выводим
--->---
Понедельник

2)
--->---
Понедельник
Вторник - не выводим

?

Самое простое: добавить флаг для борьбы с двойной входимостью. Для этого нужно создать процедуру фильтрации, которая сможет отличать строку с датой от иной строки, и возвращать соответственно: True и False. Хотя, лучше было бы все эти случаи объединить, а именно, чтобы процедура фильтра возвращала:
0 - пустая строка, 1 - ситуация "--->---", 2 - ситуация "---<---", 3 - ситуация "дата", 4 - ситуация "данные". Сам по себе вынос фильтра в отдельную процедуру упрощает код.
После создания процедуры нам нужно отслеживать синтаксис:
1. Эта строка пустая? Если нет, далее, если да, то анализ следующей.
2. Эта строка содержит IN или OUT?
3. Да: Поднимаем флаг fIOdetected = True.
4. Нет: на анализ следующей.
5. Эта строка содержит дату и fIOdetected == True?
6. Да: Выводим разделитель и строку в нужном стиле... сбрасываем флаг.
7. Нет: ошибка синтаксиса: ничего не выводим, сбрасываем флаг.
...

Сложнее, когда дата может быть в середине контекста, и может быть окружена мусором, например, от ручного ввода данных пользователем с ошибками - в этом случае одним проходом отделаться не выйдет.
Записан
Shouldercannon
Постоялец

ru
Offline Offline

« Ответ #4 : 03-01-2017 12:10 » 

Прошу прощения. Загнался и неправильно задание описал.
Проверка на наличие разделителя нужна при выводе самого первого блока, для последующих это правило не применять

* 01.jpg (198.66 Кб - загружено 6 раз.)
* 02.jpg (209.37 Кб - загружено 7 раз.)
Записан
Aether
Опытный

ru
Offline Offline
Пол: Мужской

« Ответ #5 : 03-01-2017 15:10 » 

Так понято всё верно, получается - проверка синтаксиса.
Вам нужно начать с того, чтобы сделать функцию-фильтр под Ваши нужды.
Записан
zubr
Модератор

by
Offline Offline
Пол: Мужской

« Ответ #6 : 03-01-2017 15:24 » new

Тут не все так просто. Если не везде есть разделители, то надо как-то отделять содержимое письма, определенное по разделителю от содержимого следующего письма у которого нет разделителя. Так как все письма начинаются с даты и времени, можно применить регулярные выражения, с помощью которых можно определить следующее письмо по наличию формы даты-времени в заголовке.
Записан
Страниц: [1]   Вверх
  Печать  
 

Powered by SMF 1.1.21 | SMF © 2015, Simple Machines