Экспертная система Delphi.int.ru

Сообщество программистов
Общение, помощь, обмен опытом

Логин:
Пароль:
Регистрация | Забыли пароль?

Delphi.int.ru Expert

Другие разделы портала

Переход к вопросу:

#   

Статистика за сегодня:  


Лучшие эксперты

Подробнее »



Вопрос # 853

/ вопрос решён /

Приветствую, уважаемые эксперты!
У меня возник такой вопрос по парсингу строки, строку вида "7-13,6,22-40,99,54,123..." нужно разбить на составляющие числа, причем "1-13" все числа в промежутке от одного до тринадцати. Результат - получить каждое число в отдельности и те которые находятся в промежутке в первоначальном порядке.
Я все это делал с помощью pos, разбивая на части (раздилитель запятая), потом проверял наличие в каждой части "-", потом же с тем же pos определял начало и конец цикла для получения каждого числа промежутка. И затем выводил по такому же порядку как в первоначальной строке.
Есть ли более быстрый и простой способ для достижения такого же результата? Заранеее спасибо!

Phoenix Вопрос решён, но можно продолжить его обсуждение в мини-форуме

Вопрос задал: Phoenix (статус: Посетитель)
Вопрос отправлен: 14 августа 2007, 17:18
Состояние вопроса: решён, ответов: 3.

Ответ #1. Отвечает эксперт: Вадим К

Здравствуйте, Phoenix!
Я подскажу как сделать начальное разбитие.
где то такой код

var sl:TStringList;
begin
sl:=TStringList.create;
sl.delimeterchar:=\',\';
sl.delimetertext:=\'7-13,6,22-40,99,54,123\';
//Всё теперь мы имеем в sl.count количество последовательностей, а в sl[0] = \'7-13\', sl[1] = \'6\', sl[2] = \'22-40\'
sl.free;
end;
Ну а дальше уже легче

Ответ отправил: Вадим К (статус: Академик)
Время отправки: 14 августа 2007, 17:25
Оценка за ответ: 5

Комментарий к оценке: Спасибо огромное! Я с Delimiter и DelimitedText никокда не работал, а теперь буду знать!

Ответ #2. Отвечает эксперт: Матвеев Игорь Владимирович

Здравствуйте, Phoenix!
Алгоритмически более быстрое решение наврятли возможно. Как ни крути, но разбирая строку, нужно делить ее на составляющие по запятым, как ни крути нужно организовывать цикл для восстановления интервалов.

Другое дело, что Ваш вариант может быть не максимально продуктивен или, например иметь потенциальные подводные камни (от бесконечных циклов, до переполнения буфера). Существует множество библиотек парсинга и их можно было бы применить и в Вашем случае, может быть не для собственно парсинга, а посмотреть некоторые реализации и использовать у себя.

Ответ отправил: Матвеев Игорь Владимирович (статус: Студент)
Время отправки: 15 августа 2007, 03:06

Ответ #3. Отвечает эксперт: min@y™

По роду своей деятельности на работе мне предстоит написать программу управления устройством контроля монтажа электронных модулей, проще говоря - устройством прозвонки. Там должна быть заложена такая функция как прозвонка контактов, заданных пользователем, который будет их вводить именно так: "7-13,6,22-40,99,54,123...". Поэтому я вчера решил написать тебе (и, естественно, себе) работающую на 100% функцию разбора таких конструкций. Вот она:

function ParsePageNumbers(const S: PChar; Numbers: TList): Boolean;
var
  Index: Integer;
  Len, Interval: Cardinal;
  sBegin, sEnd: string; // Начальное и конечное значение интервала (строковые)
  BeginNumber, EndNumber: Cardinal; // Начальное и конечное значение интервала (неотрицательные числа)
  IsInterval, // Флаг поиска конца интевала (нашли "-" после числа)
  DigitExpected: Boolean; // Флаг поиска нового числа (после "," и "-")
begin
  Result:= false; // По умолчанию
  Numbers.Clear;
  Len:= StrLen(S); // Длина строки
 
  if (Len = 0) or not (S[0] in [\'0\'..\'9\'])
    then Exit; // строка должна быть непустой и начинаться с цифры
 
  // Инициализация переменных
  sBegin:= \'\';
  sEnd:= \'\';
  IsInterval:= false;
  DigitExpected:= false;
  Index:= -1; // !!!
 
  // Цикл разбора строки
  repeat
    Inc(Index);
 
    case S[Index] of
      \'0\'..\'9\': begin // Нашли цифру
                  // Добавляем цифру в начало или конец интервала
                  if IsInterval
                    then sEnd:= sEnd + S[Index]
                    else sBegin:= sBegin + S[Index];
 
                  DigitExpected:= false; // След. символ - не обязательно цифра
                end;
 
      \',\', #0: begin // Конец интервала или всей строки
                 if DigitExpected
                   then Exit; // Ошибка: ожидалась цифра
 
                 if IsInterval // если ищем конец интервала, то
                   then begin
                          BeginNumber:= StrToInt(sBegin); // Начало
                          EndNumber:= StrToInt(sEnd);     // конец
 
                          // Далее формируем интервал по возрастанию
                          // или убыванию соответственно
                          if BeginNumber <= EndNumber
                            then for Interval:= BeginNumber to EndNumber do // вперёд
                                   Numbers.Add(Pointer(Interval))
                            else for Interval:= BeginNumber downto EndNumber do // назад
                                   Numbers.Add(Pointer(Interval));
                        end
                   else Numbers.Add(Pointer(StrToInt(sBegin))); // иначе сразу добавляем в список
 
                   DigitExpected:= true; // След. символ - обязательно цифра!
                   IsInterval:= false;   // Ищем начало след. интервала или единичное число
                   sBegin:= \'\';   // Очистка
                   sEnd:= \'\';     // временных переменных
                 end;
 
      \'-\': begin // середина интервала
             if DigitExpected
               then Exit; // Ошибка: ожидалась цифра
 
             IsInterval:= true;    // Установка
             DigitExpected:= true; // флагов
           end;
 
      else Exit; // Ошибка: недопустимый символ
    end; //case
  until S[Index] = #0; // До конца строки
 
  Result:= true;  // Успешно
end;

Полный пример использования этой функции находится в прицепе. УДАЧИ!
К ответу прикреплён файл. Загрузить » (срок хранения: 60 дней с момента отправки ответа)

Ответ отправил: min@y™ (статус: Доктор наук)
Время отправки: 16 августа 2007, 08:14
Оценка за ответ: 5

Комментарий к оценке: Спасибо, за пример! Выглядит немного устрашающе, зато работает как надо, думаю очень пригодится.

Мини-форум вопроса

Всего сообщений: 1; последнее сообщение — 16 августа 2007, 14:36; участников в обсуждении: 1.
min@y™

min@y™ (статус: Доктор наук), 16 августа 2007, 14:36 [#1]:

Выглядит страшно, потому что сервевр обрезает всё форматирование кода. Отформатированный код выглядит очень симпотно.
Делаю лабы и курсачи по Delphi и Turbo Pascal. За ПИВО! Пишите в личку, а лучше в аську. А ещё лучше - звоните в скайп!

31 января 2011, 20:02: Статус вопроса изменён на решённый (изменил модератор Ерёмин А.А.): Автоматическая обработка (2 и более ответов с оценкой 5)

Чтобы оставлять сообщения в мини-форумах, Вы должны авторизироваться на сайте.

Версия движка: 2.6+ (26.01.2011)
Текущее время: 22 февраля 2025, 11:53
Выполнено за 0.03 сек.