На главную Наши проекты:
Журнал   ·   Discuz!ML   ·   Wiki   ·   DRKB   ·   Помощь проекту
ПРАВИЛА FAQ Помощь Участники Календарь Избранное RSS
msm.ru
! ПРАВИЛА РАЗДЕЛА · FAQ раздела Delphi · Книги по Delphi
Пожалуйста, выделяйте текст программы тегом [сode=pas] ... [/сode]. Для этого используйте кнопку [code=pas] в форме ответа или комбобокс, если нужно вставить код на языке, отличном от Дельфи/Паскаля.
Следующие вопросы задаются очень часто, подробно разобраны в FAQ и, поэтому, будут безжалостно удаляться:
1. Преобразовать переменную типа String в тип PChar (PAnsiChar)
2. Как "свернуть" программу в трей.
3. Как "скрыться" от Ctrl + Alt + Del (заблокировать их и т.п.)
4. Как прочитать список файлов, поддиректорий в директории?
5. Как запустить программу/файл?
... (продолжение следует) ...

Вопросы, подробно описанные во встроенной справочной системе Delphi, не несут полезной тематической нагрузки, поэтому будут удаляться.
Запрещается создавать темы с просьбой выполнить какую-то работу за автора темы. Форум является средством общения и общего поиска решения. Вашу работу за Вас никто выполнять не будет.


Внимание
Попытки открытия обсуждений реализации вредоносного ПО, включая различные интерпретации спам-ботов, наказывается предупреждением на 30 дней.
Повторная попытка - 60 дней. Последующие попытки бан.
Мат в разделе - бан на три месяца...
Модераторы: jack128, D[u]fa, Shaggy, Rouse_
  
