begin process at 2012 02 10 00:19:43
  Trouver un code source :
 
dans
 
Accueil > 

Code

 > 

Shell

 > DÉCOMPOSER LES ARGUMENTS D'UNE LIGNE DE COMMANDE (GÈRE LES GUILLEMETS)

DÉCOMPOSER LES ARGUMENTS D'UNE LIGNE DE COMMANDE (GÈRE LES GUILLEMETS)


 Information sur la source

Note :
Aucune note
Catégorie :Shell Classé sous :argument, commande, parse, parser Niveau :Débutant Date de création :04/09/2006 Vu / téléchargé :9 435 / 233

Auteur : LogOff

Ecrire un message privé
Commentaire sur cette source (45)
Ajouter un commentaire et/ou une note

 Description


A partir d'une ligne de commande, cette fonction renvoie un tableau contenant la commande et ses arguments.

Le code gère l'emploi des guillemets. Ainsi, si votre commande est: shell "c:\program files\..."
l'argument renvoyé sera "c:\program files"
et non "c:\program".

Utilisation:
    - si vous voulez traiter Command() quand votre appli se lance avec des arguments
    - si vous voulez créer vos propres commandes dans une appli du style 'Console perso.'

J'espère que le code n'est pas trop embrouillé (la deuxiéme partie fait un peu usine à gaz); pour toute question et surtout pour toute amélioration, n'hésitez pas.

