Twitter iPhone pliant OnePlus 11 PS5 Disney+ Orange Livebox Windows 11

Extraire une chaine de caractères

3 réponses
Avatar
Jacques
Bonjour,

Je tourne en rond avec les fonctions mid, instr, right, left, etc.

J'ai une chaine de caractères composée de lettres et de chiffres comme par
exemple :

ABC_1_1 ou ABC_10_1 ou ABC_2_11 ou encore ABC_22_44

Les nombres peuvent être composés de 1 ou deux chiffres.
J'essaie d'extraire le premier nombre et le deuxième nombre sans savoir s'il
est composé d'un ou deux chiffres.

Merci de vos réponses


Jacques

3 réponses

Avatar
François Picalausa
On Aug 10, 12:43 am, "Jacques" wrote:
Je tourne en rond avec les fonctions mid, instr, right, left, etc.

J'ai une chaine de caractères composée de lettres et de chiffres comm e par
exemple :

ABC_1_1 ou ABC_10_1 ou ABC_2_11 ou encore ABC_22_44

Les nombres peuvent être composés de 1 ou deux chiffres.
J'essaie d'extraire le premier nombre et le deuxième nombre sans savoir s'il
est composé d'un ou deux chiffres.



Hello,

Ce qui t'intéresse n'est donc pas la position des nombres, mais bien
celle des séparateurs.

Le principe serait le suivant:
1/ On récupère la position du premier séparateur à l'aide d'Instr
2/ Si on a un premier séparateur valide, on récupère la position du
second à partir d'instr
3/ Si le second séparateur est valide,
3b/ on récupère le texte entre les deux (donc a partir de premier
séparateur +1, sur une longeur de second séparateur - premier
séparateur -1)
3c/ on récupère après le second séparteur (donc a partir de second
séparateur +1)
4/ si besoin en est, on cint les nombres

Voici une traduction possible en VBS de ceci (VBS ne supportant pas le
typage des variables, les types appropriés pour VB6 sont indiqués en
commentaire):
Const strText = "ZYX_1_45" 'As String
Dim strPrefix 'As String
Dim lngNum1 'As Long
Dim lngNum2 'As Long

If (ParseName(strText, strPrefix, lngNum1, lngNum2)) Then
MsgBox strPrefix & "_" & lngNum1 & "_" & lngNum2
Else
MsgBox "Failed"
End If

'String, String, Long, Long, returns Boolean
Function ParseName(Text, ByRef Prefix, ByRef Num1, ByRef Num2)
Const Separator = "_" 'As String
Const MIN_SIZE = 4 'As Long 'Equivalent a aucun préfix et 2
chifres (p.ex. "_0_2" )
Dim lngSepPos1 'As Long
Dim lngSepPos2 'As Long

ParseName = False

'Evite les opérations inutiles
If Len(Text) > MIN_SIZE Then
'Recherche les deux séparateurs
lngSepPos1 = Instr(1, Text, Separator)
lngSepPos2 = Instr(lngSepPos1 + 1, Text, Separator)

If (lngSepPos2 <> 0) Then
'Les deux séparateurs ont été trouvés
'Récupère les différentes parties de la chaine
Num1 = CLng(Mid(Text, lngSepPos1 + 1, lngSepPos2 -
lngSepPos1 - 1))
Num2 = CLng(Mid(Text, lngSepPos2 + 1))
Prefix = Left(Text, lngSepPos1 - 1) 'Utiliser Left$ en
place de Left

ParseName = True
End if
End If
End Function

François
Avatar
Jean-marc
Jacques wrote:
Bonjour,

Je tourne en rond avec les fonctions mid, instr, right, left, etc.

J'ai une chaine de caractères composée de lettres et de chiffres
comme par exemple :

ABC_1_1 ou ABC_10_1 ou ABC_2_11 ou encore ABC_22_44

Les nombres peuvent être composés de 1 ou deux chiffres.
J'essaie d'extraire le premier nombre et le deuxième nombre sans
savoir s'il est composé d'un ou deux chiffres.

Merci de vos réponses



En complément de la réponse de mon éminent collègue, tu
peux aussi si tu en disposes utiliser la fonction Split():

