Funkcja ExtractStrings - niepoprawne działanie?

0

Czy takie zachowanie funkcji ExtractStrings jak na załączonym zdjęciu jest poprawne? Wydaje mi się że nie.

Tekst Zestaw kolumny 2x6,5" z mp3 SPB-26 v2 źle rozdzielony:

blad.jpg

6

Wszystkiemu winien cudzysłów - dosłownie :]

Funkcja ta automatycznie obsługuje znaki cudzysłowu jako separatory "miękkie" - po napotkaniu tego znaku, wyodrębnia podciąg od tego napotkanego do następnego (lub do końca całego łańcucha, jeżeli drugiego nie znajdzie); Jak usuniesz cudzysłów z ciągu to dostaniesz więcej składowych;

I niestety ale to nie jest błąd - tak wygląda implementacja tej funkcji od dawien dawna; Praktyka jednak pokazuje, że jest to błąd - hardkodowana obsługa cudzysłowów uniemożliwia jej użycie dla dowolnych ciągów, obsługując jedynie te separatory i białe znaki, które faktycznie sami określimy;

Jak chcesz to mogę Ci napisać taką funkcję; Już robiłem podobną - procedura ExtractValueComponents z mojej biblioteki działa dokładnie tak jak chciałem i potrzebowałem; Dla Ciebie była by to nieco bardziej uniwersalna wersja;

Patrz mój post niżej.

0

Podejrzewam że problem sprawia znak " w stringu. Miałem podobne problemy z pewnymi znakami (teraz już nie pamiętam jakimi) więc napisałem własną procedurę której używam zamiast Extractstrings

0

Zapomniałem o jednym - jest jeszcze właściwość StrictDelimiter; Sprawdź czy po ustawieniu jej wartości na True znak cudzysłowu będzie ignorowany.

0

StrictDelimiter jest jedną z własności klasy Tstrings i dla funkcji ExtractStrings jest zupełnie nieistotna bo separacja stringów odbywa się w ciele funkcji, a tylko jej wyniki są zapisywane do obiektu klasy Tstrings

2

Tak @grzegorz_so, jednak sugeruję jej użycie, jeśli chodzi o tworzenie obiektu listy i wpisywanie ciągu znaków do listy poprzez którąś jej właściwość;

Edit: Inne rozwiązanie:

uses
  Classes;
var
  slComponents: TStringList;
  strComponent: String;
begin
  slComponents := TStringList.Create();
  try
    slComponents.Delimiter := ' ';
    slComponents.DelimitedText := 'Zestaw kolumny 2x6,5" z mp3  SPB-26 v2';

    for strComponent in slComponents do
      WriteLn('|', strComponent, '|');
  finally
    slComponents.Free();
    ReadLn();
  end;
end.

Link do sprawdzenia poprawności - http://ideone.com/bSmk7l

Kod testowany w najnowszym FPC, ale zachowanie to zapewne jest w pełni zgodne z Delphi.

0

Na stronie 4programmers.net znalazłem alternatywę dla Extracstrings

    procedure Split(Str: string; SubStr: string; List: TStrings);
    var
      I: Integer;
      S, Tmp: string;
    begin
      List.Clear;
      S := Str;
      while Length(S) > 0 do
      begin
        I := Pos(SubStr, S);
        if I = 0 then
        begin
          List.Add(S);
          S := '';
        end
        else
        begin
          if I = 1 then
          begin
            List.Add('');
            Delete(S, 1, Length(SubStr));
          end
          else
          begin
            Tmp := S;
            Delete(Tmp, I, Length(Tmp));
            List.Add(Tmp);
            Delete(S, 1, I + Length(SubStr) - 1);
            if Length(S) = 0 then
              List.Add('');
          end;
        end;
      end;
    end; 
0

@Rafał D - jeśli działa prawidłowo to możesz użyć, choć jest to procedura zła z kilku powodów; Przede wszystkim jest powolna, bo:

  • odbiera łańcuch przekazywany przez wartość (co jest najwolniejszym sposobem przekazywania łańcuchów znaków),
  • zawiera mnóstwo zbędnych operacji wykonywanych wewnątrz funkcji Pos i procedury Delete (ta pewnie jeszcze niechcący dokonuje ciągłej relokacji ciągu),
  • brak wywołań BeginUpdate i EndUpdate dla kompatybilności z listami jako właściwościami komponentamów,
  • źle zaprojektowana główna pętla;
    Ale tak wygląda używanie procedur/funkcji z biblioteki standardowej; Dla pojedynczych rozwiązań od biedy będzie, ale dla długich łańcuchów i tysięcy wywołań raczej bym nie używał :]

Wolałbym napisać ją sam, bazując na pointerach lub indeksach (oba sposoby dziś są równie szybkie), własnych pętlach wyszukujących oraz procedurze Move; Kodu wyszło by więcej, ale mógłby działać wielokrotnie szybciej, tym bardziej dla bardzo długich ciągów.

1 użytkowników online, w tym zalogowanych: 0, gości: 1