Page 1 sur 2

[R] Changer un symbole sur deux

Posté : sam. 21 mars 2009 18:04
par eric
Bonjour,

Je souhaite réaliser un truc qui me semble assez simple mais je n'ai pour l'instant pas trouvé de solution.

J'ai une ligne de texte de type :

1;2;3;4;5;6;7;8;9;10

Je souhaiterais changer un ; sur 2 par un autre symbole (exemple @)

Ce qui donnerait :

1;2@3;4@5;6@7;8@9;10

Comment pourrais je réaliser cela ?

Merci

Re: [..] Changer un symbole sur deux

Posté : sam. 21 mars 2009 20:49
par Tlem
Comme ceci :

Code : Tout sélectionner

$Str = "1;2;3;4;5;6;7;8;9;10"

For $i = 4 To StringLen($Str) Step 4
    $Str = StringReplace($Str, $i, "@")
Next

MsgBox(0, "", $Str)
De rien ... :mrgreen:

Re: [..] Changer un symbole sur deux

Posté : sam. 21 mars 2009 22:55
par ani
c'est une idée, mais il changera le dernier caractère en @ en l'occurance le zero du 10
edit:après teste, c'est effectivement ce que je viend de dire.

hm pas évident tout çà ;)

un numéro + séparateur + un numéro & remplacement du séparateur, vais essayer mais je promet rien ;)

Re: [..] Changer un symbole sur deux

Posté : sam. 21 mars 2009 23:09
par Iste
Ben, on découpe tout et on recolle ?

Code : Tout sélectionner

$coupe = StringSplit("1;2;3;4;kikoolol;5;6;7;8;9;10",";")
$change = 1
$colle = ""

For $i = 1 To $coupe[0]
    If $change Then
        $colle = $colle & $coupe[$i] & ";"
        $change = 0
    Else
        $colle = $colle & $coupe[$i] & "@"
        $change = 1
    EndIf
Next

MsgBox("","",$colle)
(changer $change en 0 pour inverser)

Edit :
petite modif qui evite de rajouter un separateur a la fin :

Code : Tout sélectionner

$coupe = StringSplit("1;2;3;4;kikoolol;5;6;7;8;9;10",";")
$change = 1
$colle = ""

For $i = 1 To $coupe[0]
    If $change Then
        If $i < $coupe[0] Then
            $colle = $colle & $coupe[$i] & ";"
        Else
            $colle = $colle & $coupe[$i]
        EndIf
        $change = 0
    Else
        If $i < $coupe[0] Then
            $colle = $colle & $coupe[$i] & "@"
        Else
            $colle = $colle & $coupe[$i]
        EndIf
        $change = 1
    EndIf
Next

MsgBox("","",$colle)

Re: [..] Changer un symbole sur deux

Posté : sam. 21 mars 2009 23:25
par Voodoo

Code : Tout sélectionner

$Str = "1;2;3;4;5;6;7;8;9;10"


$str=StringReplaceFreq($str,";","@",2)

#cs
    StringReplaceFreq
    retourne : 
        String si reussi
        1 si le caractére à chercher n'est pas de la même longueur que celui à ajouter.
    parametres:
        $string: chaine à traiter
        $toFind: Caractére à chercher
        $toReplace: Caractére à ajouter
        $howMany: Frequence du remplacement
#ce


func StringReplaceFreq($string,$toFind,$toReplace,$howMany)
    if StringLen($toFind) <> StringLen($toReplace) then return 1
    local $i,$count=0
    for $i=0 To StringLen($string)
        if StringCompare(StringMid($string,$i,stringlen($toFind)),$toFind) == 0 then $count+=1
        if $count >= $howMany then
            $string=StringReplace($string,$i,$toReplace)
            $count=0
        EndIf
    next
    return $string;
EndFunc



MsgBox(0, "", $Str)

Comme ça on est ni river au caractére ";" ni à la fréquence des remplacements \o/

Re: [..] Changer un symbole sur deux

Posté : sam. 21 mars 2009 23:33
par ani
whouaaaaa super fonction et hop a rajouter :)
merci voodoo :)
j'ai pas mieux à proposer je partais sur (\d;\d*) et grr :)

Re: [..] Changer un symbole sur deux

Posté : lun. 23 mars 2009 10:49
par eric
Bonjour à tous et merci de vous être penché sur le problème.

La solution de VooDoo est effectivement intéressante.

N'étant pas encore aussi calé j'étudie doucement ce code.

Pouvez vous me rapeller ce que signifie == et += (je connais par contre <> qui signifie différent).

Par contre avec cette méthode il faut que le caractère à chercher et celui à remplacer soit de la même longueur.

