String 我如何重写它以删除gotos而不损失速度或可读性?

String 我如何重写它以删除gotos而不损失速度或可读性?,string,vb6,split,goto,String,Vb6,Split,Goto,这是我写的。是的,我知道是VB6。是的,这是生产代码,而且,是的,我知道它使用gotos。我是一个懒惰、邪恶的野兽 所以,让我(和我们其他人)看看应该怎么写 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 bInqu

这是我写的。是的,我知道是VB6。是的,这是生产代码,而且,是的,我知道它使用gotos。我是一个懒惰、邪恶的野兽

所以,让我(和我们其他人)看看应该怎么写

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
Public函数SplitString(ByVal sText作为变量)作为变量
他和我一样长
将切丽调暗为字符串*1
Dim aRes作为变体
只要
Dim bInquote作为布尔值
将字符串变暗为字符串
雷迪姆战神(0)
nHere=1
nRes=0
做
如果nHere>Len(sText),则退出Do
cHere=Mid$(sText,nHere,1)
如果cHere=Chr$(32),则
如果是这样的话
sString=sString&cHere
下一步
如果结束
如果sString vbNullString,则
aRes(nRes)=sString
sString=vbNullString
nRes=nRes+1
雷迪姆保护区(NRE)
如果结束
下一步
ElseIf cHere=Chr$(34)然后
bInquote=不是bInquote
下一步
其他的
sString=sString&cHere
如果结束
下一步:
nHere=nHere+1
环
如果sString vbNullString,则
aRes(nRes)=sString
如果结束
SplitString=aRes
端函数
顺便说一下,它将字符串拆分为数组。字符串中的元素可以被引用。

非常简单:

将“If-sString-vbNullString-Then”更改为“ElseIf-sString-vbNullString-Then”,删除所有“Goto”并删除“nextChar:”

Public函数SplitString(ByVal sText作为变量)作为变量
他和我一样长
将切丽调暗为字符串*1
Dim aRes作为变体
只要
Dim bInquote作为布尔值
将字符串变暗为字符串
雷迪姆战神(0)
nHere=1
nRes=0
做
如果nHere>Len(sText),则退出Do
cHere=Mid$(sText,nHere,1)
如果cHere=Chr$(32),则
如果是这样的话
sString=sString&cHere
ElseIf sString vbNullString然后
aRes(nRes)=sString
sString=vbNullString
nRes=nRes+1
雷迪姆保护区(NRE)
如果结束
ElseIf cHere=Chr$(34)然后
bInquote=不是bInquote
其他的
sString=sString&cHere
如果结束
nHere=nHere+1
环
如果sString vbNullString,则
aRes(nRes)=sString
如果结束
SplitString=aRes
端函数

看起来很直截了当。只需使用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
Public函数SplitString(ByVal sText作为变量)作为变量
他和我一样长
将切丽调暗为字符串*1
Dim aRes作为变体
只要
Dim bInquote作为布尔值
将字符串变暗为字符串
雷迪姆战神(0)
nHere=1
nRes=0
做
如果nHere>Len(sText),则退出Do
cHere=Mid$(sText,nHere,1)
如果cHere=Chr$(32),则
如果是这样的话
sString=sString&cHere
ElseIf sString vbNullString然后
aRes(nRes)=sString
sString=vbNullString
nRes=nRes+1
雷迪姆保护区(NRE)
如果结束
ElseIf cHere=Chr$(34)然后
bInquote=不是bInquote
其他的
sString=sString&cHere
如果结束
nHere=nHere+1
环
如果sString vbNullString,则
aRes(nRes)=sString
如果结束
SplitString=aRes
端函数
我只需使用和,这是VB6的固有特性。我将把细节留给您,但基本流程是在空格上拆分,然后重新连接引号之间的对象

我已经好几年没写VB6了,也没有安装软件(用于调试),所以我不想尝试这个功能

祝你好运,

弗兰克

我听到一条经验法则说,如果你的goto向前跳,可能没问题。这看起来像是其中之一。但是,如果可以反转谓词的逻辑,似乎更容易。

我同意,应该使用Split()和Join()操作清楚、轻松地实现这一特定的逻辑。尽管人们总是可以编写长时间运行的内联代码来提高速度,但有两个理由不这样做:

  • 性能差异可能甚至不会接近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
顺便说一句:任何人都可以修复这个网站在我上面的例子中使用的错误代码引用标记,这真是太好了


编辑:没关系,我把它弄出来了。带项目符号的列表让解析器感到一阵痉挛。

您应该看看这里,了解微妙的优化如何影响这类任务:


你会发现,在这些算法中,没有一个是最好的,而是一些非常好的,然后是一些比其他算法更好的算法。

为什么你认为它现在速度快,可读性好?你是说两者都不是?do循环应该是一个计数(FOR?)循环。这将消除对nextChar标签的需要。通过在每次迭代中不重新计算LEN(sText)(它不会改变),您可能会对事情进行一些优化。实际上,即使使用DO循环,如果您将空间处理重新构造为使用ELSEIF而不是连续的if语句,您也不需要标签。但是如果您阅读了代码,我还希望能够将字符串(如我的狗“有跳蚤”)拆分为数组“我的”,“狗”,“有跳蚤”,如果您阅读了我的链接,您会看到JOIN函数仍然允许您实现您的概念。此外,代码不可读。请合作
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