Gambas France BETA


Pas de compte ? Incription

[Résolu]Fonction Val(chaine à chiffre)

Ce sujet est résolu.

1
AuteurMessages
Gamuti#1 Posté le 15/11/2010 à 10:48:00
Bonjour à tous.

J'ai un petit soucis concernant la fonction Val()
Val() permet de retourner un nombre à partir d'une chaine de caractère.
Voici ma chaine de caractères (extrait d'un site internet quelconque) :
<EM><STRONG>18.99</STRONG></EM>

La chaine est stockée dans la variable r.

Pour extraire le nombre 18,99, je fais ceci :
1
IF Mid(r, 1, 12) = Prix.Text THEN TabTxt[n].Text = Str(20 + Val(Mid(r, 13, 5))) & " €"

Ce qui devrait me retourner la valeur 18,99 incrémentée de 20 soit : 38.99 €
Sauf que ça ne marche pas comme je le voudrait.
Val() me retourne l'erreur
Type Mismatch, wanted number, got Null Instead

Ça plante au niveau de
1
Val(Mid(r,13,5))

Si je tapes
1
PRINT Mid(r,13,5)
, ça me renvoie
18,99

Mais dès que je tapes
1
Val(Mid(r,13,5)

L'interpréteur me retourne un Null

Une idée pour résoudre cette erreur d'interprétation ?
Gamuti#2 Posté le 15/11/2010 à 11:00:00
Trouvé !
C'est juste que l'interpréteur ne comprend pas le point d'un nombre décimal.
Il faut avant tout, convertir le point en virgule.
18.99 est différent de 18,99 (erreur de débutant...)
spheris#3 Posté le 15/11/2010 à 12:55:00
Gamuti,
peux-tu nous donner le code pour transformer ton . en virgule ?
;) ;)
Gamuti#4 Posté le 15/11/2010 à 13:57:00
En fait,
J'ai extrait les deux premiers chiffres puis les deux derniers.
Ensuite, j'ai fait un simple calcul :
- 2 premiers chiffres = x
- 2 derniers chiffres = y
Formule mathématique : somme = X + (Y / 100)

Concrètement, par rapport à mon code, cela donnerait :
1
TabImg[n].Tag = Str(Val(Mid(r, 13, 2)) + Val(Mid(r, 16, 2)) / 100) & " €"


Mais il doit exister beaucoup plus simple. Peut-être que la ValueBox permettrait d'éviter ce genre de calcul. Je n'ai pas essayé. À voir...

Enfin, il existe, dans l'index, le code Replace$() qui permet de convertir des chaines complètes :

1
PRINT Replace$("Gambas is a cool basic", "bas", "BAS")GamBAS IS a cool BASic

(je l'ai lu dans la doc)

Dans cet esprit, on devrait pouvoir réaliser ceci :
1
PRINT Replace$("18.99", ".", ",")18,99
spheris#5 Posté le 15/11/2010 à 20:23:00
permet moi d'ajouter une chose :

Il te faut faire un test pour voir si ta chaine de caractères est bien un nombre.
Dans ce cas tu rempli ta valuebox, sinon tu fais ta conversion et après tu remplis ta valuebox.


;) ;)
Prokopy#6 Posté le 16/11/2010 à 00:53:00
Kinder PinguiSalut,

Si je puis me permettre, pourquoi n'utilises-tu pas Replace$() pour retirer <em> et <strong> ? Ce serait plus clair :

1
r=Replace$(r, "<STRONG>", "")r=Replace$(r, "<EM>", "")r=Replace$(r, "</STRONG>", "")r=Replace$(r, "</EM>", "")


En ce qui concerne la fonction Val(), utilise plutôt la fonction CFloat() à la place. Val() prend en charge la localisation, c'est-à-dire le pays où tu vis. Comme tu le sais sans doute, le séparateur décimal anglais est le point, alors qu'en France on préfère la virgule. Donc, si un anglais essaie ton code, Val() va essayer de transformer "13,99" en un nombre décimal, ce qui va planter puisqu'en Angleterre on utilise le point.
CFloat() permet de résoudre ce problème, car lui il ne cherchera qu'un point et pas autre chose (il ne s'occupe pas de savoir ce que tu utilises). De plus, comme ta chaîne utilise déjà le point, tu évites de te taper le replacement de "." vers ",". ;)
La théorie, c'est quand on sait tout et que rien ne fonctionne.
La pratique, c'est quand ça marche mais qu'on ne sait pas pourquoi.
Quand la théorie rejoint la pratique, rien ne fonctionne et on ne sait pas pourquoi.
Gamuti#7 Posté le 16/11/2010 à 08:55:00
Salut,

