Карта сайта Kansoftware
НОВОСТИУСЛУГИРЕШЕНИЯКОНТАКТЫ
KANSoftWare

sscanf в Delphi

Delphi , Синтаксис , Текст и Строки

sscanf в Delphi

Некоторое время назад одна любезная душа прислала мне этот модуль. Я нашел его весьма полезным, но применять его вам надлежит с некоторой долей осторожности, ибо тэг %s иногда приводит к исключительным ситуациям.


unit Scanf;

interface
uses SysUtils;

type

  EFormatError = class(ExCeption);

function Sscanf(const s: string; const fmt: string;
  const Pointers: array of Pointer): Integer;
implementation

{ Sscanf выполняет синтаксический разбор входной строки. Параметры...

s - входная строка для разбора
fmt - 'C' scanf-форматоподобная строка для управления разбором
%d - преобразование в Long Integer
%f - преобразование в Extended Float
%s - преобразование в строку (ограничено пробелами)
другой символ - приращение позиции s на "другой символ"
пробел - ничего не делает
Pointers - массив указателей на присваиваемые переменные

результат - количество действительно присвоенных переменных

Например, ...
Sscanf('Name. Bill   Time. 7:32.77   Age. 8',
'. %s . %d:%f . %d', [@Name, @hrs, @min, @age]);

возвратит ...
Name = Bill  hrs = 7  min = 32.77  age = 8 }

function Sscanf(const s: string; const fmt: string;

  const Pointers: array of Pointer): Integer;
var

  i, j, n, m: integer;
  s1: string;
  L: LongInt;
  X: Extended;

  function GetInt: Integer;
  begin
    s1 := '';
    while (s[n] = ' ') and (Length(s) > n) do
      inc(n);
    while (s[n] in ['0'..'9', '+', '-'])
      and (Length(s) >= n) do
    begin
      s1 := s1 + s[n];
      inc(n);
    end;
    Result := Length(s1);
  end;

  function GetFloat: Integer;
  begin
    s1 := '';
    while (s[n] = ' ') and (Length(s) > n) do
      inc(n);
    while (s[n] in ['0'..'9', '+', '-', '.', 'e', 'E'])
      and (Length(s) >= n) do
    begin
      s1 := s1 + s[n];
      inc(n);
    end;
    Result := Length(s1);
  end;

  function GetString: Integer;
  begin
    s1 := '';
    while (s[n] = ' ') and (Length(s) > n) do
      inc(n);
    while (s[n] <> ' ') and (Length(s) >= n) do
    begin
      s1 := s1 + s[n];
      inc(n);
    end;
    Result := Length(s1);
  end;

  function ScanStr(c: Char): Boolean;
  begin
    while (s[n] <> c) and (Length(s) > n) do
      inc(n);
    inc(n);

    if (n <= Length(s)) then
      Result := True
    else
      Result := False;
  end;

  function GetFmt: Integer;
  begin
    Result := -1;

    while (TRUE) do
    begin
      while (fmt[m] = ' ') and (Length(fmt) > m) do
        inc(m);
      if (m >= Length(fmt)) then
        break;

      if (fmt[m] = '%') then
      begin
        inc(m);
        case fmt[m] of
          'd': Result := vtInteger;
          'f': Result := vtExtended;
          's': Result := vtString;
        end;
        inc(m);
        break;
      end;

      if (ScanStr(fmt[m]) = False) then
        break;
      inc(m);
    end;
  end;

begin

  n := 1;
  m := 1;
  Result := 0;

  for i := 0 to High(Pointers) do
  begin
    j := GetFmt;

    case j of
      vtInteger:
        begin
          if GetInt > 0 then
          begin
            L := StrToInt(s1);
            Move(L, Pointers[i]^, SizeOf(LongInt));
            inc(Result);
          end
          else
            break;
        end;

      vtExtended:
        begin
          if GetFloat > 0 then
          begin
            X := StrToFloat(s1);
            Move(X, Pointers[i]^, SizeOf(Extended));
            inc(Result);
          end
          else
            break;
        end;

      vtString:
        begin
          if GetString > 0 then
          begin
            Move(s1, Pointers[i]^, Length(s1) + 1);
            inc(Result);
          end
          else
            break;
        end;

    else
      break;
    end;
  end;
end;

end.

Перевод контента на русский язык:

Это реализация функции sscanf в Delphi, которая похожа на соответствующую функцию из библиотеки C. Функция принимает три параметра: s (входная строка), fmt (строка форматирования, аналогичная тем, которые используются в scanf), и Pointers (массив указателей на переменные, которые получат парсированные значения).

Реализация использует серию вспомогательных функций (GetInt, GetFloat, GetString) для парсинга входной строки по форматному спецификации. Основной цикл проходит по строке форматирования, парсит каждый поле и присваивает его соответствующей переменной.

Вот некоторые заметки о коде:

  • Класс исключения EFormatError определён в верхней части модуля, но не используется в реализации.
  • Функция GetFmt используется для парсинга строки форматирования и определения типа значения, ожидаемого для каждого поля. Это делается путем сканирования строки форматирования по символам %, за которыми следует одиночный символ (d, f или s), указывающий тип значения.
  • Функция ScanStr используется для сканирования входной строки в поисках конкретного символа (например, пробела, цифры и т.д.). Она возвращает True, если символ найден, и False в противном случае.
  • В основном цикле реализация использует простой оператор break для выхода из цикла ранее, когда она находит неожиданный форматный спецификатор или обработала все поля в входной строке.

В отношении потенциальных проблем с форматными спецификаторами %s, вы правы, что они могут вызывать проблемы, если не используются осторожно. В этой реализации форматный спецификатор %s обрабатывается вызовом функции GetString, которая сканирует входную строку до обнаружения символа пробела (или конца строки). Если входная строка содержит несколько пробелов или другие символы whitespace, это может потенциально привести к неожиданному поведению.

Вот некоторые потенциальные улучшения, которые можно сделать в коде:

  • Добавьте более полное обслуживание ошибок и механизмы журналирования для помощи в диагностике проблем с недопустимыми строками форматирования или входными данными.
  • Рассмотрите использование библиотеки регулярных выражений (например, TPregExp в Delphi) для улучшения парсинга форматных спецификаторов и значений ввода.
  • Реализуйте поддержку дополнительных форматных спецификаторов, таких как %c для символов или %p для указателей.
  • Добавьте более полное тестирование модуля для обеспечения корректной работы реализации для различных случаев ввода.

В статье описывается модуль Sscanf для Delphi, который выполняет синтаксический разбор входной строки в соответствии с форматом scanf и позволяет присваивать значения переменным.


Комментарии и вопросы

Получайте свежие новости и обновления по Object Pascal, Delphi и Lazarus прямо в свой смартфон. Подпишитесь на наш Telegram-канал delphi_kansoftware и будьте в курсе последних тенденций в разработке под Linux, Windows, Android и iOS




Материалы статей собраны из открытых источников, владелец сайта не претендует на авторство. Там где авторство установить не удалось, материал подаётся без имени автора. В случае если Вы считаете, что Ваши права нарушены, пожалуйста, свяжитесь с владельцем сайта.


:: Главная :: Текст и Строки ::


реклама


©KANSoftWare (разработка программного обеспечения, создание программ, создание интерактивных сайтов), 2007
Top.Mail.Ru

Время компиляции файла: 2024-08-19 13:29:56
2024-11-21 13:22:27/0.0060009956359863/1