2009-06-14 14 views
0

Ich schrieb dies. Ja, ich weiß, es ist VB6. Ja, es ist Produktionscode, und, ja, ich weiß, dass es Gotos verwendet. Ich bin ein faules, böses Tier ...Wie könnte ich dies umschreiben, um die gotos ohne Verlust der Geschwindigkeit oder Lesbarkeit zu entfernen?

mir So zeigen (und den Rest von uns), wie es sollte

Public Function SplitString(ByVal sText As Variant) As Variant 
    Dim nHere As Long 
    Dim cHere As String * 1 
    Dim aRes As Variant 
    Dim nRes As Long 
    Dim bInquote As Boolean 
    Dim sString As String 
    ReDim aRes(0) 
    nHere = 1 
    nRes = 0 
    Do 
    If nHere > Len(sText) Then Exit Do 
    cHere = Mid$(sText, nHere, 1) 
    If cHere = Chr$(32) Then 
     If bInquote Then 
     sString = sString & cHere 
     GoTo nextChar 
     End If 
     If sString <> vbNullString Then 
     aRes(nRes) = sString 
     sString = vbNullString 
     nRes = nRes + 1 
     ReDim Preserve aRes(nRes) 
     End If 
     GoTo nextChar 
    ElseIf cHere = Chr$(34) Then 
     bInquote = Not bInquote 
     GoTo nextChar 
    Else 
     sString = sString & cHere 
    End If 
nextChar: 
    nHere = nHere + 1 
    Loop 
    If sString <> vbNullString Then 
    aRes(nRes) = sString 
    End If 
    SplitString = aRes 
End Function 

Durch die Art und Weise geschrieben werden, teilt sie einen String in ein Array. Die Elemente in der Zeichenfolge können zitiert werden.

+3

Warum denken Sie, dass es im Moment schnell und lesbar ist? –

+0

Sagst du mir, es ist auch nicht? – bugmagnet

+0

Die DO-Schleife sollte eine Zählschleife (FOR?) Sein. Das würde das nextChar-Label überflüssig machen. Sie könnten die Dinge ein wenig optimieren, indem Sie LEN (sText) nicht bei jeder Iteration neu berechnen (es ändert sich nicht). Tatsächlich benötigen Sie selbst bei der DO-Schleife das Label nicht, wenn Sie die Space-Verarbeitung so umstrukturieren, dass ELSEIF anstelle von aufeinander folgenden IF-Anweisungen verwendet wird. –

Antwort

2

Ich stimme zu, dass dieses bestimmte Bit der Logik klar und einfach mit den Operationen Split() und Join() implementiert werden sollte. Während man immer einen langen Lauf von Inline-Code schreiben können, die dort auf sie in der Geschwindigkeit verbessert sind zwei Gründe, nicht zu:

  • wahrscheinlich Der Performance-Unterschied selten Millionen nicht einmal einen Faktor von 1,5 und eine solche Logik Ansatz verwendet wird mal auf extrem große Saiten.
  • Eine solche Inline-Logik ist nicht nur undurchsichtig und schwierig zu warten, es ist schwierig, beim ersten Schreiben des Programms richtig zu arbeiten.

Beispiel:

Function SplitString(ByVal Text As String) As String() 
    Dim Slices() As String 
    Dim UnquotedSlice As Long 

    Slices = Split(Text, """") 
    For UnquotedSlice = 0 To UBound(Slices) Step 2 
     Slices(UnquotedSlice) = Replace$(Slices(UnquotedSlice), " ", vbNullChar) 
    Next 
    SplitString = Split(Join$(Slices, ""), vbNullChar) 
End Function 

BTW: Ein großes Lob an alle, die diese Seite die perversen Code zitiert Markup beheben können oben in meinem Beispiel verwendet.

Bearbeiten: Nevermind, ich winkled es aus. Die aufgelistete Liste gab dem Parser einen Krampf.

+0

Wow, das sind beeindruckende Sachen! Ich hätte in Millionen Jahren nie an diesen Ansatz gedacht. – bugmagnet

+0

Es ist nicht perfekt. Das Auftreten mehrerer Leerzeichen außerhalb der Anführungszeichen führt zu einigen leeren Elementen im resultierenden Array. Sie können jedoch versuchen, diese Leerzeichen in jedem nicht angekreuzten "Slice" zusammenzufassen. – Bob

+0

Ah, ja, habe gerade das entdeckt und wollte es aufzeigen, aber du hast mich bis zum Anschlag geschlagen. – bugmagnet

6

Es ist ziemlich einfach:

Change "Wenn sString <> vbNullString Dann" auf "ElseIf sString <> vbNullString Then", alle "Goto" s entfernen und entfernen "nextChar:".

Public Function SplitString(ByVal sText As Variant) As Variant 
    Dim nHere As Long 
    Dim cHere As String * 1 
    Dim aRes As Variant 
    Dim nRes As Long 
    Dim bInquote As Boolean 
    Dim sString As String 
    ReDim aRes(0) 
    nHere = 1 
    nRes = 0 
    Do 
     If nHere > Len(sText) Then Exit Do 
     cHere = Mid$(sText, nHere, 1) 
     If cHere = Chr$(32) Then 
      If bInquote Then 
       sString = sString & cHere 
      ElseIf sString <> vbNullString Then 
       aRes(nRes) = sString 
       sString = vbNullString 
       nRes = nRes + 1 
       ReDim Preserve aRes(nRes) 
      End If 
     ElseIf cHere = Chr$(34) Then 
      bInquote = Not bInquote 
     Else 
      sString = sString & cHere 
     End If 

     nHere = nHere + 1 
    Loop 
    If sString <> vbNullString Then 
     aRes(nRes) = sString 
    End If 
    SplitString = aRes 
End Function 
0

Sieht ziemlich geradlinig aus. Nutzen Sie einfach die if/else-Struktur. Wenn Ihr Code in einen if-Block eintritt, wird er niemals entsprechende elseif- oder else-Blöcke eingeben. Viele Ihrer goto-Statements werden gar nicht erst benötigt.

Public Function SplitString(ByVal sText As Variant) As Variant 
    Dim nHere As Long 
    Dim cHere As String * 1 
    Dim aRes As Variant 
    Dim nRes As Long 
    Dim bInquote As Boolean 
    Dim sString As String 
    ReDim aRes(0) 
    nHere = 1 
    nRes = 0 
    Do 
     If nHere > Len(sText) Then Exit Do 
     cHere = Mid$(sText, nHere, 1) 
     If cHere = Chr$(32) Then 
      If bInquote Then 
       sString = sString & cHere 
      ElseIf sString <> vbNullString Then 
       aRes(nRes) = sString 
       sString = vbNullString 
       nRes = nRes + 1 
       ReDim Preserve aRes(nRes) 
      End If 
     ElseIf cHere = Chr$(34) Then 
      bInquote = Not bInquote 
     Else 
      sString = sString & cHere 
     End If 
     nHere = nHere + 1 
    Loop 
    If sString <> vbNullString Then 
     aRes(nRes) = sString 
    End If 
    SplitString = aRes 
End Function 
-1

Ich würde einfach die Split function und Join functions verwenden, die VB6 heimisch ist. Ich werde die Details zu Ihnen verlassen, aber der grundlegende Fluss ist auf die Räume aufzuteilen und wieder Objekte, die zwischen die Anführungszeichen sind.

Ich habe VB6 nicht in Jahren geschrieben und ich habe die Software nicht installiert (zum Debuggen), also will ich keinen Stich auf die Funktion nehmen.

Bestes Glück,
Frank

+0

Aber wenn Sie den Code zu lesen, wollte ich auch in der Lage, Strings wie teilen mein Hund "hat Flöhe" in ein Array "mein", "Hund", "hat Flöhe" – bugmagnet

+0

Und wenn Sie lesen Mein Link, Sie würden sehen, die JOIN-Funktion würde Ihnen immer noch erlauben, Ihr Konzept zu implementieren. Außerdem ist der Code nicht "lesbar". –

+0

Könnten Sie bitte auspacken, wie Split und Join die Arbeit machen? Es ist spät in der Nacht hier in Australien, und ich denke nicht so gut. – bugmagnet

1

hörte ich eine Daumenregel, die besagt, dass, wenn Ihr gehe nach vorne springt, ist es wahrscheinlich in Ordnung ist. Das sieht wie einer dieser Fälle aus. Wenn Sie jedoch die Logik eines Prädikats umkehren können, scheint es einfacher.

+0

Interessantes zum Thema. Auf der Assembler-Ebene, natürlich, alles ist ziemlich viel zu gotos (a.k.a. springt) – bugmagnet

+0

Es gibt eine andere Faustregel: nicht GOTO, wo Sie sowieso landen würden. –

2

Sie hier einen Blick haben sollte, für eine Vorstellung davon, wie subtile Optimierungen diese Art von Aufgabe auswirken:

http://www.xbeat.net/vbspeed/c_Split.htm

Sie, dass unter diesen Algorithmen sehen werden, gibt man nicht am besten ist, aber eher einige ziemlich gute und dann einige, die die Außenseiter wirklich ein bisschen besser als andere wimmern können.

Verwandte Themen