Si je puis me permettre, pourquoi n'utilises-tu pas Replace$() pour retirer <em> et <strong> ? Ce serait plus clair :

1
r=Replace$(r, "<STRONG>", "")r=Replace$(r, "<EM>", "")r=Replace$(r, "</STRONG>", "")r=Replace$(r, "</EM>", "")


L'idée est bonne.
Ceci-dit, pour un simple petit programme sans aucune prétention. Le but de mon petit soft étant de mettre à jour les tarifs de ma boutique en ligne de façon automatisée.
Replace$() est une méthode révolutionnaire mais je trouve que
1
Str(Val(Mid(r, 13, 2))

est beaucoup plus léger à utiliser. D'autant que je ne fait qu'extraire que 2 malheureux chiffres d'une chaine de caractère.

En ce qui concerne la fonction Val(), utilise plutôt la fonction CFloat() à la place. Val() prend en charge la localisation, c'est-à-dire le pays où tu vis. Comme tu le sais sans doute, le séparateur décimal anglais est le point, alors qu'en France on préfère la virgule. Donc, si un anglais essaie ton code, Val() va essayer de transformer "13,99" en un nombre décimal, ce qui va planter puisqu'en Angleterre on utilise le point.
CFloat() permet de résoudre ce problème, car lui il ne cherchera qu'un point et pas autre chose (il ne s'occupe pas de savoir ce que tu utilises). De plus, comme ta chaîne utilise déjà le point, tu évites de te taper le replacement de "." vers ",". ;)

Oui, mille fois oui !!
En effet, j'extrais la chaine de caractère depuis un site hébergé en Espagne. Mais il est traduit en plusieurs langues. Ce qui implique une attention particulière quant à la validation des paramètres régionaux.
permet moi d'ajouter une chose :

Il te faut faire un test pour voir si ta chaine de caractères est bien un nombre.
Dans ce cas tu rempli ta valuebox, sinon tu fais ta conversion et après tu remplis ta valuebox.

Je n'utilise pas la ValueBox. Mais directement des variables. Ceci pour trois raisons :
- nécessité de rajouter un paquet dans le projet
- ça permet de continuer à programmer "à l'ancienne"
- ça permet de manipuler les chaines de caractères (et de ne pas perdre la main - bon d'accord, ce n'est pas une raison évidente...)

En tout cas, merci de vos réponses. Ça permet d'améliorer en simplicité les programmes.
Prokopy#8 Posté le 16/11/2010 à 12:50:00
Kinder Pingui
Ceci-dit, pour un simple petit programme sans aucune prétention. Le but de mon petit soft étant de mettre à jour les tarifs de ma boutique en ligne de façon automatisée.
Replace$() est une méthode révolutionnaire mais je trouve que
1
Str(Val(Mid(r, 13, 2))

est beaucoup plus léger à utiliser. D'autant que je ne fait qu'extraire que 2 malheureux chiffres d'une chaine de caractère.


Certes, mais cette méthode est "statique" : si jamais quelque chose est modifié dans la chaîne (une espace quelque part par exemple), ou que par exemple le chiffre n'est pas 13.99 mais 458.19 par exemple, ton programme est par terre. Tout simplement parce qu'il faudra extraire trois chiffres au lieu de deux.

Et puis, niveau légèreté, c'est pas comme si tu utilisais ta fonction 500 fois par seconde, non ? ;)
En plus, c'est beaucoup moins lisible et donc facile à débugger.
:)
La théorie, c'est quand on sait tout et que rien ne fonctionne.
La pratique, c'est quand ça marche mais qu'on ne sait pas pourquoi.
Quand la théorie rejoint la pratique, rien ne fonctionne et on ne sait pas pourquoi.
Gamuti#9 Posté le 17/11/2010 à 09:39:00
En fait, c'est un peu plus complexe qu'on ne l'imagine.
Comme j'extrais les chiffres à partir d'une chaine de caractère dont le texte est hébergé sur un serveur en Espagne, ET que ledit site internet modifie régulièrement son code source, je ne peux qu'utiliser cette méthode.
Quoiqu'en fait, la méthode change régulièrement en fonction du code source de la page internet.
Pendant quelques mois j'avais cette forme de chaine :
<div><un certain nombre de balise><ul 187,99></ul></un certain nombre de balise></div>

Aujourd'hui, j'ai :
<EM><STRONG>18,99 EUR</STRONG></EM>

Demain, je ne sais pas comment le code sera fait.

