0

私はこれを書きました。はい、私はそれがVB6であることを知っています。はい、それは製品コードであり、goto を使用していることはわかっています。私は怠け者で邪悪な獣です...

だから私に(そして私たちの残りの人たちに)それがどのように書かれるべきかを見せてください

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

ちなみに、これは文字列を配列に分割します。文字列内の要素は引用符で囲むことができます。

4

6 に答える 6

6

それはとても簡単です:

「If sString <> vbNullString Then」を「ElseIf sString <> vbNullString Then」に変更し、すべての「Goto」を削除し、「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
于 2009-06-14T13:54:35.000 に答える
2

微妙な最適化がこの種のタスクにどのように影響するかについては、こちらをご覧ください。

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

これらのアルゴリズムの中には、最適なものはなく、かなり優れたものと、外れ値を他のものよりも少しうまく処理できるものがあることがわかります。

于 2009-06-16T00:33:55.707 に答える
2

この特定のロジックは、Split() および Join() 操作を使用して明確かつ簡単に実装する必要があることに同意します。インライン コードを長時間実行して速度を向上させることはいつでもできますが、そうしない理由が 2 つあります。

  • パフォーマンスの違いは、おそらく 1.5 倍にさえ近づきません。また、そのようなロジックが非常に大きな文字列で何百万回も使用されることはめったにありません。
  • このようなインライン ロジックは、不透明で保守が難しいだけでなく、プログラムを最初に作成するときに正しく理解するのが困難です。

例:

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

ところで: このサイトが上記の例で使用しているコード引用符マークアップを修正できる人に感謝します。

編集:気にしないでください。箇条書きリストは、パーサーにけいれんを与えました。

于 2009-06-14T15:45:07.263 に答える
1

goto が前にジャンプしても、おそらく大丈夫だという経験則を聞いたことがあります。これは、それらのケースの 1 つのように見えます。ただし、述語の論理を逆にすることができれば、簡単に思えます。

于 2009-06-14T15:13:53.047 に答える
0

かなりまっすぐに見えます。if/else 構造を利用するだけです。コードが if ブロックに入ると、対応する elseif または else ブロックに入ることはありません。そもそも goto ステートメントの多くは必要ありません。

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
于 2009-06-14T13:55:12.270 に答える