ABOUT Visual Basic Programmieren Programmierung Download Downloads Tips & Tricks Tipps & Tricks Know-How Praxis VB VBA Visual Basic for Applications VBS VBScript Scripting Windows ActiveX COM OLE API ComputerPC Microsoft Office Microsoft Office 97 Office 2000 Access Word Winword Excel Outlook Addins ASP Active Server Pages COMAddIns ActiveX-Controls OCX UserControl UserDocument Komponenten DLL EXE
Diese Seite wurde zuletzt aktualisiert am 12.03.2001

Diese Seite wurde zuletzt aktualisiert am 12.03.2001
Aktuell im ABOUT Visual Basic-MagazinGrundlagenwissen und TechnologienKnow How, Tipps und Tricks rund um Visual BasicActiveX-Komponenten, Controls, Klassen und mehr...AddIns für die Visual Basic-IDE und die VBA-IDEVBA-Programmierung in MS-Office und anderen AnwendungenScripting-Praxis für den Windows Scripting Host und das Scripting-ControlTools, Komponenten und Dienstleistungen des MarktesRessourcen für Programmierer (Bücher, Job-Börse)Dies&Das...

Themen und Stichwörter im ABOUT Visual Basic-Magazin
Code, Beispiele, Komponenten, Tools im Überblick, Shareware, Freeware
Ihre Service-Seite, Termine, Job-Börse
Melden Sie sich an, um in den vollen Genuss des ABOUT Visual Basic-Magazins zu kommen!
Informationen zum ABOUT Visual Basic-Magazin, Kontakt und Impressum

Zurück...

Split-Findigkeiten

Zurück...


Anzeige

(-hg) mailto:hg_splitquotesspaces@aboutvb.de

In Dateilisten in String-Form, wie sie etwa Anwendungen als Kommandozeile übergeben werden, und die Sie in Visual Basic von MSDN-Library - VB CommandCommand$ geliefert bekommen, sind die einzelnen Dateinamen oftmals per Leerzeichen voneinander getrennt. Einen solchen Listen-String können Sie in Visual Basic 6 einfach mit der MSDN-Library - VB SplitSplit-Funktion in seine einzelnen Bestandteile zerlegen, etwa:

Split("abc.txt def.txt ghi.txt jkl.txt", " ")

Die Funktion gibt ein Array mit den einzelnen Bestandteilen als Elemente zurück.

Diese einfache Anwendung der Split-Funktion ist allerdings untauglich, wenn die Dateinamen selbst Leerzeichen enthalten. Das Betriebssystem "klammert" solche Dateinamen in Anführungszeichen ein. Eine Zerlegung mit Split würde die Dateinamen an den Stellen ihrer Leerzeichen unbarmherzig zerlegen. Der String

abc.txt "de fg.txt" hij.txt klm.txt "no p q.txt" "rs tu.txt" vwx.txt

würde zerlegt in:

abc.txt
"de
fg.txt"
hij.txt
klm.txt
"no
p
q.txt"
"rs
tu.txt"
vwx.txt

Sie können nun auf die Split-Funktion verzichten und mehr oder weniger aufwändig mit Abzählen beginnen und dabei den gesamten String Zeichen für Zeichen von Anfang bis Ende durchlaufen. Wenn Sie sich nicht beim Zählen und Merken und Trennen verheddern, werden Sie sicher zum Ziel gelangen, irgendwie. Aber abgesehen von der Gefahr des Verhedderns ist eine solche Zeichen-für-Zeichen-Schleife nicht sonderlich effizient.

Erheblich effizienter ist es, das anscheinend unbrauchbare Resultat, das Sie von Split geliefert bekommen, aufzugreifen und lediglich zu bereinigen. Wie Sie an obenstehender Folge sehen können, beginnt ein Array-Alement mit einem Anführungszeichen, wenn es der erste Teil eines zerrissenen Teiles ist, und es endet mit einem Anführungszeichen, wenn es der letzte Teil ist. Sie können also das Array in einer Schleife durchlaufen, sich dabei Anfang und Ende eines zerrissenen Teiles merken und dazwischen die Bruchstücke einfügen. Dabei verschieben Sie die fertig zusammengefügten Teile einfach aufeinanderfolgend aufwärts und kappen die zum Schluss überzähligen Array-Elemente mit einem ReDim Preserve. Je nach dem, ob die ursprünglich zur Einklammerung dienenden Anführungszeichen beibehalten werden sollen, oder ob sie entfallen sollen, können Sie sie entfernen oder stehen lassen. Sollte die Stringliste von vornherein keine Anführungszeichen enthalten, können Sie natürlich auf den Schleifendurchlauf verzichten.

