Aller au contenu

Recuperer un réel dans une chaine


Hey_Its_Sanka

Messages recommandés

Bonjour !

 

Voici mon problème : J'ai pleins de chaînes différentes où récupérer un réel.

Existe-t-il une fonction Autolisp miracle ? Subtr ne correspond pas à ma problématique car oblige à définir un positionnement/longueur précis du réel à récupérer.

(Pour info mes réels varient entre 0 et 199 et leur décimales sont toujours séparés par des points.)

J'ai bien évidement chercher longuement sans trouver une réponse idéale, donc je vous demande de l'aide.

 

Mon rêve :

(Miracle "Blabla1.00") ---> 1.00

(Miracle "Blabla:123.45") ---> 123.45

(Miracle "Blabla 10.00Blabla") ---> 10.00

Si aucune fonction n'existe, je prend tout de même un code de secours...

 

Merci ! 😄

 

PS : Pour les petit(e)s curieux/ses, mon programme consiste à cliquer un point (pour sa valeur en x) et un texte/bloc avec attribut depuis un plan topo (pour sa valeur d'altitude écrite) et finalement créer une polyligne avec la liste de points créé et hachures de TN en vue de façade.

Je veux seulement pouvoir traiter n’importe quel texte du moment qu'il contient un réel (l'altitude) car ces derniers peuvent être écrits de diverses façons, selon le dessinateur du plan topo et la particularité du texte.

Lien vers le commentaire
Partager sur d’autres sites

Update :

j'ai réussi à faire sans la fonction avec ça :

(mais si vous avez une fonction qui le fait déjà, je suis prenneur !)

                                 (progn
                                        (setq w nil)
                                        (setq compteurdebut 1)
                                        (while
                                            (= (atof (substr txty compteurdebut 1) ) 0.0)
                                            (setq compteurdebut (1+ compteurdebut) )
                                        )
                                        (setq compteurfin compteurdebut)
                                        (while
                                            (and
                                                (/= compteurfin (strlen txty) )
                                                (or
                                                    (wcmatch (substr txty compteurfin 1) "*#*")
                                                    (= (substr txty compteurfin 1) ".")
                                                )
                                                (not w)
                                            )
                                            (if
                                                (= (substr txty compteurfin 1) ".")
                                                (setq w 1)
                                            )
                                            (setq compteurfin (1+ compteurfin) )
                                        )
                                        (while
                                            (and
                                                (/= compteurfin (strlen txty) )
                                                (wcmatch (substr txty compteurfin 1) "*#*") 
                                            )
                                            (setq compteurfin (1+ compteurfin) )
                                        )
                                        (setq y (atof(substr txty compteurdebut (- (1+ compteurfin) compteurdebut) ) ) )
                                        (setq pt (list x y))				;point final
                                    )

 

Lien vers le commentaire
Partager sur d’autres sites

Salut,

Avec les expressions régulières.

(defun miracle (str)
  (atof
    (caar (RegexpExecute str "(-?\\d+(?:\\.\\d+)?)" nil nil))
  )
)

Ou avec deux fonctions récursives une fonction récursive.

(defun miracle (str / loop)
  
  (defun loop (lst flag)
    (cond
      ((null lst) nil)
      ((< 47 (car lst) 58)
       (cons (car lst) (loop (cdr lst) (logior flag 1)))
      )
      ((and (= 46 (car lst))
	    (/= 0 flag)
       )
       (if (= flag 1)
	 (cons 46 (loop (cdr lst) 3))
       )
      )
      ((= flag 0)
       (loop (cdr lst) 0)
      )
      (T nil)
    )
  )
  
  (distof (vl-list->string (loop (vl-string->list str) 0)))
)

 

Gilles Chanteau - gileCAD - GitHub
Développements sur mesure pour AutoCAD

Lien vers le commentaire
Partager sur d’autres sites

Salut Gile, tu peux m'éclairer un peu sur les arguments inclus dans tes lisp? J'ai du mal 😅

Mettons que je te donne :

(setq txty "Seuil égal à : 76.84m...")

Comment tu écris le lisp avec cette donnée au début ? (sachant qu'avant et après l'altitude, il pourrait y avoir absolument nimporte quel caractère)

Merci

Lien vers le commentaire
Partager sur d’autres sites