' ------------------------------------------------

Private Sub Parse(ByVal buffer As String, _
ByVal separator As String, _
ByRef number1 As Long, number2 As Long)
Dim t() As String

t() = Split(buffer, separator)
If (UBound(t()) - LBound(t())) = 2 Then
number1 = CLng(Val(t(1)))
number2 = CLng(Val(t(2)))
End If
End Sub

' ------------------------------------------------


Mais il y a une alternative magnifique: lire l'article
de la FAQ sur la validation de données complexes à l'aide
d'automates:
http://faq.vb.free.fr/index.php?question3

Il suffit d'une toute petite adaptation pour ton cas.

Voici le code de l'automate qu'il te faut:

' ------------------------------------------------

Private Function ParseAutomaton(ByVal s As String, _
ByRef n1 As Long, _
ByRef n2 As Long) As Boolean
Dim etat As Integer
Dim car As String
Dim l As Long
Dim i As Long
Dim validStates As String

Dim sn1 As String, sn2 As String

validStates = "4"

l = Len(s) ' longueur de la chaine d'entrée

If l > 0 Then ' si chaine pas vide

For i = 1 To l ' puis on avance caractere par caractere
car = Mid$(s, i, 1)
Select Case etat ' et on suit l'automate
Case 0
If IsDigit(car) Then
sn1 = sn1 & car
etat = 1
End If
Case 1
If IsDigit(car) Then
sn1 = sn1 & car
Else
n1 = Val(sn1)
etat = 2
End If
Case 2
If IsDigit(car) Then
sn2 = sn2 & car
etat = 3
End If
Case 3
If IsDigit(car) Then
sn2 = sn2 & car
Else
n2 = Val(sn2)
etat = 4
End If
Case 4
' on a fini ...
End Select
Next i
End If
If etat = 3 Then
n2 = Val(sn2)
etat = 4
End If

If InStr(validStates, Trim$(Str$(etat)) & ",") > 0 Then
ParseAutomaton = True
Else
ParseAutomaton = False
End If
End Function

Private Function IsDigit(car As String) As Boolean
If car >= "0" And car <= "9" Then
IsDigit = True
End If
End Function

' ------------------------------------------------

Et voici pour tester tous les cas:

Private Sub Command1_Click()
Dim n1 As Long, n2 As Long
Dim buffer As String

buffer = "ABC_1_23"
Parse buffer, "_", n1, n2
Debug.Print n1, n2

buffer = "ABC_12_3"
Parse buffer, "_", n1, n2
Debug.Print n1, n2

buffer = "ABC_12_34"
Parse buffer, "_", n1, n2
Debug.Print n1, n2

buffer = "ABC_1_2"
Parse buffer, "_", n1, n2
Debug.Print n1, n2

buffer = "_99_98"
Parse buffer, "_", n1, n2
Debug.Print n1, n2

End Sub

QC: ok, ça marche dans tous les cas, aussi bien avec Parse qu'avec
ParseAutomaton.

Un automate à états finis est *LA* plus belle chose et l'outil le plus
puissant qui soit en informatique.

A noter qu'il ne m'a fallu que 2 minutes pour adapter le code donné
en exemple dans la FAQ à ton cas particulier. Le code est à 90% identique.

===>> Vive les Automates !! <<==
Bonne prog!

--
Jean-marc Noury (jean_marc_n2)
Microsoft MVP - Visual Basic
mailto: remove '_no_spam_' ;
FAQ VB: http://faq.vb.free.fr/
Avatar
Jacques
Merci vous deux !!

Jacques


"Jacques" a écrit dans le message de news:
#
Bonjour,

Je tourne en rond avec les fonctions mid, instr, right, left, etc.

J'ai une chaine de caractères composée de lettres et de chiffres comme par
exemple :

ABC_1_1 ou ABC_10_1 ou ABC_2_11 ou encore ABC_22_44

Les nombres peuvent être composés de 1 ou deux chiffres.
J'essaie d'extraire le premier nombre et le deuxième nombre sans savoir


s'il
est composé d'un ou deux chiffres.

Merci de vos réponses


Jacques