2013-03-15 19 views
16

Esiste una funzione Delphi per dividere la stringa da un delimitatore a più caratteri anziché da un singolo carattere?Come dividere la stringa con un delimitatore a più caratteri?

Per esempio quando mi piacerebbe usare quella funzione in questo modo:

SplitString('Whale<->Mammal<->Ocean', '<->') 

vorrei ottenere un risultato di questi 3 stringhe:

'Whale', 'Mammal', 'Ocean' 

C'è una tale funzione in Delphi per questo?

+2

A tutti voi vicino gli elettori: si prega di leggere entrambe le domande. Questo non è un dupe di http://stackoverflow.com/questions/2625707/split-a-string-into-an-array-of-strings-based-on-a-delimiter –

risposta

2

Non so se Delphi ha una procedura di split standard che utilizza una stringa come delimitatore. Ma si può scrivere il proprio o si ha o no:

procedure SplitStr(const Source, Delimiter: String; var DelimitedList: TStringList); 
var 
    s: PChar; 

    DelimiterIndex: Integer; 
    Item: String; 
begin 
    s:=PChar(Source); 

    repeat 
    DelimiterIndex:=Pos(Delimiter, s); 
    if DelimiterIndex=0 then Break; 

    Item:=Copy(s, 1, DelimiterIndex-1); 

    DelimitedList.Add(Item); 

    inc(s, DelimiterIndex + Length(Delimiter)-1); 
    until DelimiterIndex = 0; 
    DelimitedList.Add(s); 
end; 

procedure TForm1.Button1Click(Sender: TObject); 
var 
    sl: TStringList; 
begin 
    sl:=TStringList.Create; 
    SplitStr('delphi++split++string++','++',sl); 
    //do something with the list 
    sl.Free; 
end; 

Speranza che aiuta ..

3

Non esiste una funzione 'da scatola'. Se le stringhe contengono regolare testo 'buono', quindi è possibile utilizzare StringReplace con il simbolo esotico, altrimenti non è difficile scrivere una propria funzione di divisione utilizzando Pos o IdStrings.SplitString (se è disponibile in D2010)

function SplitStringByStr(const S, StrDelimiter: string): TStringDynArray; 
var 
    tmp: string; 
begin 
    tmp := StringReplace(S, StrDelimiter, '`', [rfReplaceAll]); 
    Result := SplitString(tmp, '`'); 
end; 
+0

L'unico problema che posso vedere con cioè se il testo contiene il 'simbolo esotico', questo metodo non funzionerà (come hai sottolineato). – awmross

+2

In genere, è possibile trovare un "simbolo esotico" che non viene utilizzato nelle stringhe da qualche parte nelle parti non stampabili dell'ASCII, ad esempio # 13 (ritorno a capo) o # 8 (campanello). – gabr

7

Puoi controllare la mia unità StringUtils.pas che fa parte di Cromis Library

C'è un semplice tokenizzatore di testo lì. Ma probabilmente è proprio quello di cui hai bisogno. L'interfaccia è simile a

TTextTokenizer = class 
    private 
    FTokens: TTokens; 
    FDelimiters: array of ustring; 
    public 
    constructor Create; 
    procedure Tokenize(const Text: ustring); 
    procedure AddDelimiters(const Delimiters: array of ustring); 
    property Tokens: TTokens read FTokens; 
    end; 

Suporta stringhe come delimitatori e anche più di un delimitatore.

+0

Non avevo mai sentito parlare di Cromis prima. Cromis ha qualche test unitario? Non sono riuscito a trovarne nessuno nello zip di download. Inoltre, sarebbe opportuno sfogliare il codice online o almeno una documentazione dell'API (solo un suggerimento) – awmross

+0

È una libreria che utilizzo in molti codici di produzione e li condivido per altri, se lo desiderano. Devo ancora coprire alcune unità con dei test. Per la maggior parte dei pezzi importanti ho programmi demo che coprono la maggior parte delle funzionalità. Estenderò la copertura del test e renderò pubblico SVN. Ma la documentazione sarà probabilmente molto tardi visto che non ho molto tempo in questi giorni. Alcuni componenti sono abbastanza usati da molte persone, specialmente IPC e Scheduler. – Runner

+0

credendo alle fonti che hai postato in un'altra risposta, viene tokenizzato una sola volta per ogni sui delimitatori, e su tutti loro in qualsiasi ordine casuale sono soddisfatti. –

33

C'è un'altra soluzione piuttosto semplice che utilizza TStringList. Modificare l'interruzione di riga:

procedure TForm208.Button1Click(Sender: TObject); 
var 
    lst: TStringList; 
begin 
    lst := TStringList.Create; 
    try 
    lst.LineBreak := '<->'; 
    lst.Text := 'Whale<->Mammal<->Ocean'; 
    Memo1.Lines := lst; 
    finally 
    lst.Free; 
    end; 
end; 
+4

Questo è pulito :) – Runner

+1

+1 Mi piace molto. –

+0

Dovresti usare "StrictDelimiter"? O non importa in questo caso? – awmross

4

Se avete installato JCL poi nell'unità jclStrings c'è StrToStrings procedura:

var sl: TStringList; 
begin 
    sl := TStringList.Create; 
    StrToStrings('Whale<->Mammal<->Ocean' , '<->' , sl); 
Problemi correlati