> Собрать и Разобрать строку , Как лучше
    Использую следующий шаблон для создания строки:
    "command + *#* + data[1] + *#* + data[n]"
    Как видно разделителем логических частей служит "*#*" (без кавычек), но может случчится так, что этот набор символов (*#*) может содержаться в data или/и в command.

    Помогите, пожалуйста, выбрать уникальный разделитель минимальной длины, что бы вероятность его появления в command и data Было минимальным. (я не контролирую содержание этих переменных, оно может быть любым, но его вводит пользователь с клавиатуры).

    И, соответственно, другой вопрос:
    Как эту строку порезать и перенести логические части в динамический массив?
    Я делаю так:
    ExpandedWrap disabled
        
        Information:=Copy(StringFormatedStream.DataString, 1, length(StringFormatedStream.DataString));  
        i:=0;
        SetLength(DataArray, 1);
        DataArray[0]:=UDPServer.Binding.PeerIP;
        Inc(i);
        SetLength(DataArray, 2);
        while Pos('*#*', Information)<>0 do
        begin
          DataArray[i]:=Copy(Information, 1, Pos('*#*', Information)-1);
          Delete(Information, 1, Pos('*#*', Information)+2);
          Inc(i);
          SetLength(DataArray, i+1);
        end;
        DataArray[i]:=Information;

    Но, как мне кажется, это громоздко и использует много переменных. Как оптимизировать? Может есть уже готовые функции для разделения строки?
    Сообщение отредактировано: Joni Qwest -
      Выбери разделитель такой, чтобы точно не встречался тексте полей. Например, я бы выбрал #9 - табуляция.
      Код разбора строки неоптимальный. Лучше воспользоваться конечным автоматом.
        Цитата Joni Qwest @
        Помогите, пожалуйста, выбрать уникальный разделитель минимальной длины, что бы вероятность его появления в command и data Было минимальным


        Для этого нужно знать что из себя представляют command и data.
          Цитата

          Как эту строку порезать и перенести логические части в динамический массив?
          ...
          Может есть уже готовые функции для разделения строки?


          У класса TStrings есть пара свойств: Delimiter и DelimitedText.

          В первое записываешь твой разделитель, во второе - текст с разделителями. В свойстве Items[] получаешь массив подстрок между разделителями.

          И наоборот, если Items[] уже предварительно заполнено, устанавливаешь нужный Delimiter и в св-ве DelimitedText получаешь нужную результирующую строку.

          На это
          Цитата

          Помогите, пожалуйста, выбрать уникальный разделитель минимальной длины, что бы вероятность его появления в command и data Было минимальным. (я не контролирую содержание этих переменных, оно может быть любым, но его вводит пользователь с клавиатуры).

          я затрудняюсь что-либо ответить.
            Doesntmatter
            Спасибо, попробую.
              ExpandedWrap disabled
                 {Строку с указанным разделителем раскладывает в массив строк}
                  procedure SepStrToStrings(const Source: String; const Sep: Char;
                    Strings: TStrings);
                 
                 
                implementation
                 
                // const Sep = #9; или #13
                 
                procedure SepStrToStrings(const Source: String; const Sep: Char;
                  Strings: TStrings);
                var
                  I, P, L: Integer;
                begin
                  P := 1;
                  L := Length(Source);
                  while True do begin
                    while (P <= L) and (Source[P] = Sep) do Inc(P);
                    if P > L then Break;
                    I := P;
                    while (P <= L) and (Source[P] <> Sep) do Inc(P);
                    Strings.Add(Copy(Source, I, P - I));
                  end;
                end;
                Спасибо всем, разобрался
                  Цитата Joni Qwest @
                  Помогите, пожалуйста, выбрать уникальный разделитель минимальной длины, что бы вероятность его появления в command и data Было минимальным. (я не контролирую содержание этих переменных, оно может быть любым, но его вводит пользователь с клавиатуры).

                  Если делать правильно, то не важно встречается разделитель в тексте или нет.
                  Просто надо использовать еще и например кавычки когда в значении поля встретился символ разделителя.
                  Например, посмотри свойство CommaText у tStrings.

                  Добавлено
                  Цитата Joni Qwest @
                  Как эту строку порезать и перенести логические части в динамический массив?

                  Вот держи вырезку из моего модуля awString (уже публиковавшегося на форуме):
                  интерфейс:
                  ExpandedWrap disabled
                    /////////////////////////////////////// Работа со списками строк (DelimitedText)
                    // Список строк (DelimitedText) это строка, содержащая несколько
                    // элементов разделенных Delimiter. Каждый элемент списка заключается
                    // в QuoteChar (см.AnsiQuotedStr) если он содержит "опасные"
                    // символы: [#0..' ',QuoteChar,Delimiter]
                    //
                    // Например: '"Сысоев Александр Петрович",программист,"ник:""SAP"""'
                    //
                    // Строить список строк можно например так:
                    //    s := '';
                    //    for i := 0 to Count-1 do
                    //      s := s + DelimitedQ(StringArray[I],QuoteChar,Delimiter) + Delimiter;
                    //
                    // Замечание: функции аналогичны свойствам DelimitedText и CommaText объекта
                    //            tStrings. Однако, при интерпретации списка строк есть отличия.
                    //            В tStrings (мне кажется из-за ошибки)
                    //               строка 'a,' соответствует двум элементам 'a' и ''
                    //             а строка 'a, ' соответствует одному элементу 'a' - не странно-ли?
                    //            В DelimitedText, обе строки соответствуют двум элементам 'a' и ''.
                     
                    function DelimitedQ (const Str         :String;
                                               QuoteChar   :Char = '"';
                                               Delimiter   :Char = ','         ) :String;
                    // Если Str содержит "опасные" символы: [#0..' ',QuoteChar,Delimiter], то
                    // возвращает его заключенным в QuoteChar (см.AnsiQuotedStr).
                    // Иначе, возвращает Str без изменений.
                     
                    function DelimitedText (StringArray :array of string;
                                            QuoteChar   :Char = '"';
                                            Delimiter   :Char = ','         ) :String;           overload;
                    // Возвращает список строк построенный из элементов StringArray
                    function DelimitedText (StringList  :String;
                                            QuoteChar   :Char = '"';
                                            Delimiter   :Char = ','         ) :tStringDynArray;  overload;
                    // Возвращает массив элементов постоенный из списка строк StringList
                    function DelimitedText (StringList  :String;
                                            Index       :Integer;
                                            QuoteChar   :Char = '"';
                                            Delimiter   :Char = ','         ) :String;           overload;
                    // Возвращает элемент с номером Index (0..) и списка строк StringList
                    // Если элемент с таким номером отсутствует, возвращает пустую строку.
                    function DelimitedGet  (var StringList :String;
                                                QuoteChar  :Char = '"';
                                                Delimiter  :Char = ','         ) :String;       overload;
                    // Возвращает первый элемент из списка строк StringList.
                    // Удаляет его, и следующие за ним разделители из StringList.

                  реализация
                  ExpandedWrap disabled
                    /////////////////////////////////////// Работа со списками строк (DelimitedText)
                    // Список строк (DelimitedText) это строка, содержащая несколько
                    // элементов разделенных Delimiter. Каждый элемент списка заключается
                    // в QuoteChar (см.AnsiQuotedStr) если он содержит "опасные"
                    // символы: [#0..' ',QuoteChar,Delimiter]
                    // Например: '"Сысоев Александр Петрович",программист,"ник:""SAP"""'
                     
                    function DelimitedQ (const Str         :String;
                                               QuoteChar   :Char = '"';
                                               Delimiter   :Char = ','         ) :String;
                    // Если Str содержит "опасные" символы: [#0..' ',QuoteChar,Delimiter], то
                    // возвращает его заключенным в QuoteChar (см.AnsiQuotedStr).
                    // Иначе, возвращает Str без изменений.
                    var p :PChar;
                    begin
                      Result := Str;
                      if  Result <> ''  then begin
                        // проверить, если в строке встречается хотя бы один "опасный" символ
                        // то выполнить AnsiQuotedStr
                        p := pChar(Result);
                        while not (p^ in [#0..' ', QuoteChar, Delimiter]) do
                          {$IFDEF MSWINDOWS}  p := CharNext(p);  {$ELSE}  Inc(p);  {$ENDIF}
                        if (p^ <> #0) then
                          Result := AnsiQuotedStr(Result, QuoteChar);
                      end;
                    end;
                     
                    //
                    // Обычно, список строк строится так:
                    //    s := '';
                    //    for i := 0 to Count-1 do
                    //      s := s + DelimitedQ(StringArray[I],QuoteChar,Delimiter) + Delimiter;
                    //
                    // Делать универсаьный DelimitedAdd (см.ниже) нельзя.
                    // Иначе, при
                    //   s := ''; DelimitedAdd(s,''); DelimitedAdd(s,'');
                    // в s останется пустая строка, а должно ',' - всетаки есть два пустых элемента.
                    //
                    //procedure DelimitedAdd (var StringList :String;
                    //                            Element    :String;
                    //                            QuoteChar  :Char = '"';
                    //                            Delimiter  :Char = ','         );
                    //// Добавляет к списку строк StringList строку Element
                    //begin
                    //  if  StringList<>''  then  StringList := StringList + Delimiter;
                    //  StringList := StringList + DelimitedQ(Element,QuoteChar,Delimiter);
                    //end;
                    //
                     
                    function DelimitedText (StringArray :array of string;
                                            QuoteChar   :Char = '"';
                                            Delimiter   :Char = ','         ) :String;
                    // Возвращает список строк построенный из элементов StringArray
                    var
                      i, Count: Integer;
                    begin
                      Count := Length(StringArray);
                      if (Count = 1) and (StringArray[0] = '') then
                        // единственная, пустая строка - требуется спец.обработка поскольку
                        // если этого не сделать, то результатом будет пустая строка, что
                        // соответствует отсутствию строк в списке.
                        Result := QuoteChar + QuoteChar
                      else begin
                        Result := '';
                        for i := 0 to Count-1 do
                          Result := Result + DelimitedQ(StringArray[I],QuoteChar,Delimiter) + Delimiter;
                        System.Delete(Result, Length(Result), 1);
                      end;
                    end;
                     
                     
                    function DelimitedText (StringList  :String;
                                            QuoteChar   :Char = '"';
                                            Delimiter   :Char = ','         ) :tStringDynArray;
                    // Возвращает массив элементов постоенный из списка строк StringList
                     
                      procedure Add(s :String);
                      begin
                        SetLength(Result,Length(Result)+1);
                        Result[Length(Result)-1] := s;
                      end;
                     
                    var
                      p, b: PChar;
                      s: string;
                    begin
                      SetLength(Result,0);
                      if  StringList = ''  then  Exit;
                      p := pChar(StringList);
                      while p^ <> #0 do begin
                     
                        // пропуск "пробелов" перед элементом
                        while p^ in [#1..' '] do  p:={$IFDEF MSWINDOWS}CharNext(p){$ELSE}p+1{$ENDIF};
                     
                        // прочитать элемент
                        if      p^ = QuoteChar then  // обрамленный элемент
                          s := AnsiExtractQuotedStr(p, QuoteChar)
                        else begin              // не обрамленный элемент - ограничивается Delimiter
                          b := P;              // или любым символом <= ' '
                          while (p^ > ' ') and (p^ <> Delimiter) do p:={$IFDEF MSWINDOWS}CharNext(p){$ELSE}p+1{$ENDIF};
                          SetString(s, b, p-b);
                        end;
                        Add(S);
                     
                        // пропуск "пробелов" после элемента
                        while p^ in [#1..' '] do  p:={$IFDEF MSWINDOWS}CharNext(p){$ELSE}p+1{$ENDIF};
                     
                        // пропуск Delimiter
                        if p^ = Delimiter then begin
                          p:={$IFDEF MSWINDOWS}CharNext(p){$ELSE}p+1{$ENDIF};
                          if  p^ = #0  then  Add('');
                        end;
                     
                      end;
                    end;
                     
                     
                    function DelimitedText (StringList  :String;
                                            Index       :Integer;
                                            QuoteChar   :Char = '"';
                                            Delimiter   :Char = ','         ) :String;
                    // Возвращает элемент с номером Index (0..) и списка строк StringList
                    // Если элемент с таким номером отсутствует, возвращает пустую строку.
                    var a :tStringDynArray;
                    begin
                      a := DelimitedText(StringList,QuoteChar,Delimiter);
                      if  Index < Length(a)  then
                        Result := a[Index]
                      else
                        Result := '';
                    end;
                     
                     
                    function DelimitedGet  (var StringList  :String;
                                            QuoteChar   :Char = '"';
                                            Delimiter   :Char = ','         ) :String;           overload;
                    // Возвращает первый элемент из списка строк StringList.
                    // Удаляет его, и следующие за ним разделители из StringList.
                    var
                      p, b: PChar;
                    begin
                      if  StringList = ''  then begin
                        Result := '';
                        Exit;
                      end;
                      p := pChar(StringList);
                     
                      // пропуск "пробелов" перед элементом
                      while p^ in [#1..' '] do  p:={$IFDEF MSWINDOWS}CharNext(p){$ELSE}p+1{$ENDIF};
                     
                      // прочитать элемент
                      if      p^ = QuoteChar then  // обрамленный элемент
                        Result := AnsiExtractQuotedStr(p, QuoteChar)
                      else begin              // не обрамленный элемент - ограничивается Delimiter
                        b := P;              // или любым символом <= ' '
                        while (p^ > ' ') and (p^ <> Delimiter) do p:={$IFDEF MSWINDOWS}CharNext(p){$ELSE}p+1{$ENDIF};
                        SetString(Result, b, p-b);
                      end;
                     
                      // пропуск "пробелов" после элемента
                      while p^ in [#1..' '] do  p:={$IFDEF MSWINDOWS}CharNext(p){$ELSE}p+1{$ENDIF};
                     
                      // пропуск Delimiter
                      if p^ = Delimiter then
                        p:={$IFDEF MSWINDOWS}CharNext(p){$ELSE}p+1{$ENDIF};
                     
                      Delete(StringList,1,p-pChar(StringList));
                    end;
                  0 пользователей читают эту тему (0 гостей и 0 скрытых пользователей)
                  0 пользователей:


                  Рейтинг@Mail.ru
                  [ Script execution time: 0,0352 ]   [ 16 queries used ]   [ Generated: 4.10.25, 10:57 GMT ]