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:
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:
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;
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
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.
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
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.
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;
@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:
BeginUpdate
i EndUpdate
dla kompatybilności z listami jako właściwościami komponentamów,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.