Source

  • Option Explicit
  • ' Ce type de données contient les infos. relatives à l'occurrence des arguments
  • Public Type TempType
  • Pos1 As Integer 'Position de début dans strArgLine
  • pos2 As Integer 'Position de fin dans strArgLine
  • Filled As Boolean 'Si les champs Pos1 et Pos2 sont tous les deux renseignés
  • Done As Boolean 'Quand l'argument a été passé en revue
  • End Type
  • Sub main()
  • ' Cette Sub ne sert qu'à tester la fonction ParseCommandLine
  • Dim CmdLine As String
  • Dim CommandLine() As String
  • 'C'est une ligne de commande de test
  • CmdLine = "copy /Y c:\winnt\notepad.exe ""c:\program files"""
  • 'Appel de la fonction, qui renvoie un tableau
  • CommandLine() = ParseCommandLine(CmdLine)
  • 'Ce tableau contient:
  • '- en index 0, la commande
  • '- en index > 0, les arguments
  • Dim i As Integer
  • For i = 0 To UBound(CommandLine())
  • MsgBox CommandLine(i)
  • Next i
  • End Sub
  • Public Function ParseCommandLine(strCommandLine As String) As String()
  • Dim strArgs() As String 'Tableau temporaire contenant certains des arguments
  • Dim CommandLine() As String 'Tableau temporaire contenant la commande et tous les arguments
  • Dim strArgLine As String 'la chaîne contenant les arguments
  • Dim strTemp As String 'Chaîne temporaire de traitement intermédiare
  • Dim pos As Integer
  • Dim pos2 As Integer
  • Dim i As Integer
  • Dim j As Integer
  • Dim k As Integer
  • '/ Traitement de strCommandLine
  • strCommandLine = Trim(strCommandLine) 'On enlève les espaces
  • If strCommandLine = "" Then Exit Function 'Si la ligne est vide, il n'y a rien à traiter
  • ' On regarde s'il la commande est précédée d'arguments ou non
  • pos = InStr(1, strCommandLine, " ")
  • If pos = 0 Then
  • 'Il n'y a pas d'arguments
  • ReDim CommandLine(0) 'On dimensionne le tableau
  • CommandLine(0) = strCommandLine 'On le remplit à l'index 0 avec la commande
  • strArgLine = "" 'Pas d'arguments à traiter
  • Else
  • ReDim CommandLine(0) 'On dimensionne le tableau
  • CommandLine(0) = Mid(strCommandLine, 1, pos - 1) 'On le remplit à l'index 0 avec la commande
  • strArgLine = Mid(strCommandLine, pos + 1) 'On récupère les arguments à traiter
  • End If
  • '/ Traitement de la chaîne contenant les arguments (strArgLine)
  • strArgLine = Trim(strArgLine) 'On enlève les espaces
  • pos = InStr(1, strArgLine, """") 'On regarde si la chîne contient des guillemets
  • If pos = 0 Then 'Pas de guillemets
  • 'Combien d'arguments ?
  • pos2 = InStr(1, strArgLine, " ")
  • If pos2 = 0 Then 'Un seul argument
  • ReDim Preserve CommandLine(1)
  • CommandLine(1) = strArgLine
  • Else 'Plusieurs arguments
  • 'On utilise un tableau intermédiaire pour y stocker les arguments
  • strArgs() = Split(strArgLine, " ")
  • 'On ajoute au tableau de résultat le contenu du tableau intermédiaire
  • For i = 0 To UBound(strArgs())
  • ReDim Preserve CommandLine(i)
  • CommandLine(i) = strArgs(i)
  • Next i
  • End If
  • Else 'Il y a des guillemets, c'est ici que ça se complique
  • 'Dans ce tableau, on stocke les mots séparés par des guillemets
  • Dim intTemps As Integer
  • Dim Temp() As TempType
  • 'On dimensionne le tableau
  • intTemps = 0
  • ReDim Temp(intTemps)
  • 'On définit le tableau comme étant vide à l'index concerné (0)
  • Temp(intTemps).Filled = False
  • ' /On remplit le tableau avec la position de début et de fin des chaînes contenues entre guillemets
  • 'On fixe la position de départ de la recherche des guillemets au 1er caractère de la chaîne des arguments
  • pos = 1
  • While pos <> 0
  • 'On recherche la position des guillemets
  • pos = InStr(pos, strArgLine, """")
  • If pos <> 0 Then
  • 'Si le tableau est complété à l'index concerné, on incrémente l'index et on redimensionne le tableau en conséquence
  • If Temp(intTemps).Filled = True Then
  • intTemps = intTemps + 1
  • ReDim Preserve Temp(intTemps)
  • Temp(intTemps).Filled = False
  • End If
  • 'Si la position de début n'a pas été stockée
  • If Temp(intTemps).Pos1 = 0 Then
  • 'On la stocke
  • Temp(intTemps).Pos1 = pos
  • 'Si la position de fin n'a pas été stockée
  • ElseIf Temp(intTemps).pos2 = 0 Then
  • 'On la stocke
  • Temp(intTemps).pos2 = pos
  • 'On définit le tableau comme étant complété à l'index concerné (intTemps)
  • Temp(intTemps).Filled = True
  • End If
  • 'On incrémente la position de départ de la recherche des guillemets, pour ne pas tourner en rond
  • pos = pos + 1
  • End If
  • Wend
  • 'Dans ce tableau, on stocke les mots séparés par des espaces
  • Dim Temp2a() As String
  • Temp2a = Split(strArgLine, " ")
  • 'Dans ce tableau, on stocke la position des mots séparés par des espaces
  • Dim intTemps2 As Integer
  • Dim Temp2() As TempType
  • intTemps2 = 0
  • For i = 0 To UBound(Temp2a)
  • intTemps2 = intTemps2 + 1
  • ReDim Preserve Temp2(intTemps2)
  • Temp2(intTemps2).Pos1 = Len(GetTable(Temp2a(), 0, i - 1)) + i * 1 + 1
  • Temp2(intTemps2).pos2 = Temp2(intTemps2).Pos1 + Len(Temp2a(i)) - 1
  • Next i
  • 'Maintenant, on ajoute au tableau final les différents éléments (élément séparés par des espaces et éléments situés entre guillemets), en supprimant les redondances, ie. les éléments séparés par des espaces ET situés entre guillemets
  • Dim Found As Boolean
  • For i = 1 To intTemps2
  • 'Par défaut, la chaîne séparée par des espaces ne correspond pas à une chaîne placée entre guillemets
  • Found = False
  • For j = 0 To intTemps
  • If Temp2(i).Pos1 = Temp(j).Pos1 Then
  • 'Si la chaîne ne correspond pas à une chaîne placée entre guillemets
  • Found = True
  • 'On ajoute la chaîne entre guillemets au tableau final des arguments
  • ReDim Preserve CommandLine(UBound(CommandLine()) + 1)
  • CommandLine(UBound(CommandLine())) = Mid(strArgLine, Temp(j).Pos1, Temp(j).pos2 - Temp(j).Pos1 + 1)
  • 'On définit qu'elle a été traitée
  • Temp2(i).Done = True
  • 'Pour les chaînes séparées par des espaces qui appartiennent à la chaîne placée entre guillemets,
  • 'on définit qu'elles ont été traitées.
  • For k = i To intTemps2
  • If Temp2(k).pos2 <= Temp(j).pos2 Then
  • Temp2(k).Done = True
  • End If
  • Next k
  • End If
  • Next j
  • If Found = False Then 'La chaîne ne correspond pas à une chaîne placée entre guillemets
  • If Temp2(i).Done = False Then 'Sil la chaîne n'a pas été traitée auparavant
  • 'On l'ajoute au tableau final des arguments
  • ReDim Preserve CommandLine(UBound(CommandLine()) + 1)
  • CommandLine(UBound(CommandLine())) = Mid(strArgLine, Temp2(i).Pos1, Temp2(i).pos2 - Temp2(i).Pos1 + 1)
  • 'On définit qu'elle a été traitée
  • Temp2(i).Done = True
  • End If
  • End If
  • Next i
  • End If
  • 'On renvoie le résultat de la fonction
  • ParseCommandLine = CommandLine()
  • End Function
  • ' Cette function rassemble en une chaîne les éléments d'un tableau (sans y mettre les séparateurs), d'un index de début à un index de fin.
  • Function GetTable(strTable() As String, IndexFrom As Integer, IndexTo As Integer)
  • Dim i As Integer
  • Dim strTemp As String
  • For i = IndexFrom To IndexTo
  • strTemp = strTemp & strTable(i)
  • Next i
  • GetTable = strTemp
  • End Function
Option Explicit

    ' Ce type de données contient les infos. relatives à l'occurrence des arguments
    Public Type TempType
        Pos1 As Integer     'Position de début dans strArgLine
        pos2 As Integer     'Position de fin dans strArgLine
        Filled As Boolean   'Si les champs Pos1 et Pos2 sont tous les deux renseignés
        Done As Boolean     'Quand l'argument a été passé en revue
    End Type

Sub main()

    ' Cette Sub ne sert qu'à tester la fonction ParseCommandLine

    Dim CmdLine As String
    Dim CommandLine() As String

    'C'est une ligne de commande de test
    CmdLine = "copy /Y c:\winnt\notepad.exe ""c:\program files"""

    'Appel de la fonction, qui renvoie un tableau
    CommandLine() = ParseCommandLine(CmdLine)
    
    'Ce tableau contient:
        '- en index 0, la commande
        '- en index > 0, les arguments
    Dim i As Integer
    For i = 0 To UBound(CommandLine())
        MsgBox CommandLine(i)
    Next i

End Sub

Public Function ParseCommandLine(strCommandLine As String) As String()
        
    Dim strArgs() As String         'Tableau temporaire contenant certains des arguments
    Dim CommandLine() As String     'Tableau temporaire contenant la commande et tous les arguments
    
    Dim strArgLine As String        'la chaîne contenant les arguments
    Dim strTemp As String           'Chaîne temporaire de traitement intermédiare
    
    Dim pos As Integer
    Dim pos2 As Integer
    
    Dim i As Integer
    Dim j As Integer
    Dim k As Integer
    

    '/ Traitement de strCommandLine
    
    strCommandLine = Trim(strCommandLine)       'On enlève les espaces
    If strCommandLine = "" Then Exit Function   'Si la ligne est vide, il n'y a rien à traiter
    
    ' On regarde s'il la commande est précédée d'arguments ou non
    pos = InStr(1, strCommandLine, " ")
    
    If pos = 0 Then
        'Il n'y a pas d'arguments
        ReDim CommandLine(0)                                'On dimensionne le tableau
        CommandLine(0) = strCommandLine                     'On le remplit à l'index 0 avec la commande
        strArgLine = ""                                     'Pas d'arguments à traiter
    Else
        ReDim CommandLine(0)                                'On dimensionne le tableau
        CommandLine(0) = Mid(strCommandLine, 1, pos - 1)    'On le remplit à l'index 0 avec la commande
        strArgLine = Mid(strCommandLine, pos + 1)           'On récupère les arguments à traiter
    End If


    '/ Traitement de la chaîne contenant les arguments (strArgLine)
    
    strArgLine = Trim(strArgLine)       'On enlève les espaces
    pos = InStr(1, strArgLine, """")    'On regarde si la chîne contient des guillemets
    
    If pos = 0 Then 'Pas de guillemets
        
        'Combien d'arguments ?
        pos2 = InStr(1, strArgLine, " ")
        
        If pos2 = 0 Then 'Un seul argument
            
            ReDim Preserve CommandLine(1)
            CommandLine(1) = strArgLine
        
        Else 'Plusieurs arguments
            
            'On utilise un tableau intermédiaire pour y stocker les arguments
            strArgs() = Split(strArgLine, " ")
            
            'On ajoute au tableau de résultat le contenu du tableau intermédiaire
            For i = 0 To UBound(strArgs())
                ReDim Preserve CommandLine(i)
                CommandLine(i) = strArgs(i)
            Next i
        
        End If
        
        
    Else 'Il y a des guillemets, c'est ici que ça se complique
        
        'Dans ce tableau, on stocke les mots séparés par des guillemets
        Dim intTemps As Integer
        Dim Temp() As TempType

        'On dimensionne le tableau
        intTemps = 0
        ReDim Temp(intTemps)
        
        'On définit le tableau comme étant vide à l'index concerné (0)
        Temp(intTemps).Filled = False
        
        
        ' /On remplit le tableau avec la position de début et de fin des chaînes contenues entre guillemets
        
        'On fixe la position de départ de la recherche des guillemets au 1er caractère de la chaîne des arguments
        pos = 1
        While pos <> 0
            'On recherche la position des guillemets
            pos = InStr(pos, strArgLine, """")
            If pos <> 0 Then
                
                'Si le tableau est complété à l'index concerné, on incrémente l'index et on redimensionne le tableau en conséquence
                If Temp(intTemps).Filled = True Then
                    intTemps = intTemps + 1
                    ReDim Preserve Temp(intTemps)
                    Temp(intTemps).Filled = False
                End If
                
                'Si la position de début n'a pas été stockée
                If Temp(intTemps).Pos1 = 0 Then
                    'On la stocke
                    Temp(intTemps).Pos1 = pos
                'Si la position de fin n'a pas été stockée
                ElseIf Temp(intTemps).pos2 = 0 Then
                    'On la stocke
                    Temp(intTemps).pos2 = pos
                    'On définit le tableau comme étant complété à l'index concerné (intTemps)
                    Temp(intTemps).Filled = True
                End If
            
                'On incrémente la position de départ de la recherche des guillemets, pour ne pas tourner en rond
                pos = pos + 1
            
            End If
        Wend
        
        
        'Dans ce tableau, on stocke les mots séparés par des espaces
        Dim Temp2a() As String
        Temp2a = Split(strArgLine, " ")
        
        'Dans ce tableau, on stocke la position des mots séparés par des espaces
        Dim intTemps2 As Integer
        Dim Temp2() As TempType
        intTemps2 = 0
        
        For i = 0 To UBound(Temp2a)
            intTemps2 = intTemps2 + 1
            ReDim Preserve Temp2(intTemps2)
            
            Temp2(intTemps2).Pos1 = Len(GetTable(Temp2a(), 0, i - 1)) + i * 1 + 1
            Temp2(intTemps2).pos2 = Temp2(intTemps2).Pos1 + Len(Temp2a(i)) - 1
        Next i
        
        
        'Maintenant, on ajoute au tableau final les différents éléments (élément séparés par des espaces et éléments situés entre guillemets), en supprimant les redondances, ie. les éléments séparés par des espaces ET situés entre guillemets
        
        Dim Found As Boolean
        
        For i = 1 To intTemps2
            
            'Par défaut, la chaîne séparée par des espaces ne correspond pas à une chaîne placée entre guillemets
            Found = False
            
            For j = 0 To intTemps
                
                If Temp2(i).Pos1 = Temp(j).Pos1 Then
                    'Si la chaîne ne correspond pas à une chaîne placée entre guillemets
                    Found = True
                    
                    'On ajoute la chaîne entre guillemets au tableau final des arguments
                    ReDim Preserve CommandLine(UBound(CommandLine()) + 1)
                    CommandLine(UBound(CommandLine())) = Mid(strArgLine, Temp(j).Pos1, Temp(j).pos2 - Temp(j).Pos1 + 1)
                    
                    'On définit qu'elle a été traitée
                    Temp2(i).Done = True
                    
                    'Pour les chaînes séparées par des espaces qui appartiennent à la chaîne placée entre guillemets,
                    'on définit qu'elles ont été traitées.
                    For k = i To intTemps2
                        If Temp2(k).pos2 <= Temp(j).pos2 Then
                            Temp2(k).Done = True
                        End If
                    Next k
                    
                End If
            Next j
            
            If Found = False Then 'La chaîne ne correspond pas à une chaîne placée entre guillemets
                
                If Temp2(i).Done = False Then 'Sil la chaîne n'a pas été traitée auparavant
                    
                    'On l'ajoute au tableau final des arguments
                    ReDim Preserve CommandLine(UBound(CommandLine()) + 1)
                    CommandLine(UBound(CommandLine())) = Mid(strArgLine, Temp2(i).Pos1, Temp2(i).pos2 - Temp2(i).Pos1 + 1)
                    
                    'On définit qu'elle a été traitée
                    Temp2(i).Done = True
                End If
            
            End If
            
        Next i
        
    End If
    
    'On renvoie le résultat de la fonction
    ParseCommandLine = CommandLine()

End Function


' Cette function rassemble en une chaîne les éléments d'un tableau (sans y mettre les séparateurs), d'un index de début à un index de fin.
Function GetTable(strTable() As String, IndexFrom As Integer, IndexTo As Integer)

    Dim i As Integer
    Dim strTemp As String
    
    For i = IndexFrom To IndexTo
        strTemp = strTemp & strTable(i)
    Next i

    GetTable = strTemp
End Function



 Fichier Zip

Les Membres Club peuvent télécharger directement un fichier contenu dans le zip sans télécharger le zip en entier !

Télécharger le zip


 Sources de la même categorie

Source avec Zip CHOIX DE COULEUR SOUS XP EN MODE CONSOLE par ccgousset
Source avec Zip Source .NET (Dotnet) ENVOYEUR DE MAIL EN BATCH/DOS par Ant95
Source avec Zip Source avec une capture LANCEUR REALVNC par Nobru59
Source avec Zip Source .NET (Dotnet) XGBLENDERCOMPRESSOR par XelectroX
Source avec Zip Source .NET (Dotnet) CONTRÔLER L'AUTORUN DE WINDOWS XP (ET SUPÉRIEUR) ET LES NOTI... par ShareVB

 Sources en rapport avec celle ci

Source avec Zip Source avec une capture Source .NET (Dotnet) PATCHEUR DE FICHIER par tototh
Source avec Zip BON DE COMMANDE par alpha5
Source avec Zip Source avec une capture GESTION GÉNÉRALE DES SOCIÉTÉ par promarc
PARSE PDF AVEC ITEXTSHARP (RÉCUPÉRATION DU TEXTE, PAS OCR) par Norres
Source avec Zip ARGUMENTS DE LA LIGNE DE COMMANDE AMÉLIORÉ par Philippe PUECH

Commentaires et avis

Commentaire de PCPT le 04/09/2006 21:27:23 administrateur CS

salut,
c'est plus qu'optimisable....



Private Function ParseCommandLine(ByVal strCommandLine As String) As String()
    strCommandLine = Trim$(strCommandLine)
    If LenB(strCommandLine) = 0 Then
        ReDim ParseCommandLine(0) 'pour éviter l'erreur de ton Main ; pas testé?!!
    Else
        Dim i As Integer, iCptQuotes As Integer
        Dim aRes() As String
        iCptQuotes = 0
        For i = 1 To Len(strCommandLine)
            If Mid$(strCommandLine, i, 1) = Chr$(34) Then iCptQuotes = iCptQuotes + 1
        Next i
        
        'tout tronçon de chaîne ouvert par des " doit être fermé
        If iCptQuotes > 0 Then
            If (iCptQuotes / 2 <> Int(iCptQuotes / 2)) Then
                Err.Raise vbString, , "Construction de la chaîne de paramètres incorrecte"
            Else
                iCptQuotes = 0
                For i = 1 To Len(strCommandLine)
                    If Mid$(strCommandLine, i, 1) = Chr$(34) Then
                        iCptQuotes = iCptQuotes + 1
                    ElseIf Mid$(strCommandLine, i, 1) = Chr$(32) Then
                        If (iCptQuotes / 2 <> Int(iCptQuotes / 2)) Then Mid$(strCommandLine, i, 1) = Chr$(0)
                    End If
                Next i
            End If
        End If
        

        aRes = Split(strCommandLine, Chr$(32))
        ReDim ParseCommandLine(UBound(aRes))

        If iCptQuotes > 0 Then
            For i = 0 To UBound(aRes)
                aRes(i) = Replace(aRes(i), Chr$(0), Chr$(32))
            Next i
        End If
        ParseCommandLine = aRes
        Erase aRes
    End If
End Function


routine identique mais bien plus compacte ;)
à mettre sur codyx...

++
PCPT  [AFCK]

Commentaire de Renfield le 05/09/2006 08:09:11 administrateur CS

On peut même ne faire qu'une seule boucle :

Private Function ParseCommandLine(Optional ByVal strCommandLine) As String()
Dim i As Long
Dim nQuotes As Integer
Dim sChar As String
    '# Si aucune chaine avec les arguments de ligne de commande n'a été fournie...
    If IsMissing(strCommandLine) Then
        '# On utilise celle recue par l'executable, obtenu grâce a la fonction Command$()
        strCommandLine = Trim$(Command$())
    Else
        '# sinon, on utilise celle effectivement fournie par l'utilisateur.
        strCommandLine = Trim$(strCommandLine)
    End If
    If LenB(strCommandLine) = 0 Then
        ReDim ParseCommandLine(0) 'pour éviter l'erreur de ton Main ; pas testé?!!
    Else
        '# On regarde la chaine, caractère par caractère
        For i = 1 To Len(strCommandLine)
            '# On évite d'extraire deux fois le même caractère
            sChar = Mid$(strCommandLine, i, 1)
            '# Si le caractère considéré est une guillemet, on incrémente le compteur
            If sChar = ChrW$(34) Then
                nQuotes = nQuotes + 1
            '# si c'est un espace...
            ElseIf sChar = " " Then
                '# ...et que nous sommes en dehors d'un 'tronçon' avec des guillemets,
                '# on remplace l'espace par un carctère \0
                If Not CBool(nQuotes And 1) Then
                    Mid$(strCommandLine, i, 1) = vbNullChar
                End If
            End If
        Next i

        '# tout tronçon de chaîne ouvert par des " doit être fermé
        '# On teste donc si le nombre de guillemets est pair ou impair
        If CBool(nQuotes And 1) Then
            Err.Raise vbString, , "Construction de la chaîne de paramètres incorrecte"
        Else
            '# On découpe la ligne de commande à chaque \0 rencontré
            'strCommandLine = Replace(strCommandLine, ChrW$(34), vbNullString)
            ParseCommandLine = Split(strCommandLine, vbNullChar)
        End If
    End If
End Function


nous avons PCPT et moi même laissé le résultat tel quel...
reste que je pense qu'il serait de bon ton de supprimer les guillemets, dans le resultat. J'ai mis en commentaire la ligne qu'il te suffit d'activer si tu souhaite effectivement supprimer les guillemets

Commentaire de LogOff le 05/09/2006 08:23:44

Merci PCPT pour ton post, l'idée de remplacer les espaces dans les chaînes entre guillemets par un chr(0) simplifie tout le code.

Ainsi que pour avoir corrigé ma gestion d'erreur qui provoquait elle-même une erreur!

Pour info.: chr(0), ça correspond à quel caractère (non affichable?) ?

Commentaire de Renfield le 05/09/2006 08:26:07 administrateur CS

VbNullChar

c'est non affichable

Commentaire de Patrice99 le 05/09/2006 08:28:48

Déjà fait ici :
http://patrice.dargenton.free.fr/CodesSources/Doc2Pdf.vbp.html#65
www.vbfrance.com/code.aspx?ID=29662

Commentaire de LogOff le 05/09/2006 08:28:59

J'ai eu la réponse à ma question par Renfield (son post est arrivé pendant la rédaction du mien).

Tu peux expliquer l'utilisation de CBool stp (vb me dit juste: Convertit une expression en Boolean) ?
Merci,

Commentaire de LogOff le 05/09/2006 08:38:48

Merci Patrice99, c'est noté. Tu conviendras quand même qu'on peut difficilement trouver ton code en lançant une recherche avec des mots-clefs comme 'ligne de commande' etc.

Quand vous avez des bouts de code comme ça, réutilisables et pas encore postés, ajoutez-les séparément, c'est bon pour tout le monde!

Commentaire de Renfield le 05/09/2006 09:22:49 administrateur CS

'nQuotes And 1' va renvoyer une valeur numérique.
CBool la transforme juste un Boolean (Vrai/Faux)

c'est une bonne habitude a prendre lorsque l'on fait des opérations bit à bit, en VB

le test
If CBool(nQuotes And 1) Then

est vrai si nQuotes est impair, c'est bien ce que l'on cherche...

Commentaire de Patrice99 le 05/09/2006 09:27:39

Exact, ce n'est pas évident à retrouver, même via Google. C'est pour cela que je signale mes bouts de code quand l'occasion se présente.

Commentaire de BruNews le 05/09/2006 09:55:02 administrateur CS

If nQuotes And 1 Then
et
If CBool(nQuotes And 1) Then
ne donnent pas idem pour le If ???

Bizzare, If teste si condition <> 0, normalement pas autre chose donc devrait être équivalent en plus court.

Commentaire de asimengo le 05/09/2006 10:21:53

(3.1 and 1) = 1, de même cbool(3.1 and 1) = True est-ce à dire que 3.1 est impair?

Commentaire de Renfield le 05/09/2006 10:29:49 administrateur CS

les deux écritures sont bien évidemment équivalentes, oui...

Asimengo, on ne joue ici qu'avec des nombres entiers

? 3.1 or 0
3
lors d'opérations bit a bit, VB supprime la partie décimale...

Commentaire de BruNews le 05/09/2006 10:31:56 administrateur CS

nQuotes est un entier dans ce code, ne pas sortir la phrase du contexte sinon on ne se comprendra plus.

Commentaire de Renfield le 05/09/2006 11:12:06 administrateur CS

J'ai pris pour habitude d'utiliser CBool lors d'opérations bit à bit.
Bien qu'il ne soit pas requis dans de nombreux cas, il arrive que son absence soit génante :

a = 5
'# On teste si a est impair
If a And 1 Then
    '# On arrive ici, c'est OK
End If

a = 5
'# On teste si a est pair
If Not (a And 1) Then
    '# On arrive ici, ca n'est pas voulu
    '# l'explication est simple :
    '# a And 1 => 1
    '# Not 1   => -2   et comme -2 est different de 0...
End If

a = 5
'# On teste si a est impair
If Not CBool(a And 1) Then
    '# On n'arrive plus ici, c'est OK
End If

Pourtant, et bien que certains seront satisfaits de CBool, une petite discussion avec notre ami BruNews m'aura éclairé sur le fait qu'un cast est un cast et qu'il consomme des cycles...il n'est pas plus complexe de faire un test d'égalité avec 0 :

a = 5
'# On teste si a est pair
If (a And 1)=0 Then
    '# On n'arrive pas ici, pas de souci
End If

il y a donc de fortes chances pour que j'abandonne CBool....

Commentaire de ratala le 05/09/2006 11:32:41

Ne marche pas avec un
"cmd.exe exe.exe"/ping
le fichier cmd.exe exe.exe est evidament un seul fichier

Commentaire de Renfield le 05/09/2006 11:59:03 administrateur CS

bien vu.
c'est à cause de l'espace attendu avant le /ping...

Commentaire de PCPT le 05/09/2006 12:18:55 administrateur CS

Patrice99 -> Codyx.Org est aussi là pour çà ;)

