Page 1 sur 1

Récupération de mots d'une chaine de caractères

Publié : sam. 26/juin/2010 14:12
par G-Rom
Stringfield() est une fonction très pratique pour récupérer des morceaux dans une chaine de caractères.
Mais hélàs il faut que la chaine que l'on passe en paramètres à Stringfield() ne comporte pas d'espace superflu ( en admettant que l'on veut récupérer chacun des mots entre les espaces)
car si il y a un espace entre 2 mots , stringfield() va pioché entre les 2 , c'est à dire rien , et vous renvoyer un #NULL

en admettant que vous avez ce genre de chaine à décortiqué :

Code : Tout sélectionner

TEXT$ = "Cette      Chaine  de        caracteres    à des espaces    superflu"

; Sans PackString
For i = 1 To CountString(TEXT$,Chr(32))
  Debug StringField(TEXT$,i,Chr(32))
Next 
le Debbuger renvois des #NULL entre les espaces.

tandis qu'avec PackString :

Code : Tout sélectionner

TEXT$ = "Cette      Chaine  de        caracteres    à des espaces    superflu"
TEXT$ = PackString(TEXT$,Chr(32))

; avec PackString
For i = 1 To CountString(TEXT$,Chr(32))+1
  Debug StringField(TEXT$,i,Chr(32))
Next 
C'est quand même plus propre !

Sortie :
Cette
Chaine
de
caracteres
à
des
espaces
superflu
La fameuse fonction :

Code : Tout sélectionner

Procedure.s PackString(string.s, separator.s)
  Protected Char.a=0
  Protected Fill.a=0
  Protected Out$
  
  For i = 1 To Len(string)
    Char = Asc(Mid(string,i,1))
    If Char <> 32
     Fill = 1 
     Out$ + Chr(Char)  
    EndIf 
    
    If Char = 32 And Fill = 1
      Fill = 0
      Out$ + separator
    EndIf 
  Next   
  
  ProcedureReturn Out$
EndProcedure

Re: Récupération de mots d'une chaine de caractères

Publié : sam. 26/juin/2010 20:02
par Ar-S

Code : Tout sélectionner

TEXT$ = "Cette Chaine de caracteres à des espaces superflu" 
; Sans PackString 
For i = 1 To CountString(TEXT$,Chr(32)) 
  Debug StringField(TEXT$,i,Chr(32)) 
Next  

TEXT$ = "Cette Chaine de caracteres à des espaces superflu" 
TEXT$ = PackString(TEXT$,Chr(32)) 
; avec PackString 
For i = 1 To CountString(TEXT$,Chr(32))+1 
  Debug StringField(TEXT$,i,Chr(32)) 
Next 
Me renvoient (j'ai pas remis la procedure mais bien sûr je l'utilise)

Code : Tout sélectionner

Cette
Chaine
de
caracteres
à
des
espaces

Cette
Chaine
de
caracteres
à
des
espaces
superflu

Donc il manque "superflu" à la fin du 1er debug. Est-ce le but de packString() ?

Re: Récupération de mots d'une chaine de caractères

Publié : sam. 26/juin/2010 21:18
par G-Rom
Le 1° debug n'utilise pas PackString() , il manque juste +1 à la fin de countstring() ;)

Re: Récupération de mots d'une chaine de caractères

Publié : sam. 26/juin/2010 21:18
par nico
Je ne comprend pas ta démo, avec ce code je n'ai aucun espace superflu:

Code : Tout sélectionner

TEXT$ = "Cette Chaine de caracteres à des espaces superflu" 
; Sans PackString 
For i = 1 To CountString(TEXT$,Chr(32)) +1
 Debug StringField(TEXT$,i,Chr(32)) 
Next 

Re: Récupération de mots d'une chaine de caractères

Publié : sam. 26/juin/2010 21:59
par G-Rom

Code : Tout sélectionner

TEXT$ = "Cette      Chaine  de        caracteres    à des espaces    superflu"

La mise en forme bouffe les espaces...

Re: Récupération de mots d'une chaine de caractères

Publié : sam. 26/juin/2010 22:24
par nico
J'avais compris entre-temps :)

Je préfère la version sans le ASC:

Code : Tout sélectionner

Procedure.s PackString(string.s, separator.s) 
 Protected Char.s
 Protected Fill.l=0 
 Protected Out$ 
  
 For i = 1 To Len(string) 
  Char.s = Mid(string,i,1)
  If Char <> " " 
   Fill = 1  
   Out$ + Char 
  ElseIf Char = " " And Fill = 1 
   Fill = 0 
   Out$ + separator 
  EndIf  
 Next    
  
 ProcedureReturn Out$ 
EndProcedure
Sympa ta procédure, je ne l'aurais pas fait de cette façon mais la tienne me parait bien meilleure. :)

Re: Récupération de mots d'une chaine de caractères

Publié : sam. 26/juin/2010 23:12
par nico
IL semble que cette version soit deux mille fois plus rapide que la tienne (d'après des tests sur un fichiers de 62.2Ko):

la tienne autour de 20000 ms
la nouvelle version entre 10 et 30 ms

C'est vrai que j'avais remarqué que les opérations sur les chaines avec PB étaient rapide mais là c'est impressionnant.

Code : Tout sélectionner

Procedure.s PackString2(string.s, separator.s)
  Protected Chaine$,Chaine2$
  Chaine$=Trim(string)
  Repeat
    Chaine2$=Chaine$
    Chaine$ = ReplaceString(Chaine$, separator+separator, separator)
  Until Chaine2$=Chaine$
  ProcedureReturn Chaine$
EndProcedure


La procédure de test (Il vous faudra créer le fichier test):

Code : Tout sélectionner

ReadFile(0, "test.txt")
longueur=Lof(0)
*mem=AllocateMemory(longueur)
ReadData(0,*mem,longueur)
TEXT$=PeekS(*mem)
CloseFile(0)

Procedure.s PackString(string.s, separator.s) 
 Protected Char.s
 Protected Fill.l=0,i.l
 Protected Out$ 
  
 For i = 1 To Len(string) 
  Char.s = Mid(string,i,1)
  If Char <> " " 
   Fill = 1  
   Out$ + Char 
  ElseIf Char = " " And Fill = 1 
   Fill = 0 
   Out$ + separator 
  EndIf  
 Next    
  
 ProcedureReturn Out$ 
EndProcedure

Procedure.s PackString2(string.s, separator.s) 
  Protected Chaine$,Chaine2$
  Chaine$=Trim(string)
  Repeat
    Chaine2$=Chaine$
    Chaine$ = ReplaceString(Chaine$, separator+separator, separator)
  Until Chaine2$=Chaine$
  ProcedureReturn Chaine$
EndProcedure

TempsDepart = ElapsedMilliseconds()
TEXT1$ = PackString(TEXT$,Chr(32)) 
TempsEcoule = ElapsedMilliseconds()-TempsDepart 
MessageRequester( "Info","Temps écoulé : "+Str(TempsEcoule)+" millisecondes" )
CreateFile(0,"test1.txt")
WriteString(0,TEXT1$)
CloseFile(0)

TempsDepart = ElapsedMilliseconds()
TEXT2$ = PackString2(TEXT$,Chr(32)) 
TempsEcoule = ElapsedMilliseconds()-TempsDepart 
MessageRequester( "Info","Temps écoulé : "+Str(TempsEcoule)+" millisecondes" )
CreateFile(0,"test2.txt")
WriteString(0,TEXT2$)
CloseFile(0)

Re: Récupération de mots d'une chaine de caractères

Publié : dim. 27/juin/2010 0:23
par G-Rom
8O
Merci nico , j'avais pas pensé à ce genre de différence !
c'est certainement du au fait que je parcours la chaine , je vois pas comment optimisé sans replacestring() du coup ?

Re: Récupération de mots d'une chaine de caractères

Publié : dim. 27/juin/2010 17:50
par Scrat
Salut

y' ça aussi

Code : Tout sélectionner

s.s="Cette      Chaine  de        caracteres    à des espaces    superflu 123"
Dim result$(0)
CreateRegularExpression(0,"[\H]+[\S]?")
NbFound = ExtractRegularExpression(0,s , Result$())
For k = 0 To NbFound-1
  Debug Result$(k)
Next

FreeRegularExpression(0)
a+


edit : \s remplacé par \S c'est mieux

Re: Récupération de mots d'une chaine de caractères

Publié : dim. 27/juin/2010 18:23
par SPH
Extremement simple et court :

Code : Tout sélectionner

txt$="Des            espaces  superflus      quelque    part ????    "

Repeat
lg=Len(txt$)
txt$=ReplaceString(txt$,"  "," ")
Until Len(txt$)=lg

Debug txt$
:mrgreen:

Re: Récupération de mots d'une chaine de caractères

Publié : dim. 27/juin/2010 18:35
par Scrat
oui mais je crois qu'il veut spliter la chaine en mots

A+

Re: Récupération de mots d'une chaine de caractères

Publié : lun. 30/août/2010 17:31
par GeBonet
Bonjour,

Voilà également une forme.... Le "truc" substituer 2 blancs par un point... Puis les retirer :wink:
Pour tester et après copie placer des espaces dans la chaine$... à boucher..
BBcode n'en veut pas lui... :wink:

Code : Tout sélectionner

; ---------------------------------------------------
; -- Autres évacuateur de blancs...        GeBonet --
; ---------------------------------------------------
; 
Chaine$="Je suis une chaîne          contenant    des         espaces  variables"
Debug "Au début :"
Debug "> "+Chaine$
;---------- Phase 1 : Remplace par des points ------
Repeat 
  If FindString(Chaine$,"  ",1)  ; Ici <2> blancs par <1> point
    ReplaceString(Chaine$,chr(32)+chr(32),".",#PB_String_InPlace,1):k=1 ; Flag pour boucler..
    Else :k=0:EndIf   
Until k=0  
;
;---------- Phase 2 : Retire les points ------
;
Repeat 
  If FindString(Chaine$,"..",1) Or FindString(Chaine$,"."+chr(32),1) 
    Repeat  
      x=FindString(Chaine$,"..",1)-1 
      If x>0  
        chaine$=Left(Chaine$,x)+Mid(Chaine$,x+3) 
      EndIf  
    Until x<1  
    x=FindString(Chaine$,"."+chr(32),1)-1 
    Repeat 
      If x>0 
        x=FindString(Chaine$,"."+chr(32),1)-1 
        chaine$=Left(Chaine$,x)+Mid(Chaine$,x+2) 
      EndIf 
    Until x<1  
  EndIf 
  
Until CountString(Chaine$,".")=0  
; 
Debug "> Forme finale : " 
Debug "> "+Chaine$ 
;
; Utilisation de "StringField" pour finir... 
;
For i = 1 To CountString(Chaine$,Chr(32))+1 
  Debug StringField(Chaine$,i,Chr(32)) 
Next  
End
;
Bon, ce n'est qu'un autre point de vue... Image

Re: Récupération de mots d'une chaine de caractères

Publié : lun. 30/août/2010 21:31
par GallyHC
Bonjour,

Apres quelque reflexion j'ai essaye de faire une fonction courte. J'espere ne pas etre hors sujet :).

Code : Tout sélectionner

Define i.l
Define result.s
Define chaine.s = "Cette      Chaine  de        caracteres    à des espaces    superflu"

For i = 1 To CountString(chaine,Chr(32)) + 1
  result = Trim(StringField(chaine,i,Chr(32)))
  If result <> ""
    Debug result  
  EndIf
Next i
Cordialement,
GallyHC

Re: Récupération de mots d'une chaine de caractères

Publié : lun. 30/août/2010 22:44
par GeBonet
GallyHC a écrit : Après quelque réflexion j'ai essaye de faire une fonction courte. J'espère ne pas être hors sujet :).
Ben non, c'est pas hors sujet... C'est aussi une solution dans le cas d'espaces...

Ma démarche est autres. Elle est de montrer que l'on peut utiliser des moyens détournés.
Comme dans l'exemple que je donne, d'utiliser un autre marqueur qui lui est plus contrôlable vu que c'est toi même qui le place (ici j'ai placé des points, car justement dans la phrase il pourrait y en avoir et alors serait inclus avec le mots le précédent avec ta forme. etc.).

Essaye :

Code : Tout sélectionner

Define chaine.s = "Cette      Chaine  de        caractères.    à des espaces.    superflu"
Mais dans le cas qui ne serait que composée de mots et d'espaces (et même de trop). Ta forme est beaucoup plus simple !
De plus je ne suis pas certain que la volonté de départ était de décomposer en mots, mais d'évacuer les espaces ou autres caractères récurrent...

En fait tout dépend de ce que l'on veux en faire... Si par exemple c'était un analyseur syntaxique... Il serait préférable de "capturer" les mots un par un au fur et à mesure qu'ils sont introduits... Cela permet une aide à compléter la frappe avec des mots valides lorsqu'il s'agit de "langage" ou "pseudo-langage". Enfin c'est ce que j'en pense... :wink: