cConstantNum() - Constante numérique d'après une chaine de caractères représentant un nombre
# 0000000160
ajouté le 11/03/2005 09:17:25 et modifié le 30/03/2005
consulté 11011 fois
Niveau
initié
Avec FoxPro on ne sait pas toujours à quel séparateur décimal se vouer ... le séparateur courant (set('POINT')) ou le point '.' (period) ?
Val() attend le séparateur décimal courant (virgule en général pour les francophones)
Les calculs, et alter column de caractère à numérique, attendent une constante nombre, avec le pointpour séparateur décimal (period)
Pour nous qui, en général, utilisons la virgule comme séparateur décimal, la conversion de caractère à numérique est un petit casse-tête.
La fonction cConstantNum() affranchit de ces subtilités encombrantes.
Elle est livrée avec lNumber(). lNumber() vérifie qu'une chaine de caractère est valide pour représenter un nombre.
Code source :
FUNCTION cConstantNum && Constante numérique d'après une chaine de caractères représentant un nombre LPARAMETERS ;
tcNum,; && Chaine de caractères supposée représenter un nombre
tlPeriod && [.F.] séparateur décimal point (.F.: courant) [Val() veut courant, calcul et ALTER COLUMN veulent point] LOCAL lcResult
m.lcResult = Space(0)
* Si le paramètre est de type caractère LOCAL llResult
m.llResult = Vartype(m.tcNum) == 'C' ASSERT m.llResult MESSAGEProgram() + Space(1) + "Paramètre de type caractère attendu" IF m.llResult
* Si le paramètre peut représenter un nombre
m.llResult = lNumber(m.tcNum) IF m.llResult
* Supprimer les espaces et séparateurs de milliers éventuels LOCAL lcNum, lcSep, lcPoint
m.lcNum = Alltrim(m.tcNum)
m.lcSep = Set('Separator')
m.lcPoint = Set('Point')
m.lcNum = Iif(m.lcSep == m.lcPoint, m.lcNum, Chrtran(m.lcNum, m.lcSep, Space(0)))
m.lcNum = Chrtran(m.lcNum, Space(1), Space(0))
* Lire si séparateur décimal POINT demandé LOCAL llPeriod
m.llPeriod = Iif(Vartype(m.tlPeriod) == 'L', m.tlPeriod, .F.)
* Si la chaine comporte au plus un séparateur décimal LOCAL llPoint, lnPoints, lnPeriods
m.llPoint = m.lcPoint == '.'
m.lnPoints = Occurs(m.lcPoint, m.lcNum)
m.lnPeriods = Iif(m.llPoint, 0, Occurs('.', m.lcNum))
m.llResult = m.lnPoints + m.lnPeriods <= 1 IF m.llResult
* Si le séparateur courant n'est pas le point IFNOT m.llPoint
* Ajuster le séparateur si nécessaire DOCASE CASE m.llPeriod AND m.lnPoints = 1
m.lcNum = Chrtran(m.lcNum, m.lcPoint, '.') CASENOT m.llPeriod AND m.lnPeriods = 1
m.lcNum = Chrtran(m.lcNum, '.', m.lcPoint) ENDCASE ENDIF
m.lcResult = m.lcNum ENDIF ENDIF ENDIF
RETURN m.lcResult
* ----------- FUNCTION lNumber && Chaine de caractères représente un nombre LPARAMETERS ;
tcChain && Chaine à vérifier LOCAL llResult
* Si la chaine est correcte IFVartype(m.tcChain) == 'C' ; ANDNOTEmpty(m.tcChain)
* Définir les caractères non numériques possibles LOCAL lcSeps
m.lcSeps = Set("Point") + Set("Separator") + [ .+-]
* Vérifier chaque caractère de la chaine LOCAL lcChain, lnChar, lcChar
m.lcChain = Alltrim(m.tcChain) FOR m.lnChar = 1 TOLen(m.lcChain)
m.lcChar = Substr(m.lcChain, m.lnChar, 1)
m.llResult = ; IsDigit(m.lcChar) ; OR m.lcChar $ m.lcSeps IFNOT m.llResult EXIT ENDIF ENDFOR ENDIF
RETURN m.llResult
Commentaires
le 12/03/2005, eddymaue a écrit : func cConstantNum ( tcNum) && Chaine de caractères supposée représenter un nombre RETURN CHRTRAN(TRANSFORM(tcNum),IIF(SET("point")=".",",","."),SET("point"))
le 14/03/2005, FoxInCloud (Th. Nivelet) a écrit : cConstantNum() dépasse précisément les limites de cette formule. Th N
le 15/03/2005, eddymaue a écrit : Je ne faisais que répondre à la question initiale et à son objectif. Et je te cite
Avec FoxPro on ne sait pas toujours à quel séparateur décimal se vouer ... le séparateur courant (set('POINT')) ou le point '.' (period) ?
Pour ce qui est du reste. Si les données sont extraites d'une page html je comprend. Si non c'est que les entrées ne sont pas formatées.
Comme par exemple #####.## et ou 9999.99 imposés dans un contrôle d'entré. Textbox, Editbox et autres.
Autrement dit. On force l'utilisateur à utiliser un format prédéterminé.
À ce moment là, ça devient inutile d'essayer de trouver des caractères non numériques.
Reste tourjours le "-","+" et le "%" dans un champ caractère et ou toute ambiguïté est éliminée par EMPTY(cConstantNum,CHRTRAN,"0123456789%-+",""))=.t. que je validerais en entré. En ce qui me concerne, ta fonction est défensive et si le problème se pose alors là c'est la structure même du programme qui est à revoir.
Au plaisir d'en discuter et d'en approfondir le sujet.
Eddy a+
le 15/03/2005, FoxInCloud (Th. Nivelet) a écrit : Merci pour ce cours magistral. Tu sembles connaître les manies de tous les utilisateurs, sauf les miens. Pour ce qui est de la structure du programme, la mienne me convient parfaitement. Merci en tous cas de ta contribution positive et flatteuse. Th N
func cConstantNum ( tcNum) && Chaine de caractères supposée représenter un nombre
RETURN CHRTRAN(TRANSFORM(tcNum),IIF(SET("point")=".",",","."),SET("point"))