Commentaire de bouv le 05/09/2006 15:04:39

Je rejoins la conversation de BruNews et Renfield sur l'histoire du CBool.

Il est vrai que VB ne requiert pas le CBool dans le cas présent. Et je ne le met moi même jamais (ou presque).

Il s'agit à mon sens d'une des nombreuses 'fautes de programmation' que VB nous laisse faire. Certains diront souplesse, je préfère parler de fautes ou de code peu rigoureux que VB nous laisse programmer.
Ex : Utilisation de variables implicites, type casting...

Autre exemple :
Dim dVar As Double
Dim iVar as Integer
dVar = 3.2
iVar = dVar

Ceci ne posera pas non plus de problème !

++

Commentaire de Patrice99 le 05/09/2006 15:29:17

Ma fonction ne marche pas avec "cmd.exe exe.exe"/ping
Elle renvoie "cmd.exe exe.exe" et ping
Mais elle fonctionne avec "cmd.exe exe.exe" /ping

PCPT > Codyx.Org est aussi là pour çà ;)
Oui mais j'ai trop l'habitude d'utiliser Google pour trouver ce que je cherche, car je n'aime pas attendre, et j'aime sa pertinence. Je me sert de Google pour retrouver la plupart des fonctions que j'utilise, car j'ai mis les sources de mes programmes sur le web grace à VBToHtml.