Dans le code de mon programme, je détecte ce genre de chaine par comparaison.
Pour ce faire, je place le contenu d'une partie de la chaine de caractère en question dans un Label, puis j'extrapole :
-> suppression des espaces en début et fin de ligne
-> récupération des deux premiers chiffres en question
-> récupération des deux derniers chiffres
-> déclarer que ces chiffres ne correspondent plus à la chaine de caractère mais à une valeur numérique
-> calcul en utilisant cette méthode : 20 + x + (y/100)
-> allez, soyons fous, je retransforme ma somme NUMÉRIQUE en chaine avec le symbole € à la fin (just for fun)

et cela est réalisé en une seule et unique ligne de code !!
1
IF Mid(Trim(r), 1, 12) = Prix.Text THEN TabTxt[n].Text = Str(20 + Val(Mid(Trim(r), 13, 2))) & " €"

Prix.Text est un label contenant la chaine à comparer soit :
<em><strong>

Bon, j'avoue !! cette ligne de code change en fonction du site internet espagnol, de même que la chaine à comparer qui se trouve dans Prix.Text

Et puis, le scr&#105;pt ne sera pas diffusé. Il s'agit d'une simple application dans un but personnel (petite boutique en ligne)
Ceci-dit, le code source peut être disponible à qui le demande.

Voici une image de l'application :
spheris#10 Posté le 17/11/2010 à 18:15:00
Par contre, Gamuti, explique moi une chose :
Comment ton soft va chercher les données sur le net pour en extraire la chaine de caractères ?
Merci pour ta réponse.
;) ;)
Prokopy#11 Posté le 17/11/2010 à 20:36:00
Kinder PinguiAvec la méthode HTTPClient.Get() dans le composant gb.net.curl, non ? ;)

http://gambasdoc.org/help/comp/gb.net.curl/httpclient?fr&v3
La théorie, c'est quand on sait tout et que rien ne fonctionne.
La pratique, c'est quand ça marche mais qu'on ne sait pas pourquoi.
Quand la théorie rejoint la pratique, rien ne fonctionne et on ne sait pas pourquoi.
Gamuti#12 Posté le 18/11/2010 à 09:06:00

Avec la méthode HTTPClient.Get() dans le composant gb.net.curl, non ? Wink

http://gambasdoc.org/help/comp/gb.net.curl/httpclient?fr&v3

Je ne maitrise pas assez gambas pour allez dans ta direction.

Par contre, Gamuti, explique moi une chose :
Comment ton soft va chercher les données sur le net pour en extraire la chaine de caractères ?
Merci pour ta réponse.
;) ;)

Simplement avec la méthode wget disponible depuis un shell
1
SHELL "wget " & adrURL1 & adrURL2 & " -P /tmp/" WAIT

Le WAIT permet d'attendre la fin de l'exécution du SHELL autrement, ça part en erreur de relecture du fichier (c'est pour la suite)
Ensuite, il faut récupérer le fichier dans le /tmp/ de l'arborescence linux.
1
hFile = OPEN "/tmp/" & adrURL2 FOR INPUT WHILE NOT Eof(hFile) LINE INPUT #hFile, chaine r = Trim(chaine) IF r = Disponible.Text THEN TabImg[n].Picture = ImgDispo.Picture IF r = Indisponible.Text OR r = Indisponible2.Text THEN TabImg[n].Picture = ImgIndispo.Picture TabTxt[n].Tag = "0" END IF IF Mid(r, 1, 12) = Prix.Text THEN TabTxt[n].Text = Str(20 + Val(Mid(r, 13, 2))) & " €" TabImg[n].T g = Str(Val(Mid( , 1 , 2 ) + Val(Mid( , 1 , 2 ) / 10 ) & " ₠E IT C OSE #h le S ELL "rm -r /t p " & adr RL2 'On supprime le fichier temporaire

- adrURL1 correspond à l'adresse du serveur distant (du style : http://www.machinchose.com)
- adrURL2 correspond à l'adresse de la page HTML (pageweb.html)
Donc, en combinant adrURL1 & adrURL2, on aura une adresse complète : http://www.machinchose.com/pageweb.html
Pourquoi 2 arguments ?
-> simplement que le deuxième argument (adrURL2) permet à wget d'enregistrer la page web sur le /tmp/
Aussi, les objet Disponible, Indisponible et Indisponible2 sont des Label dont la chaine permet de comparer une ligne sur le code source de adrURL2.
spheris#13 Posté le 19/11/2010 à 19:43:00
Bonne astuce Gamuti !

Je ne maitrise pas assez gambas pour allez dans ta direction.


Mais le Mac gyver astucieux qui réside en toi te permet de contourner le problème.
;) ;)
1