Dans certain cas je dois remplacer un ; par deux ou trois caractères.

J'ai aussi essayé de supprimer un caractère sur deux avec cette méthode mais apparement on ne peut pas mettre rien comme caractère de remplacement.

Code : Tout sélectionner

$str=StringReplaceFreq($str,";","",2)
(ne fonctionne pas).

Comme ça on est ni river au caractére ";" ni à la fréquence des remplacements
Je ne l'avais pas précisé mais c'était effectivement important parce que le texte peut contenir des mots de taille variable et contenir des nombres de ; différent d'un texte à l'autre.

Merci beaucoup pour votre aide.

Re: [..] Changer un symbole sur deux

Posté : lun. 23 mars 2009 11:29
par Voodoo
== signifie = en étant "case sensitive" si tu compares des string. C'est à dire que "ok" est différent de "Ok" ou "oK". (dans ma fonction ce n'est pas utile puisque l'on compare à 0, c'est juste une habitude que j'ai prise :mrgreen: )

$count+=1 équivaut a $count=$count+1

Pour la liste des operators regarde ici

Effectivement $str=StringReplaceFreq($str,";","",2) ne fonctionne pas car ce n'est pas de la même longueur, pour cela il faut tricher avec un $str=StringReplaceFreq($str,";",chr(0),2).

Re: [..] Changer un symbole sur deux

Posté : lun. 23 mars 2009 12:21
par eric
Merci pour le lien vers les opérateurs.
Effectivement $str=StringReplaceFreq($str,";","",2) ne fonctionne pas car ce n'est pas de la même longueur, pour cela il faut tricher avec un $str=StringReplaceFreq($str,";",chr(0),2).
Ca n'a pas l'air de fonctionner.

Dans l'exemple donné cela retourne seulement :

1;2

Re: [..] Changer un symbole sur deux

Posté : lun. 23 mars 2009 13:14
par Voodoo
exact, bon c'est du bidouillage de toute façon mais si tu mets Chr(28) la sa marche !

Re: [..] Changer un symbole sur deux

Posté : lun. 23 mars 2009 14:18
par eric
C'est effectivement de la bidouille mais je cherche un moyen aussi de remplacer un Chr(34) & ";" & Chr(34) par un @.

Le chr(0) correspond apparement à une fin de chaine de caractère d'ou l'arrêt après le 2.

Le chr(28) est semble t il une sorte d'espace insécable donc c'est pas tout à fait ça.

C'est pas si simple ce truc finalement. :wink:

Re: [..] Changer un symbole sur deux

Posté : lun. 23 mars 2009 14:47
par Iste
Avec mon code tu peux remplacer par ce que tu veux !

Code : Tout sélectionner

$string = "1;2;3;4;kikoolol;5;6;7;8;9;10"
$Remplacer = ";"
$par = "YMCA"

$coupe = StringSplit($string,$Remplacer,1) ;Cette ligne découpe la chaine et met chaque petit bout dans une array. [0] contien le nombre de petits bout, et le ,1 a la fin signifit que le separteur est TOUT ce qu'il y a ecris (par defaut, si on lui donne ",;:" comme separateur, il découpe a chaque "," ou ";" ou ":")
$change = 1 ;ca c'est juste un boléen qui dit "on change" ou "on change pas" pour modifier un caractere ur deux
$colle = "" ;heu... ben c'est le resultat, mais pour le moment c'est vide...

For $i = 1 To $coupe[0] ;On lit chaque petit bout découpé
    If $change Then ;Si $change est sur 1, on change le separateur 
        If $i < $coupe[0] Then ;si c'est le dernier petit bout, on met pas de separateur a la fin
            $colle = $colle & $coupe[$i] & $Remplacer ; on rajoute le bout de chaine a la suite des autre, et on place le separateur
        Else ;si on est a la fin,
            $colle = $colle & $coupe[$i] ; on rajoute le bout de chaine a la suite des autre, et on place pas le separateur vu qu'on est a la fin
        EndIf
        $change = 0 ;on previen que le prochain faudra pas changer
    Else ;si on change pas, on colle le bout lu suivit du separateur normal
        If $i < $coupe[0] Then ;si c'est le dernier petit bout, on met pas de separateur a la fin
            $colle = $colle & $coupe[$i] & $par ; on rajoute le bout de chaine a la suite des autre, et on place le separateur normal
        Else ;si on est a la fin,
            $colle = $colle & $coupe[$i] ; on rajoute le bout de chaine a la suite des autre, et on place pas le separateur vu qu'on est a la fin
        EndIf
        $change = 1 ;et la on dit que le prochain on le change
    EndIf
Next