Commentaire de BruNews le 05/09/2006 15:31:44 administrateur CS

ah non, là je suis pas du tout d'accord sur le sujet du 'If', aucune faute de prog à écrire:
If mavar Then
  ' execute ok
End If

'If' teste le NON 0 pour exécuter la condition comme dans tout langage normal, un cast superflu n'est en aucun cas de la rigueur programmatique, seulement perte de cycles car remplissage des bits à 1 (or eax, -1) totalement inutile.

If mavar And 1 Then OkExecute
sera traduit en:
test eax, 1
je LabelNON

il serait dommage d'en rajouter, non ?

Commentaire de bouv le 05/09/2006 15:56:11

Pour :

If mavar Then
  ' execute ok
End If

Je suis ok, mais pour :

If mavar And 1 Then OkExecute

Cela me parait moins evident.
Après je peux me tromper, si je mets ça dans le même sac que le reste (de certaines "non rigueurs" de VB) indûment. Dans ce cas je suis volontier preneur d'explication.

++

Commentaire de Patrice99 le 05/09/2006 16:03:19

Parfois non : Attention, en VBA, le test If Not True Then ne fonctionne pas à 100%, il y a des cas où ça ne marche pas (par exemple si on lance une application Access 2000 avec Access 2002, remplacer If Not bVar par If False = bVar par mesure de prudence)