Public Function SplitQuotesSpaces1(Str As String, _
 Optional ByVal KeepQuotes As Boolean) As String()

  Dim nParts() As String
  Dim nInside As Boolean
  Dim i As Integer
  Dim ii As Integer

  nParts = Split(Str, " ")
  If InStr(Str, Chr$(34)) Then
    For i = 0 To UBound(nParts)
      If Left$(nParts(i), 1) = Chr$(34) Then
        If Not KeepQuotes Then
          nParts(ii) = Mid$(nParts(i), 2)
        End If
        nInside = True
      ElseIf Right$(nParts(i), 1) = Chr$(34) Then
        If Not KeepQuotes Then
          nParts(ii) = nParts(ii) & " " & Left$(nParts(i), _
           Len(nParts(i)) - 1)
        Else
          nParts(ii) = nParts(ii) & " " & nParts(i)
        End If
        ii = ii + 1
        nInside = False
      ElseIf nInside Then
        nParts(ii) = nParts(ii) & " " & nParts(i)
      Else
        nParts(ii) = nParts(i)
        ii = ii + 1
      End If
    Next 'i
    ReDim Preserve nParts(0 To ii - 1)
  End If
  SplitQuotesSpaces1 = nParts
End Function

Eine andere Möglichkeit sieht auf den ersten Blick ziemlich widersinnig aus, weil der den einschließenden Anführungszeichen zugrunde liegende Paar-Gedanke zunächst völlig ignoriert wird. Hierbei wird der String zunächst mit der Split-Funktion anhand der Anführungszeichen als Trennzeichen zerlegt. Das Resultat sieht zunächst so aus (ich habe die Leerzeichen zur Kenntlichmachung durch rote Sternchen ersetzt):

abc.txt*
de*fg.txt
*hij.txt*klm.txt*
no*p*q.txt
*
rs*tu.txt
*vwx.txt

Aber auch hier ist ein brauchbares und programmatisch auswertbares Schema zu erkennen. Zunächst haben alle Teile, die mit einem Leerzeichen beginnen oder enden, zuvor keine Leerzeichen enthalten. Sie sind also recht einfach durch Trimmen der Leerzeichen zurecht zu stutzen. Enthalten diese Teile immer noch (ein) Leerzeichen, ist bzw. sind diese(s) tatsächliche Trenner, und der Teil-String kann noch einmal einfach per Split-Funktion aufgeteilt werden. Besteht aus einem Teil nur noch aus einem Leerzeichen, oder nach dem Trimmen nur noch aus einem Leeren String, braucht er nicht weiter berücksichtigt zu werden. Schließlich bleiben noch die Teile zu berücksichtigen, die nicht mit einem Leerzeichen beginnen oder enden, aber dennoch mindestens ein Leerzeichen enthalten. Diese Teile waren ursprünglich von Anführungszeichen eingeschlossen (die Sie gegebenenfalls wieder hinzufügen können). Sie durchlaufen einfach alle Teile, bearbeiten sie entsprechend und fügen sie in ein neues Array ein, das sie bei Bedarf in größeren Schüben mit ReDim Preserve vergrößern müssen. Sollten Sie es zufällig über den tatsächlichen Bedarf hinaus vergrößert haben, stutzen Sie es zum Schluss wieder zurück. Auch hier erübrigt sich natürlich die ganze Bastelei, wenn der Anfangs-String schon gar keine Anführungszeichen enthalten hat.

