Suite : Récupérer le chiffre

Le
Jean-marc
Hello à tous,

Faisant suite à la question de Greg
"comment récupérer les chiffre 142 et le 9;
exemple
SCALE: 1//142.9g/"


Comme je l'indiquais dans ma réponse initiale, ce genre de problème
se résoud typiquement par un petit automate à états finis, suivant
la technique décrite dans l'article de la FAQ:
http://faq.vb.free.fr/index.php?question3

Plutot qu'un long discours, voici comment on peut modéliser le
problème.

Description:
- Lire jusqu'au double slash
- Stocker les chiffres jusqu'à un point
- consommer le point
- lire les chiffres tant qu'il y en a (et les stocker)

Voici l'automate à états finis correspondant:
(Les états sont entre crochets carrés, les transitions entre
parenthèses. Les états finaux sont entre double crochets
carrés.).

Les états de sortie valides sont les états 6 et 7. L'état 4 est
final et invalide.


+(pas digit)->[[4]]
|
++ +-(/)->[2] +--( pas . )-->[[4]]
| (pas /) | | | (pas digit)
| | | | |
+->[0]-(/)>[1] +--(digit)-->[3]<+
^ | | |
| | | (digit)
+-(pas /)--+ | | |
| | |
| | |
| | |
[[4]]<--(pas digit)[5]<(.)--+ +-+
|
| +--(pas digit)-->[[7]]--+
| | ^ |
| | | (car)
+--(digit)-->[[6]]<-+ | |
| | +-+
| (digit)
| |
+-+

Il ne reste plus qu'à coder notre automate, ce qui se fait de façon
entièrement mécanique (c'est la beauté de la chose) :

Option Explicit

Function SplitScale(ByVal s As String, _
ByRef first As String, _
ByRef last As String) As Boolean

Dim etat As Integer
Dim car As String
Dim l As Long
Dim i As Long
Dim validStates As String

validStates = "6,7,"

l = Len(s)

If l > 0 Then

etat = 0
For i = 1 To l
car = Mid$(s, i, 1)
Select Case etat
Case 0
If IsSlash(car) Then
etat = 1
End If
Case 1
If IsSlash(car) Then
etat = 2
Else
etat = 0
End If
Case 2
If IsDigit(car) Then
first = first & car
etat = 3
Else
etat = 4 ' FIN
End If
Case 3
If IsDigit(car) Then
first = first & car
etat = 3
ElseIf IsDot(car) Then
etat = 5
Else
etat = 4 ' FIN
End If
Case 4
Exit For ' Force FIN
Case 5
If IsDigit(car) Then
last = last & car
etat = 6
Else
etat = 4 ' FIN
End If
Case 6
If IsDigit(car) Then
last = last & car
etat = 6
Else
etat = 7
End If
Case 7
etat = 7
End Select
Next i
End If

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

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

Private Function IsSlash(ByVal car As String) As Boolean
If car = "/" Then
IsSlash = True
End If
End Function


Private Function IsDot(ByVal car As String) As Boolean
If car = "." Then
IsDot = True
End If
End Function


Et pour tester:

Dim s As String
Dim first As String
Dim last As String
Dim ret As Boolean

s = Text1.Text
ret = SplitScale(s, first, last)
Label1.Caption = ret & " " & first & " " & last


Et voila. On a maintenant une fonction qui non seulement
fait ce qu'on voulait (récupérer ce qu'il faut de part et d'autre
de la virgule) mais qui en plus valide syntaxiquement la chaine.

Et cerise sur le gateau, ce genre d'implémentation est simplissime
à lire et à modifier si nécessaire.

Bonne soirée !

Cordialement;

--
Jean-marc Noury (jean_marc_n2)
Microsoft MVP - Visual Basic
FAQ VB: http://faq.vb.free.fr/
mailto: remove '_no_spam_' ; _no_spam_jean_marc_n2@yahoo.fr
Vidéos High-Tech et Jeu Vidéo
Téléchargements
Vos réponses
Gagnez chaque mois un abonnement Premium avec GNT : Inscrivez-vous !
Trier par : date / pertinence
bahn po
Le #17950511
Jean-marc a écrit :
Hello à tous,