Commentaire de BruNews le 05/09/2006 16:08:55 administrateur CS

mavar And 1
donne un résultat sur registre EFlags (pas sur mavar puiqsque non affecté) seulement, le test est toujours sur 0 ou NON 0 dans tous les cas.
Il pourrait en aller autrement avec des 'objets' VB ou VBA mais sur des types primaires, If se comporte ici comme dans tout langage.

Commentaire de BruNews le 05/09/2006 16:10:24 administrateur CS

Patrice > c'est bien ce qu'on dit, toujours comparer à 0 ou non 0.

Commentaire de Renfield le 05/09/2006 16:17:30 administrateur CS

BruNews est tout se qu'il y a de plus au fait de se qui se passe en coulisses.

VB/VBA/VBS ne dérogent (heureusement) pas à la règle, et un IF ne teste qu'une seule et unique chose :
que l'expression présente entre If et Then soit ou non différent de 0.

son évaluation, c'est encore autre chose...

mavar And 1  va effectuer une operation bit a bit, et générer une valeur numérique
(qui sera testée selon son égalité ou non avec 0)

rien d'autre a ajouter là dessus

Commentaire de Patrice99 le 05/09/2006 17:00:07

BruNews > c'est bien ce qu'on dit, toujours comparer à 0 ou non 0.

