Foro de elhacker.net

Programación => Programación Visual Basic => Mensaje iniciado por: 79137913 en 14 Marzo 2011, 15:20 pm



Título: [SOURCE] MultiSplit7913 Un split diferente XD
Publicado por: 79137913 en 14 Marzo 2011, 15:20 pm
HOLA!!!

Hoy queria hacer un split que devuelva un array con varios delimitadores y aparte tenga la opcion de guardar el delimitador... en fin... hice esta funcion, espero que les sirva.

Antes que el codigo Ejemplo:

Código
  1. Private Sub Ejemplo()
  2. Dim dels(3) As String
  3. Dim result() As String
  4. Const ss As String = "hola+como--andas(((esto====es+una--prueba"
  5.    dels(0) = "+"
  6.    dels(1) = "--"
  7.    dels(2) = "((("
  8.    dels(3) = "===="
  9.  
  10.    'sin preservar delimitadores
  11.    result = MultiSplit7913(ss, dels, False)
  12.    'result = ("hola";"como";"andas";"esto";"es";"una";"prueba")
  13.  
  14.    'preservando delimitadores
  15.    result = MultiSplit7913(ss, dels, True)
  16.    'result = ("hola";"+como";"--andas";"(((esto";"====es";"+una";"--prueba")
  17. End Sub

El Codigo

Código
  1. Private Function MultiSplit7913(expression As String, Delimiter() As String, PreserveDel As Boolean) As String()
  2. Dim DelCount    As Long
  3. Dim lExp        As Long
  4. Dim X           As Long
  5. Dim Pos         As Long
  6. Dim DelPos()    As Long
  7. Dim AuxArr()    As String
  8. Dim LastPos     As Long
  9. Dim LastLen     As Long
  10. Dim LastInstr   As Long
  11.  
  12.    expression = expression & Delimiter(0)
  13.    lExp = Len(expression)
  14.    DelCount = UBound(Delimiter)
  15.    ReDim DelPos(lExp)
  16.  
  17.    For X = 0 To DelCount
  18.        Pos = 1
  19.        LastInstr = InStr(Pos, expression, Delimiter(X))
  20.        Do While LastInstr <> 0
  21.            DelPos(LastInstr) = X + 1
  22.            Pos = LastInstr + Len(Delimiter(X)) + Pos
  23.            LastInstr = InStr(Pos, expression, Delimiter(X))
  24.        Loop
  25.    Next
  26.  
  27.    ReDim AuxArr(0)
  28.  
  29.    LastPos = 1
  30.  
  31.    For X = 0 To lExp
  32.        If DelPos(X) <> 0 Then
  33.            ReDim Preserve AuxArr(UBound(AuxArr) + 1)
  34.            If PreserveDel Then
  35.                AuxArr(UBound(AuxArr) - 1) = Mid$(expression, LastPos, X - LastPos)
  36.            Else
  37.                AuxArr(UBound(AuxArr) - 1) = Mid$(expression, LastPos + LastLen, X - LastPos - LastLen)
  38.                LastLen = Len(Delimiter(DelPos(X) - 1))
  39.            End If
  40.            LastPos = X
  41.        End If
  42.    Next
  43.  
  44.    ReDim Preserve AuxArr(UBound(AuxArr) - 1)
  45.  
  46.    MultiSplit7913 = AuxArr
  47.  
  48. End Function
  49.  

GRACIAS POR LEER!!!


Título: Re: [SOURCE] MultiSplit7913 Un split diferente XD
Publicado por: raul338 en 14 Marzo 2011, 15:39 pm
Funciona, pero lo podrias mejorar ;)

Aqui te van unos ejemplos :)

  • Podrias ahorrarte las 3 llamadas a InStr guardandolas en una sola variable :xD
  • En lugar de guardar las posiciones con un flag, guarda en un array las posiciones de los delimitadores, asi despues evitas volver a recorrer la cadena (segundo for) y solo recorres el array y haces un mid, ya que tienes la posicion en el arreglo

Por lo demas, Esta buena la idea :)


Título: Re: [SOURCE] MultiSplit7913 Un split diferente XD
Publicado por: 79137913 en 14 Marzo 2011, 15:49 pm
HOLA!!!

Mmm, en cuanto al punto 1 si, lo voy a cambiar.

