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
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.
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..." ?
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?
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....
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".
' 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
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
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.
"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 !
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?
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.
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
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)
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.
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)
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.
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
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.
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
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....
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!
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
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
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...
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
J'ai testé la fonction avec plusieurs cas de figure, cela marche parfaitement.
++
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..." ?