MsgBox("","",$colle)
par contre, il est surement moin optimisé, donc si ton code doit etre rapide, prend pas cette solution.

Re: [..] Changer un symbole sur deux

Posté : lun. 23 mars 2009 16:52
par eric
Merci Iste pour ce code que j'ai un peu plus de mal à comprendre.

Je l'ai testé et il fonctionne sur mon exemple simple mais ne semble pas accepter plus d'un caractère pour le séparateur.

Si je prend comme exemple :

Code : Tout sélectionner

$str = ("1;;2;;3;;4;;5;;6;;7;;8;;9;;10;")
    
    $Remplacer =  ";;" 
$par = "@@"

$coupe = StringSplit($str,$Remplacer)
$change = 1
$colle = ""

For $i = 1 To $coupe[0]
    If $change Then
        If $i < $coupe[0] Then
            $colle = $colle & $coupe[$i] & $Remplacer
        Else
            $colle = $colle & $coupe[$i]
        EndIf
        $change = 0
    Else
        If $i < $coupe[0] Then
            $colle = $colle & $coupe[$i] & $par
        Else
            $colle = $colle & $coupe[$i]
        EndIf
        $change = 1
    EndIf
Next

MsgBox("","",$colle)
J'obtiens :

1;;@@2;;@@3;;@@4;;@@5;;@@6;;@@7;;@@8;;@@9;;@@10;;

Eh ben je n'imaginais pas que c'étais aussi compliqué de faire cela :oops:

Re: [..] Changer un symbole sur deux

Posté : lun. 23 mars 2009 17:06
par eric
C'est pas trop grave, je pense garder la version de VooDoo

Je ferais un :

Code : Tout sélectionner

$str=StringReplaceFreq($str,";","@",2)
Et si j'ai besoin de mettre par exemple 2 @ je rajouterais un :

Code : Tout sélectionner

StringReplace ($str,"@","@@")

Re: [..] Changer un symbole sur deux

Posté : lun. 23 mars 2009 18:14
par Iste
oui non, j'ai oublié un parametre pour dir que le truc a remplacer fait pas forcement un caratere, je vais edit mon precedent post, et expliquer comment ca marche

Re: [..] Changer un symbole sur deux

Posté : lun. 23 mars 2009 18:57
par Max5
Voici une autre possibilité que je viens de faire, utilisant les expressions régulières, mais j'ignore si elle est très flexible.
En tout cas ça marche pour l'exemple donné :

Code : Tout sélectionner

$replace = remplacement_1_sur_2("1;2;3;4;5;6;7;8;9;10", ";", "@")

MsgBox(0, "result", $replace)

Func remplacement_1_sur_2($sString, $sRecherche, $sRemplacement)
    If StringRight($sString, "1") <> $sRecherche Then
        $sString = $sString & $sRecherche
    EndIf

    $split = StringRegExp($sString, "(.*?" & $sRecherche & ").*?", 3)

    $1_sur_2 = ""
    For $i = 1 To UBound($split) - 1 Step 2
        $1_sur_2 = $1_sur_2 & $split[$i-1] & StringReplace($split[$i], $sRecherche, $sRemplacement)
    Next

    Return StringLeft($1_sur_2, StringLen($1_sur_2) - 1)
EndFunc
 

Re: [..] Changer un symbole sur deux

Posté : lun. 23 mars 2009 21:29
par Tlem
@Max5 : La coloration syntaxique est réservée aux forums Exemples, Tutoriels et Fonctions et UDF.
Merci.

Re: [..] Changer un symbole sur deux

Posté : mar. 24 mars 2009 16:04
par eric
Bonjour et merci Max5.

Ca a l'air de bien fonctionner aussi.

Re: [..] Changer un symbole sur deux

Posté : mar. 24 mars 2009 16:05
par eric

Code : Tout sélectionner

if StringCompare(StringMid($string,$i,stringlen($toFind)),$toFind) == 0 then $count+=1
J'ai un peu de mal à comprendre cette ligne.

Est ce que quelqu'un pourrais l'expliquer plus en détail SVP

Merci.

Re: [..] Changer un symbole sur deux

Posté : mar. 24 mars 2009 17:34
par Voodoo
StringMid a besoin de la chaine ($string), de la position de depart: ici donné par $i pour balayer toute la chaine $string et de combien de caractères il doit avancer: nous ce qui nous intéresse c'est de comparer $toFind donc on cherche quelque chose de la même taille d'ou le stringlen($toFind). Avec le StringMid on arrive donc à découper la chaine, il faut la comparer en utilisant StringCompare et tout sa nous permet d'incrémenter $count afin de savoir combien de fois on a trouvé $toFind.