En cuanto al punto 2... En ese array que decis, ademas de la posicion del delimitador debo guardar el delimitador (osea delimitador(0) en posicion 3) eso me obliga a usar 2 vectores o una matriz, al usar una matriz tendria que saltar los espacios blancos que hay, pero si uso 2 vectores uno para la posicion y otro para el delimitador mmm... podria ser voy a probar.

Me dio fiaca hacer el punto 2 XD

GRACIAS POR LEER!!!


Título: Re: [SOURCE] MultiSplit7913 Un split diferente XD
Publicado por: raul338 en 14 Marzo 2011, 17:31 pm
Puedes crear un tipo "marcador" con dos long, uno que indique el index del separador y otro que diga el index del char donde empieza, y asi sigues teniendo un solo arreglo :P


Título: Re: [SOURCE] MultiSplit7913 Un split diferente XD
Publicado por: 79137913 en 15 Marzo 2011, 15:46 pm
HOLA!!!

Si, hice eso cuando lo estapa haciendo, pero al usar instr por cada delimitador el vector estaria desordenado y ordenarlo es un bajon... la otra forma que tendria es con mid, pero seria mas lento.

GRACIAS POR LEER!!!


Título: Re: [SOURCE] MultiSplit7913 Un split diferente XD
Publicado por: raul338 en 15 Marzo 2011, 15:54 pm
Pero... si ya estas insertando ordenadamente :|


Título: Re: [SOURCE] MultiSplit7913 Un split diferente XD
Publicado por: 79137913 en 15 Marzo 2011, 16:29 pm
HOLA!!!

No, Fijate que se hace un recorrido(hecho de instr en el while) por cada Delimitador, entonces si en el lugar 3 y 10 esta el delimitador 1 y en el lugar 7 esta el delimitador 2 el vector quedara asi:

Código:
Pos.index(3,10,7)
Pos.Delimit(1,1,2)

GRACIAS POR LEER!!!


Título: Re: [SOURCE] MultiSplit7913 Un split diferente XD
Publicado por: raul338 en 15 Marzo 2011, 20:11 pm
Me entendiste mal :xD
yo me referia asi
Código:
Private Type Separador
    index    As Long
    delimit   As Long
End Type

posicion 1
   .index = 3
   .Delimit = 1
posicion 2
   .index = 10
   .delimit = 2
posicion 3
   .index = 7
   .delimit = 1

:P te dije, usando un solo vector :P


Título: Re: [SOURCE] MultiSplit7913 Un split diferente XD
Publicado por: Psyke1 en 15 Marzo 2011, 20:21 pm
Esa fue una de las formas que pensé yo!! :D

DoEvents! :P


Título: Re: [SOURCE] MultiSplit7913 Un split diferente XD
Publicado por: 79137913 en 15 Marzo 2011, 23:50 pm
HOLA!!!

Si, en un vector, lo entiendo, pero lo que te decia era que es un bajon ordenarlo.

GRACIASPOR LEER!!!


Título: Re: [SOURCE] MultiSplit7913 Un split diferente XD
Publicado por: raul338 en 15 Marzo 2011, 23:55 pm
Pero para que lo queres ordenar si ya lo estas ingresando ordenadamente


Título: Re: [SOURCE] MultiSplit7913 Un split diferente XD
Publicado por: 79137913 en 16 Marzo 2011, 12:47 pm
HOLA!!!

Porque ... si yo tengo esto:
Código:
Pos.index(3,10,7)
Pos.Delimit(1,1,2)

Lo que va a dar es:
Código:
Respuesta(mid(texto,1,3),mid(texto,4,10),mid(texto,11,7))
                                              error^  ^

Entendes?

GRACIAS POR LEER!!!


Título: Re: [SOURCE] MultiSplit7913 Un split diferente XD
Publicado por: raul338 en 16 Marzo 2011, 13:36 pm
Deja, sigues sin entender lo que trato de decir :xD


Título: Re: [SOURCE] MultiSplit7913 Un split diferente XD
Publicado por: 79137913 en 16 Marzo 2011, 13:52 pm
HOLA!!!

 >:( bueno :/

GRACIAS POR LEER!!!


Título: Re: [SOURCE] MultiSplit7913 Un split diferente XD
Publicado por: Psyke1 en 22 Marzo 2011, 19:09 pm
La mejor forma que hay se me ocurre de hacerlo, con un Type, queda superbonito ;D :

Código
  1. Option Explicit
  2.  
  3. '// @ntdll.dll
  4. Private Declare Sub RtlMoveMemory Lib "ntdll.dll" (ByVal Destiny As Long, ByVal Source As Long, ByVal Bytes As Long)
  5.  
  6. Private Type SPLIT_POSITION
  7.    Mark        As Long
  8.    LenBDel     As Long
  9. End Type
  10.  
  11. Public Static Function MrFrogMultiSplit(ByRef strText$, ByRef strDelimiter$(), ByRef strOutputArray$()) As Boolean
  12. Dim strTmpDel$, lngLenBDel&, lngLenBText&, lngUBDel&, lngLBDel&
  13. Dim SP() As SPLIT_POSITION, tmpSP As SPLIT_POSITION
  14. Dim lngCount&, lngStart&, B2c&, Q&, C&
  15.  
  16.    lngLenBText = VBA.Strings.LenB(strText)
  17.    If (Not Not strDelimiter) And (lngLenBText > 0) Then
  18.        lngLBDel = LBound(strDelimiter)
  19.        lngUBDel = UBound(strDelimiter)
  20.  
  21.        ReDim SP(255) As SPLIT_POSITION
  22.        lngCount = 0
  23.  
  24.        For Q = lngLBDel To lngUBDel
  25.            strTmpDel = strDelimiter(Q)
  26.            lngStart = VBA.Strings.InStrB(1, strText, strTmpDel)
  27.  
  28.            If (lngStart - 1)>0 Then
  29.                lngLenBDel = VBA.LenB(strTmpDel)
  30.  
  31.                Do
  32.                    tmpSP.Mark = lngStart
  33.                    tmpSP.LenBDel = lngLenBDel
  34.  
  35.                    lngStart = VBA.Strings.InStrB(lngStart + lngLenBDel, strText, strTmpDel)
  36.  
  37.                    C = lngCount
  38.                    If C Then
  39.                        Do While tmpSP.Mark < SP(C - 1).Mark
  40.                            C = C - 1
  41.                            If C = 0 Then Exit Do
  42.                        Loop
  43.  
  44.                        If C < lngCount Then
  45.                            B2c = lngCount - C
  46.                            RtlMoveMemory VarPtr(SP(C + 1)), VarPtr(SP(C)), B2c + B2c + B2c + B2c + B2c + B2c + B2c + B2c
  47.                        End If
  48.                    End If
  49.                    SP(C) = tmpSP
  50.  
  51.                    lngCount = lngCount + 1
  52.                    If lngCount And &HFF Then
  53.                        ReDim Preserve SP(lngCount + &HFF) As SPLIT_POSITION
  54.                    End If
  55.                Loop While lngStart
  56.            End If
  57.        Next Q
  58.  
  59.        ReDim strOutputArray$(lngCount)
  60.        lngCount = lngCount - 1
  61.        lngStart = 1
  62.  
  63.        For Q = 0 To lngCount
  64.            strOutputArray$(Q) = VBA.Strings.MidB$(strText, lngStart, SP(Q).Mark - lngStart)
  65.            lngStart = SP(Q).Mark + SP(Q).LenBDel
  66.        Next Q
  67.  
  68.        If (lngStart And Not 1) < lngLenBText Then
  69.            strOutputArray$(Q) = VBA.Strings.MidB$(strText, lngStart, lngLenBText - lngStart + 2)
  70.        End If
  71.  
  72.        MrFrogMultiSplit = True
  73.    End If
  74. End Function

Código:
Private Sub Form_Load()
Const strTest$ = "My+name--is(((MrFrog====and+I--love(((frogs... :P+hahaha===="
Dim strArr$(), strDels$()
Dim FixIdeBug&()
Dim vItem

    Debug.Assert Not FixIdeBug Or App.hInstance

    strDels = Split("+ -- ((( ====", " ")

    If MrFrogMultiSplit(strTest, strDels, strArr) Then
        Debug.Print "---> "; Time$; " <---"
    
        For Each vItem In strArr
            Debug.Print vItem
        Next vItem
    End If
End Sub

DoEvents! :P