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

Partagez votre expérience de PureBasic avec les autres utilisateurs.
G-Rom
Messages : 3641
Inscription : dim. 10/janv./2010 5:29

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

Message 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
Avatar de l’utilisateur
Ar-S
Messages : 9539
Inscription : dim. 09/oct./2005 16:51
Contact :

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

Message 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() ?
~~~~Règles du forum ~~~~
⋅.˳˳.⋅ॱ˙˙ॱ⋅.˳Ar-S ˳.⋅ॱ˙˙ॱ⋅.˳˳.⋅
W11x64 PB 6.x
Section HORS SUJET : ICI
LDV MULTIMEDIA : Dépannage informatique & mes Logiciels PB
UPLOAD D'IMAGES : Uploader des images de vos logiciels
G-Rom
Messages : 3641
Inscription : dim. 10/janv./2010 5:29

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

Message par G-Rom »

Le 1° debug n'utilise pas PackString() , il manque juste +1 à la fin de countstring() ;)
nico
Messages : 3702
Inscription : ven. 13/févr./2004 0:57

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

Message 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 
G-Rom
Messages : 3641
Inscription : dim. 10/janv./2010 5:29

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

Message par G-Rom »

Code : Tout sélectionner

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

La mise en forme bouffe les espaces...
nico
Messages : 3702
Inscription : ven. 13/févr./2004 0:57

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

Message 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. :)
nico
Messages : 3702
Inscription : ven. 13/févr./2004 0:57

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

Message 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)
G-Rom
Messages : 3641
Inscription : dim. 10/janv./2010 5:29

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

Message 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 ?
Scrat
Messages : 86
Inscription : sam. 15/mars/2008 16:00

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

Message 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
Avatar de l’utilisateur
SPH
Messages : 4937
Inscription : mer. 09/nov./2005 9:53

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

Message 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:

!i!i!i!i!i!i!i!i!i!
!i!i!i!i!i!i!
!i!i!i!
//// Informations ////
Intel Core i7 4770 64 bits - GTX 650 Ti
Version de PB : 6.12LTS- 64 bits
Scrat
Messages : 86
Inscription : sam. 15/mars/2008 16:00

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

Message par Scrat »

oui mais je crois qu'il veut spliter la chaine en mots

A+
Avatar de l’utilisateur
GeBonet
Messages : 453
Inscription : ven. 29/févr./2008 16:17
Localisation : Belgique

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

Message 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
Windows 7 et Windows 8.1 Pb 5.0 jusque 5.24 Lts 64 et 5.3 (64)/b]
“Ceux qui rêvent éveillés ont conscience de mille choses qui échappent à ceux qui ne rêvent qu’endormis.”
-Edgar Allan Poe-
Avatar de l’utilisateur
GallyHC
Messages : 1708
Inscription : lun. 17/déc./2007 12:44

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

Message 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
Configuration : Tower: Windows 10 (Processeur: i7 "x64") (Mémoire: 16Go) (GeForce GTX 760 - 2Go) - PureBasic 5.72 (x86 et x64)
Avatar de l’utilisateur
GeBonet
Messages : 453
Inscription : ven. 29/févr./2008 16:17
Localisation : Belgique

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

Message 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:
Windows 7 et Windows 8.1 Pb 5.0 jusque 5.24 Lts 64 et 5.3 (64)/b]
“Ceux qui rêvent éveillés ont conscience de mille choses qui échappent à ceux qui ne rêvent qu’endormis.”
-Edgar Allan Poe-
Répondre