Public Function SplitQuotesSpaces2(Str As String, _
 Optional ByVal KeepQuotes As Boolean) As String()

  Dim nPartsQuotes() As String
  Dim i As Integer
  Dim nPartsStr() As String
  Dim nTestTrim As String
  Dim nPartPartsStr() As String
  Dim ii As Integer
  Dim nCount As Integer
  Dim nBlock As Integer
  
  If InStr(Str, Chr$(34)) Then
    nPartsQuotes = Split(Str, Chr$(34))
    nBlock = UBound(nPartsQuotes)
    ReDim nPartsStr(0 To nBlock)
    For i = 0 To nBlock
      nTestTrim = Trim$(nPartsQuotes(i))
      Select Case True
        Case nTestTrim <> nPartsQuotes(i)
          nPartPartsStr = Split(nTestTrim, " ")
          For ii = 0 To UBound(nPartPartsStr)
            nPartsStr(nCount) = nPartPartsStr(ii)
            nCount = nCount + 1
            If nCount > nBlock Then
              nBlock = nBlock + 5
              ReDim Preserve nPartsStr(0 To nBlock)
            End If
          Next 'ii
        Case Len(nTestTrim) = 0
        Case Else
          If KeepQuotes Then
            nPartsStr(nCount) = Chr$(34) & nPartsQuotes(i) & Chr$(34)
          Else
            nPartsStr(nCount) = nPartsQuotes(i)
          End If
          nCount = nCount + 1
          If nCount > nBlock Then
            nBlock = nBlock + 5
            ReDim Preserve nPartsStr(0 To nBlock)
          End If
      End Select
    Next 'i
    ReDim Preserve nPartsStr(0 To nCount - 1)
    SplitQuotesSpaces2 = nPartsStr
  Else
    SplitQuotesSpaces2 = Split(Trim$(Str), " ")
  End If
End Function

Dass beide Verfahren nur dann sauber und fehlerfrei funktionieren können, wenn die Ausgangs-String "sauber" vorliegen, versteht sich von selbst. Beide kommen ins Schleudern, wenn sich etwa zwischen einleitendem Anführungszeichen und eingeschlossenem String oder zwischen diesem und dem abschließenden Anführungszeichen weitere Leerzeichen befinden (bei Dateinamen bzw. Pfadangaben an sich eine Unmöglichkeit).

Sie werden sich (und mich) nun fragen, welche der beiden Varianten die bessere, empfehlenswertere sei. Dazu kann ich nach einigen Zeit-Messungen nur sagen, dass bei kurzen Ausgangs-Strings die erste Variante ungefähr ein Drittel schneller ist. Aufgabenstellungen, bei denen solche kurzen String-Listen vorkommen, sind jedoch allermeistens nicht zeitkritisch - es ist also egal. Die zweite Variante mag vielleicht eher ein wenig wegen ihres größeren Umfangs und ihres etwas verqueren Prinzips abschreckend wirken.

Doch je länger der Ausgangs-String ist, je länger die Teil-Strings sind und je mehr in Anführungszeichen eingeschlossene Teile im Ausgangs-String enthalten sind, um so mehr holt die zweite Variante gegenüber der ersten auf und überholt sie schließlich. Dies liegt vor allem daran, dass die erste Variante weitaus ausgiebiger Gebrauch von String-Operationen macht, bei denen Teil-Strings hin und her kopiert werden. Eine solche Kopiererei frisst grundsätzlich immer Performance und benachteiligt die erste Variante zunehmend.

Die zweite Variante habe ich Ihnen aber auch noch aus einem anderen Grund gezeigt. Es sieht nämlich derart widersinnig und zunächst entgegengesetzt der ursprünglichen Aufgabenstellung aus, dass man sie vom "natürlichen Programmierer-Menschenverstand" her eher erst gar nicht in Erwägung zieht. Doch mag gerade erst dieser Ansatz bei so manch kompliziert und an kaum einer Regel festmachbaren Teilungsaufgabe eine brauchbare Grundlage ergeben. Setzen Sie sich doch einfach einmal damit an andere Paarungs-Probleme, etwa an Klammerungen in mathematischen Ausdrücken oder an Strings voller HTML-("<...>")-Tags...


Modul modSplitQuotesSpaces (modSplitQuotesSpaces.bas - ca. 3,3 KB)


Artikel
Zum Download-Bereich dieses Artikel
Mail an den Autor dieses Artikels

KnowHow
Zur KnowHow-Übersicht

KnowHow-Themen
Themen - Allgemeines
Themen - Entwicklungsumgebung (VB-IDE)
Themen - Forms
Themen - Steuerelemente (Controls)
Themen - Grafik
Themen - Dateien
Themen - UserControls
Themen - Einsteiger-Tipps
Themen - Wussten Sie...?

Übersicht nach Titeln in alphabetischer Reihenfolge
Übersicht nach Erscheinungsdatum

Schnellsuche




Zum Seitenanfang

Copyright © 1999 - 2017 Harald M. Genauck, ip-pro gmbh  /  Impressum

Zum Seitenanfang

Zurück...

Zurück...

Download Internet Explorer