Certes, mais si bVar est un booléen, c'est quand même triste que Not bVar ne soit pas toujours correctement évalué !
Heureusement en DotNet avec compilation Strict, il est strictement impossible de se faire piéger ainsi comme en VB6, ou plus gravement comme en VBA

Commentaire de BruNews le 05/09/2006 17:12:41 administrateur CS

Comme quoi VBA 2002 a été correctement réécrit...

Lecture des manuels Intel (ce qu'un VBiste fait régulièrement...) indique clairement:
NOT => Flags affected: NONE
Quand je vous dis qu'il y a de la logique partout, he he.

Commentaire de asimengo le 05/09/2006 17:30:40

Mon exemple était juste pour que la précision soit faite. Tout le monde passe par ici et ne comprend pas toujours très bien. La précision a été faite par Renfield et Brunews, ce test de parité (x and 1) n'est efficace que si x est un entier. Si résultat = 0 alors x est pair sinon (si différent de 0, peu importe la valeur) alors x est impair

Néanmoins:
Renfield dit :  lors d'opérations bit a bit, VB supprime la partie décimale...
(3.5 and 1) = 0, ne semble pas vérifier, ai-je mal interpreter ce qu'a dit Renfield?

Commentaire de Renfield le 05/09/2006 17:44:53 administrateur CS

x And 1  ne pourra renvoyer que 0 ou 1

pas mal interprété, non ....
(3.5 And 1) => 0
VB arrondit apparemment il doit y avoir un Cast vers un Long, en interne

Commentaire de BruNews le 05/09/2006 17:55:47 administrateur CS

qu'il convertisse ou non, sa structure interne est (en hexa):
400C0000 00000000
le bit droit est 0 donc résult 0 tout a fait normalement.

Commentaire de bouv le 05/09/2006 18:01:55

"toujours comparer à 0 ou non 0"
C'est bien là que je ne trouve pas cela "normal".
False = 0
True = -1
Or, If bVar Then ..., ne devrait entrer dans la première partie du If que si bVar = True donc = -1.
Seulement si on fait, If 5 Then ... cela fonctionne également !

Commentaire de PCPT le 05/09/2006 18:06:57 administrateur CS

condition : est-ce que 5<>0 oui
nop?

Commentaire de BruNews le 05/09/2006 18:14:22 administrateur CS

bouv > c'était le 1/4 h plaisanterie ou quoi ?

Commentaire de Renfield le 05/09/2006 18:16:17 administrateur CS

Bouv, tu peux pas remettre en cause 30 ans d'informatique basés sur
"est-ce différent de 0 ?"

Commentaire de LogOff le 05/09/2006 19:31:12

Pour l'histoire du '/ping', il est clair que si la syntaxe de la ligne de commande est incorrecte (ie. si pas de séparateur 'espace ' entre les arguments), la fonction ne retourne pas le résultat attendu.

Commentaire de PCPT le 05/09/2006 20:26:49 administrateur CS

en dessous de l'incrémentation de nQuotes :

If (i > 1) And (i < Len(strCommandLine)) Then
    If nQuotes And 1 Then
        If Mid$(strCommandLine, i + 1, 1) <> " " Then
            strCommandLine = Left$(strCommandLine, i) & " " & Right$(strCommandLine, Len(strCommandLine) - i)
        End If
    End If
End If

Commentaire de PCPT le 05/09/2006 20:31:32 administrateur CS

woups, je corrige çà

Commentaire de PCPT le 05/09/2006 20:41:09 administrateur CS

    ' si c'est une " de fermeture, on insère un espace s'il n'y en a pas
    If (i > 1) And (i < Len(strCommandLine)) Then
        If Not CBool(nQuotes And 1) Then
            If Mid$(strCommandLine, i + 1, 1) <> " " Then
                strCommandLine = Left$(strCommandLine, i) & " " & Right$(strCommandLine, Len(strCommandLine) - i)
            End If
        End If
    End If

marrant, sans CBool çà fausse tout ^^

Commentaire de bouv le 05/09/2006 20:56:13

Oula... ne vous enervez pas, je ne fais qu'emettre un point de vu.

Je ne connais que VB6 comme langage et tout ce que j'ai appris c'est sur ce site, je n'ai jamais pris aucun cours. Donc il me manque évidemment quelques bases importantes.

Comme dit plus haut : "je suis volontier preneur d'explication".

Commentaire de clafouti le 06/09/2006 13:23:15

Eh les gars, c'est bien joli toutes vos explications, mais il y a plus simple !!!
Déclarer bQuotes as boolean, et initialiser à true.
Ensuite dans la boucle de "comptage" des quotes, il suffit de faire bQuotes = not bQuotes.
Pour tester si c'est pair ou pas : if bQuotes then....

Commentaire de PCPT le 06/09/2006 13:28:16 administrateur CS

clafouti -> et sorti de ta boucle tu vois comment qu'il y en avait ou pas (des ")? ....
et si cette proposition était valable (mais c'est pas le cas), je ne vois pas en quoi soudainement le code devient "plus simple" ;)
si?

Commentaire de clafouti le 06/09/2006 18:31:04

La seule chose qui importe est de savoir si on a un nombre pair (correct) ou impair (incorrect) de quotes. A la fin de la boucle, si bQuotes est false, c'est qu'il y a un nombre impair de quotes ==> message d'erreur.
Quand à la simplicité du code, elle me parrait évidente : qu'est-ce qui est plus lisible : "if cBool(nQuotes and 1) Then..." ou "if not bQuotes Then..." ?

Commentaire de PCPT le 07/09/2006 02:54:29 administrateur CS

tu proposes d'initialiser à true. mais s'il n'y a aucune quote????
++

Commentaire de clafouti le 07/09/2006 08:48:33

Si il y a aucune quotes, à la fin de la boucle de vérification, bQuotes est true, et donc pas de messages d'erreur.
J'ai testé la fonction avec plusieurs cas de figure, cela marche parfaitement.

Commentaire de Renfield le 03/10/2006 17:47:22 administrateur CS

sans vouloir relancer la polémique...

voici un code fonctionnel (on m'a demandé ce code, je voulais filer une version claire...)


Private Sub Form_Load()
Dim i As Long
Dim xsParts() As String
    xsParts = ParseCommandLine("")
    For i = LBound(xsParts) To UBound(xsParts)
        Debug.Print i, xsParts(i)
    Next i
    Unload Me
End Sub

Private Function ParseCommandLine(Optional ByVal vsCommandLine) As String()
Dim i As Long
Dim bInQuotes As Boolean
Dim nChar As Integer
    '# Si aucune chaine avec les arguments de ligne de commande n'a été fournie...
    If IsMissing(vsCommandLine) Then
        '# On utilise celle recue par l'executable, obtenu grâce a la fonction Command$()
        vsCommandLine = Trim$(Command$())
    Else
        '# sinon, on utilise celle effectivement fournie par l'utilisateur.
        vsCommandLine = Trim$(vsCommandLine)
    End If
    If LenB(vsCommandLine) Then
        '# On regarde la chaine, caractère par caractère
        For i = 1 To Len(vsCommandLine)
            '# On évite d'extraire deux fois le même caractère
            nChar = AscW(Mid$(vsCommandLine, i, 1))
            '# Si le caractère considéré est une guillemet, on incrémente le compteur
            If nChar = 34 Then
                bInQuotes = Not bInQuotes
            '# si c'est un espace...
            ElseIf nChar = 32 Then
                '# ...et que nous sommes en dehors d'un 'tronçon' avec des guillemets,
                '# on remplace l'espace par un carctère \0
                If Not bInQuotes Then
                    Mid$(vsCommandLine, i, 1) = vbNullChar
                End If
            End If
        Next i

        '# tout tronçon de chaîne ouvert par des " doit être fermé
        '# On teste donc si le nombre de guillemets est pair ou impair
        If bInQuotes Then
            Err.Raise vbString, , "Construction de la chaîne de paramètres incorrecte"
        Else
            '# On supprime les guillemets de la chaine finale
            vsCommandLine = Replace(vsCommandLine, ChrW$(34), vbNullString)
            '# On découpe la ligne de commande à chaque \0 rencontré
            ParseCommandLine = Split(vsCommandLine, vbNullChar)
        End If
    Else
        ReDim ParseCommandLine(0) As String
    End If
End Function

 Ajouter un commentaire


Discussions en rapport avec ce code source dans le forum

Argument de ligne de commande [ par sheur60 ] Je cherche a récupérer des arguments passer en ligne de commande de mon programme. Par exemple, si mon raccourci est C:\Prog.exe /toto, je cherche à r Argument de ligne de commande [ par sheur60 ] Je cherche a récupérer des arguments passer en ligne de commande de mon programme. Par exemple, si mon raccourci est C:\Prog.exe /toto, je cherche à r line argument [ par terriblepat ] bonjour,je cherche la commande qui va me permettre de récupérer un argument sur la ligne de commande ?the terrible terriblepat passage argument ligne de commande [ par jarni ] Quoi ecrire dans monprog.exe (créé en VB6) pour que le fichier taratata.xyz soit passé comme argument à monprog.exe dans un ultérieur:shell monprogr.e probleme argument ligne de commande URGENT [ par kevinscherrens ] Commen changer la valeur de l'argument de la ligne de commande dans le code de VB?MERCI D'AVANCE argument en ligne de commande [ par mesdebuts ] Bonjour à toutes et à tous ! J'ai actuellement un souci dans un programme en VB.Je m'explique, j'ai créé un programme qui va parcourir argument en ligne de commande [ par aurbadguy ] je sais qu'il est possible de recuperer ces arguments avec la fonction split sur la variables commandDim args() As Stringargs = Split(Command(), " ")< commande shell [ par Jeff ] Salut!!J'ai 1 commande shell qui lance 1 fichier a.batsi je mets 0 à l'argument Windowstyle le .bat fonctionneor si je veux cacher la fenetre lors de argument en ligne de commande [ par cartman29 ] Bonjour, Je travail actuellement sur un projet VB.NET pour une copie de fichier seulement je dois faire une sauvegarde journalière des données. J'a erreur de syntaxe dans access (3075) [ par real47 ] J'ai un probleme que je ne trouve pas a resoudre dans ma base de donné access J'ai toujours un message d'erreur 3075 qui apparait lorsque que je clik


Nos sponsors


Sondage...

CalendriCode

Février 2012
LMMJVSD
  12345
6789101112
13141516171819
20212223242526
272829    

Consulter la suite du CalendriCode

Photothèque

 
Développement réalisé par Nicolas SOREL (Nix) avec l'aide de : Cyril DURAND et Emmanuel (EBArtSoft), Merci à Vincent pour ses précieux conseils.
CodeS-SourceS.com© Toute reproduction même partielle est interdite sauf accord écrit du Webmaster
CodeS-SourceS.com© est une marque déposée tous droits réservés

Google Coop CodeS-SourceS Google Coop CodeS-SourceS
Temps d'éxécution de la page : 0,952 sec (3)

Nous contacter | Annoncer sur CodeS-SourceS | Mentions légales