Faisant suite à la question de Greg
"comment récupérer les chiffre 142 et le 9;
exemple
SCALE: 1//142.9g/"




txt = "SCALE: 1//142.9g/"
txt = Replace(txt, "SCALE: 1//", "")
txt = Replace(txt, "g/", "")

Dim final As Variant

final = Split(txt, ".")

Debug.Print final(0) & " avec " & final(1)


Bonne nuit...
PH
Le #17950711
Jean-marc a écrit :
Hello à tous,

Faisant suite à la question de Greg
"comment récupérer les chiffre 142 et le 9;
exemple
SCALE: 1//142.9g/"


Comme je l'indiquais dans ma réponse initiale, ce genre de problème
se résoud typiquement par un petit automate à états finis, suivant
la technique décrite dans l'article de la FAQ:
http://faq.vb.free.fr/index.php?question3

Plutot qu'un long discours, voici comment on peut modéliser le
problème.

Description:
- Lire jusqu'au double slash
- Stocker les chiffres jusqu'à un point
- consommer le point
- lire les chiffres tant qu'il y en a (et les stocker)

Voici l'automate à états finis correspondant:
(Les états sont entre crochets carrés, les transitions entre
parenthèses. Les états finaux sont entre double crochets
carrés.).

Les états de sortie valides sont les états 6 et 7. L'état 4 est
final et invalide.


+---(pas digit)---->[[4]]
|
+---+ +-(/)->[2] +--( pas . )-->[[4]]
| (pas /) | | | (pas digit)
| | | | |
+->[0]----(/)------>[1] +--(digit)-->[3]<------+
^ | | |
| | | (digit)
+----(pas /)-----+ | | |
| | |
| | |
| | |
[[4]]<--(pas digit)---[5]<---------(.)-----+ +----+
|
| +--(pas digit)-->[[7]]--+
| | ^ |
| | | (car)
+--(digit)-->[[6]]<----+ | |
| | +----+
| (digit)
| |
+-------+

Il ne reste plus qu'à coder notre automate, ce qui se fait de façon
entièrement mécanique (c'est la beauté de la chose) :

Option Explicit

Function SplitScale(ByVal s As String, _
ByRef first As String, _
ByRef last As String) As Boolean

Dim etat As Integer
Dim car As String
Dim l As Long
Dim i As Long
Dim validStates As String

validStates = "6,7,"

l = Len(s)

If l > 0 Then

etat = 0
For i = 1 To l
car = Mid$(s, i, 1)
Select Case etat
Case 0
If IsSlash(car) Then
etat = 1
End If
Case 1
If IsSlash(car) Then
etat = 2
Else
etat = 0
End If
Case 2
If IsDigit(car) Then
first = first & car
etat = 3
Else
etat = 4 ' FIN
End If
Case 3
If IsDigit(car) Then
first = first & car
etat = 3
ElseIf IsDot(car) Then
etat = 5
Else
etat = 4 ' FIN
End If
Case 4
Exit For ' Force FIN
Case 5
If IsDigit(car) Then
last = last & car
etat = 6
Else
etat = 4 ' FIN
End If
Case 6
If IsDigit(car) Then
last = last & car
etat = 6
Else
etat = 7
End If
Case 7
etat = 7
End Select
Next i
End If

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

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

Private Function IsSlash(ByVal car As String) As Boolean
If car = "/" Then
IsSlash = True
End If
End Function


Private Function IsDot(ByVal car As String) As Boolean
If car = "." Then
IsDot = True
End If
End Function


Et pour tester:

Dim s As String
Dim first As String
Dim last As String
Dim ret As Boolean

s = Text1.Text
ret = SplitScale(s, first, last)
Label1.Caption = ret & " " & first & " " & last


Et voila. On a maintenant une fonction qui non seulement
fait ce qu'on voulait (récupérer ce qu'il faut de part et d'autre
de la virgule) mais qui en plus valide syntaxiquement la chaine.

Et cerise sur le gateau, ce genre d'implémentation est simplissime
à lire et à modifier si nécessaire.

Bonne soirée !

Cordialement;



Superbe. Il y a bien longtemps que je n'avais pas entendu parler des
automates à état fini.
Publicité
Poster une réponse
Anonyme