La première solution avec les expressions régulières illustre assez bien la blague :

"Certaines personnes, lorsqu'elles sont confrontées à un problème, se disent "Je sais, je vais utiliser des expressions régulières". Maintenant, elles ont deux problèmes."

Je vais donc plutôt essayer d'expliquer comment fonctionne la seconde (que j'ai modifiée).

Tout d'abord, parce que LISP est basé sur les listes, on traiter le problème en utilisant une liste de caractères (nombres entiers) plutôt qu'une chaîne de caractères. La fonction vl-string->list convertit une chaine de caractère en liste d'entiers (les codes ASCII des caractères). La fonction vl-list->string permettra de faire la conversion inverse du résultat.

Pour traiter la liste, on utilise une fonction récursive qui prend en argument la liste de caractères et un drapeau qui indique si aucun chiffre n'a encore été trouvé (0), un ou plusieurs chiffres ont été trouvés (1), un point (séparateur décimal) a été trouvé après des chiffres (1 | 2 = 3).

Qui dit fonction récursive, dit condition d'arrêt. Dans ce cas deux conditions peuvent être rencontrées : la liste est vide ou un caractère non numérique est trouvé alors que le drapeau est supérieur à 0. Pour ces deux conditions la fonction revoie nil.

La fonction parcourt la liste élément par élément en constituant la liste qui sera renvoyée avec uniquement des chiffres et, éventuellement un point.

Exemple avec une chaîne simple : "ht=12.5m".

;; Premier appel (premier caractère = 'h')
(loop (104 116 61 49 50 46 53 109) 0)

;; Second appel (second caractère = 't')
(loop (116 61 49 50 46 53 109) 0)

;; Troisième appel (troisième caractère = '=')
(loop (61 49 50 46 53 109) 0)

;; Quatrième appel (quatrième caractère = '1')
(loop (49 50 46 53 109) 0)

;; Cinquième appel (cinquième caractère = '2')
(cons 49 (loop (50 46 53 109) 1))

;; Sixième appel (sixième caractère = '.')
(cons 49 (cons 50 (loop (46 53 109) 1)))

;; Septième appel (septième caractère = '5')
(cons 49 (cons 50 (cons 46 (loop (53 109) 3))))

;; Huitième appel (huitième caractère = 'm')
(cons 49 (cons 50 (cons 46 (cons 53 (loop (109) 3)))))

;; Dépilement
(cons 49 (cons 50 (cons 46 (cons 53 nil))))
(cons 49 (cons 50 (cons 46 '(53))))
(cons 49 (cons 50 '(46 53)))
(cons 49 '(50 46 53))
(49 50 46 53)

 

Gilles Chanteau - gileCAD - GitHub
Développements sur mesure pour AutoCAD

Lien vers le commentaire
Partager sur d’autres sites

Comme je sais que certains ont du mal avec la récursivité, voilà l'équivalent avec une boucle while

(defun miracle (str / lst res break dot)
  (setq lst (vl-string->list str))
  (while (and lst (not break))
    (cond
      ((< 47 (car lst) 58)
       (setq res (cons (car lst) res)
	     lst (cdr lst)
       )
      )
      ((= 46 (car lst))
	(if dot
	  (setq break T)
	  (if res
	    (setq res (cons 46 res)
		  lst (cdr lst)
		  dot T
	    )
	    (setq lst (cdr lst))
	  )
	)
      )
      (T
       (if res
	 (setq break T)
	 (setq lst (cdr lst))
       )
      )
    )
  )
  (distof (vl-list->string (reverse res)))
)

 

Gilles Chanteau - gileCAD - GitHub
Développements sur mesure pour AutoCAD

Lien vers le commentaire
Partager sur d’autres sites

  • 2 semaines après...

Créer un compte ou se connecter pour commenter

Vous devez être membre afin de pouvoir déposer un commentaire

Créer un compte

Créez un compte sur notre communauté. C’est facile !

Créer un nouveau compte

Se connecter

Vous avez déjà un compte ? Connectez-vous ici.

Connectez-vous maintenant
×
×
  • Créer...

Information importante

Nous avons placé des cookies sur votre appareil pour aider à améliorer ce site. Vous pouvez choisir d’ajuster vos paramètres de cookie, sinon nous supposerons que vous êtes d’accord pour continuer. Politique de confidentialité