Page 1 sur 2

isString(), isNumeric()

Publié : mar. 29/oct./2013 10:41
par Mesa
Comment savoir si une donnée (entrée par l'utilisateur par exemple, ou une variable) est une string ou un nombre ?

isString(?)
isNumeric(?) avec virgule et signe "moins"
isInteger(?)
isFloat(?)

La fonction doit accepter n'importe quoi en entrée et ne pas renvoyer une erreur de compilateur (utilisation de pointeurs ?)
Par ex: le compilo doit accepter isString(0.5) et renvoyer False, et accepter isString("12bbb") et renvoyer True.

C'est possible ?

Ça m'aurait été utile dans la création de certaines macros, entre autre.

Mesa.

Re: isString(), isNumeric()

Publié : mar. 29/oct./2013 11:02
par Backup
je supose que tu sais qu'il existe des fonctions qui font ça sur le forum :)

recherche avec "IsAlpha" ,"IsNumeric" par exemple :)

Re: isString(), isNumeric()

Publié : mar. 29/oct./2013 11:06
par Ar-S
Salut Mesa,
Je pense que la difficulté viens de la reconnaissance de la donnée, je partirai donc sur de l'expression régulière afin de catégoriser ces données avant de les traiter.

Re: isString(), isNumeric()

Publié : mar. 29/oct./2013 12:44
par falsam
Je pense que Mesa souhaiterait une solution native. Mais il me semble que Fred avait déjà répondu sur ce sujet.

En attendant une solution native, j'aime bien ce code de SFSxOI (Forum anglais)

Code : Tout sélectionner

Procedure IsNumeric(in_str.s) ; whole number - or - floats - with - single decimal point or comma
  rex_IsNumeric = CreateRegularExpression(#PB_Any,"^\d*(\.|,)?\d*+$") ; Any digit 0-9, and float - with or without comma or decimal point
  Is_Numeric.b = MatchRegularExpression(rex_IsNumeric, in_str)
  ; FreeRegularExpression(rex_IsNumeric) ; if needed or desired - regular expression freed when program ends anyway
  ProcedureReturn Is_Numeric
EndProcedure

Debug IsNumeric("1234A56789102345678901.12345678910234567890") ; ooops one error
Debug IsNumeric("1234A56789102345678901.12345678.910234567890") ; ooops another error

Debug IsNumeric("123456789102345678901.12345678910234567890") ; one decimal point
Debug IsNumeric("123456789102345678901,12345678910234567890") ; one comma
Debug IsNumeric("123456789102345678901") ; no decimal point or comma
Debug IsNumeric("0,123456789102345678901") ; preceding 0 then comma
Debug IsNumeric("0.123456789102345678901") ;  preceding 0 then decimal point

Re: isString(), isNumeric()

Publié : mar. 29/oct./2013 15:29
par Micoute
Et TypeOf() ?

Re: isString(), isNumeric()

Publié : mar. 29/oct./2013 18:20
par Backup
falsam a écrit :J

En attendant une solution native, j'aime bien ce code de SFSxOI (Forum anglais)
dommage

Code : Tout sélectionner

Debug IsNumeric("$ff") 
ne marche pas :twisted:

Re: isString(), isNumeric()

Publié : mar. 29/oct./2013 20:07
par falsam
Dobro a écrit :ne marche pas
Mais si ça fonctionne ..... essayes encore une fois :)

Code : Tout sélectionner

Debug IsNumeric("$ff")
Debug a écrit :0
donc ça fonctionne non ?

Re: isString(), isNumeric()

Publié : mar. 29/oct./2013 20:22
par Backup
ben non

0 c'est quans c'est pas numerique !

donc ça ne marche pas car $FF c'est du numerique ... mais en hexa ;)

Re: isString(), isNumeric()

Publié : mar. 29/oct./2013 21:41
par falsam
Dobro a écrit :ben non

0 c'est quans c'est pas numerique !

donc ça ne marche pas car $FF c'est du numerique ... mais en hexa ;)
MouaHHHHHHhhh j'avais même pas vu. Mais là je m'en sers que pour tester des valeur compréhensible par le commun des mortels. Des vrais chiffres négatifs, positifs, décimales ou pas :)

Re: isString(), isNumeric()

Publié : mar. 29/oct./2013 23:11
par PAPIPP
Bonjour à tous
Déjà vu
http://www.purebasic.fr/french/viewtopi ... s+#p157517
Un peu plus court et surtout valable pour presque toute valeur numérique sous forme de chaine.

Sauf pour une valeur numérique >0 en tête de chaine, mais peut être amélioré.

Code : Tout sélectionner

Procedure Isnumeric(STRNG.s)
  STRNG=ReplaceString(STRNG, " ", "" )+"1" ; peut être supprimé si l'on considére qu'une chaine avec 1 ou plusieurs Blancs n'est pas numérique
  ;   STRNG+"1" ; peut remplacer l'instruction précedente
  If ValD(STRNG)<>0 Or Val(STRNG)<>0
    ProcedureReturn #True
  Else 
    ProcedureReturn #False
  EndIf   
EndProcedure 


Dim tab.s{15}(20)
tab(I)="458"
i+1:tab(I)="-458"
i+1:tab(I)="+ 45. 8  "
i+1:tab(I)="$BCE"
i+1:tab(I)="45.8"
i+1:tab(I)="%101010"
i+1:tab(I)="5.667e-2"
i+1:tab(I)="-5.667e-2"
i+1:tab(I)="azafdf"
i+1:tab(I)="a654"
i+1:tab(I)="0.00"
i+1:tab(I)="%0 0 0 0 0 0"
i+1:tab(I)="AB0 045ABCD 0 0 0 0"
i+1:tab(I)="0045ABCD 0 0 0 0"  ;  C'est un cas ou l'algo trouve une valeur numérique 
i+1:tab(I)="00 0ABCD 0 0 0 0"  


Jmax=i

For i=0 To jmax
  VALN=isnumeric(tab(i))
  Debug  "num="+Str(valn)+" i="+Str(i)+" tab(i)="+tab(i)
Next

A+

Re: isString(), isNumeric()

Publié : mer. 30/oct./2013 7:21
par graph100
Il me semble que Mesa voudrait un type variant.

En revanche son post indique des contraires : Si la fonction doit accepter n'importe quoi, avec on est au niveau programmeur,
si c'est une entrée dans un champ, alors on est au niveau utilisateur, et c'est de l'interprétation de chaine pur et dur (pas de isString(0.5) par exemple)

sinon, comme l'a cité Micoute, TypeOf() donne le type des entrées dans le code. MAIS, c'est d'un intérêt limité car le type variant n'existe pas en PB.
On ne peux donc pas écrire des procédures acceptant n'importe quel type de paramètre. La détection du type se fait de manière lexicale lors de la compilation, tu utiliseras cette fonction principalement pour écrire des macro, du genre :

Code : Tout sélectionner

Macro adapt(variant)
	CompilerSelect TypeOf(variant)
		CompilerCase #PB_Double
			result.d = variant
			
		CompilerCase #PB_String
			result.d = ValD(variant)
			
	CompilerEndSelect
EndMacro

chaine.s = "5.659"
adapt(chaine)
Debug result

var_double.d = 59.5613
adapt(var_double)
Debug result
qui n'est pas très utile :mrgreen:

La même sans les directives Compiler

Code : Tout sélectionner

Macro adapt(variant)
	Select TypeOf(variant)
		Case #PB_Double
			result.d = PeekD(@variant)
			
		Case #PB_String
			result.d = ValD(PeekS(@variant))
			
	EndSelect
EndMacro

chaine.s = "5.659"
adapt(chaine)
Debug result

var_double.d = 59.5613
adapt(var_double)
Debug result

Re: isString(), isNumeric()

Publié : mer. 30/oct./2013 9:22
par Mesa
Je n'avais pas pensé à typeof :?
Ça permet d'utiliser un semblant de "variant" en effet.

@graph100
Ton code est excellent, pile ce que je recherchais.
Merci. :D

Mesa.

Re: isString(), isNumeric()

Publié : mer. 30/oct./2013 11:33
par PAPIPP
Je vais avouer mon incompétence mon ignorance ou mes lacunes je ne sais encore.
Mais sans vouloir lancer une polémique d’ordre logique ou technique.
Pouvez vous me dire quand le programmeur, il s’agit bien de lui et de lui seul, ne connait pas le type de la variable qu’il est en train de manipuler ?. Surtout s’il maitrise tout le PRG

En effet même lorsque l’on utilise un programme réalisé par d’autre DLL EXE lib etc
Il est indispensable de connaître le type des paramètres sinon on va au crash avec une probabilité assez grande.
Il est difficile de connaître le type à coup sûr s’il n’est pas donné.
Une analyse du code machine peut nous le faire pressentir.
Une analyse d’un résultat peut aussi nous le faire pressentir.
Si vous ne le connaissez pas je ne vois pas d’autre méthode.

Donc la seule question intéressante est :
Dans une chaine de caractère en provenance de l’extérieure d’un autre PRG ou d’un utilisateur les éléments sont-ils de type numérique ou pas ?

Ps : certains langages ne permettent pas d’envoyer n’importe quoi dans un type donné
Le type n’est non seulement défini pour un type de donnée mais aussi pour limiter les valeurs enregistrées. Ce n’est pas le cas en PB car cela alourdirait le compilateur. En Pb on peut faire un peu ce que l’on veut c’est au programmeur à faire attention

Exemple :

Code : Tout sélectionner

Structure octet 
  StructureUnion
    Vb.b
    Vc.c
    Va.a
    car.s{1}
  EndStructureUnion
EndStructure 
Define car.octet
For i=0 To 1024
  car\vb+1
  r.l=i % Random(10,1)  
  If r>3 And r<5
    Debug "car\Va="+Str(car\Va)+"  car\Vb="+Str(car\Vb)+"  car\Vc="+Str(car\Vc)+"  car\car="+car\car
  EndIf
Next 
Debug "****** avec 'A' comme incrément ************"
For i=0 To 1024
  car\Vc+'A'
  r.l=i % Random(10,1)  
  If r>3 And r<5
    Debug "car\Va="+Str(car\Va)+"  car\Vb="+Str(car\Vb)+"  car\Vc="+Str(car\Vc)+"  car\car="+car\car
  EndIf
 Next

Re: isString(), isNumeric()

Publié : mer. 30/oct./2013 12:19
par falsam
PAPIPP a écrit :Pouvez vous me dire quand le programmeur, il s’agit bien de lui et de lui seul, ne connait pas le type de la variable qu’il est en train de manipuler ?. Surtout s’il maitrise tout le PRG
Je suis d'accord avec toi. Moi je parle bien du contrôle de l'utilisateur final.

Contrairement à d'autres langages ou ateliers de génie logiciel (AGL) permettant de développer des applications de gestion, Pure Basic ne possède pas de champ numérique monétaire avec gestion de la virgule ou pas. Je suis donc obligé de contrôler si une valeur saisi par un utilisateur final est bien numérique.

Exemple 10,15 et 10.15 sont bien numérique
Par contre ne pas accepter A0.10 et 10,,15 ou encore 10.15.5

Avoir un champ string formaté serait vraiment bien et faciliteré le codage d'une application de gestion

■ StringGadget(#pb_Any, 10, 20, 80, 20, "99 999,99")
Permet la saisie et l'affichage des valeur de 0,0 à 99 999,99

■ StringGadget(#pb_Any, 10, 20, 80, 20, "999-")
Permet la saisie et l'affichage des valeur de -999 à 999
Pour ajouter la partie décimale le masque serait 999,99-

■ StringGadget(#pb_Any, 10, 20, 80, 20, "(999)")
Permet la saisie des nombre de 0 à 999 et l'affichage avec les parenthèses.

■ StringGadget(#pb_Any, 10, 20, 80, 20, "999-[#Red]")
Permet la saisie des nombre de -999 à 999 et l'affichage en rouge si la valeur est négative.

■ StringGadget(#pb_Any, 10, 20, 80, 20, "999,99 $")
Permet la saisie des nombre de 0 € à 999 €. Le symbole monétaire ou libellé monétaire serait défini par la fonction InitDevise(Code). Exemple InitDevise("FRF") pour obtenir le symbole €.

Ce ne sont que quelques exemples que certains d'entres vous, utilisateurs d'un AGL connu, reconnaîtront :)

Avoir cette fonctionnalité en natif serait un plus pour développer des applications de gestion.

Re: isString(), isNumeric()

Publié : jeu. 31/oct./2013 1:43
par PAPIPP
Bonjour falsam

Je suis entièrement d’accord avec toi.

J’ajoute que pour une bonne gestion le type flottant double précision est insuffisant car on ne gère pas avec des règles d’arrondi parfaitement définies dans tout le processus soit d’une comptabilité soit d’une gestion rigoureuse.
Je ne sais si les (AGL) utilisent comme type le BCD paked ou paked decimal ou COMP-3 du cobol.

En effet en BCD paked ou COMP-3 (PACKED DECIMAL) les éléments de données sont utilisés en COBOL, parce qu'il conserve un nombre fixe de décimales. Tous les calculs aboutissent à un résultat ayant le nombre de décimales parfaitement définis. Ceci est particulièrement utile dans les opérations de type comptables. Les nombres à virgule flottante avec un nombre de chiffres après la virgule décimale variable (par exemple la virgule peut "flotter") qui n'est pas la façon dont les opérations financières sont généralement représentées.

Voici à titre d’exemple les résultats d’une division en flottant simple et double précision.
On voit des variations dans la précision ce qui n’est pas acceptable en comptabilité
Je sais que certains logiciels de compta sont en flottant double précision (pour des petites entreprises avec des nombres relativement peu important)

Code : Tout sélectionner

Macro _q_t_
"
EndMacro
Macro _n (__n)
_q_t_#__n#=_q_t_+Str(__n)+" "
EndMacro
Macro _d (__D,__nv=8)
_q_t_#__D#=_q_t_+StrD(__D,__nv)+" "
EndMacro
Macro _f (__F,__nv=8)
_q_t_#__F#=_q_t_+StrF(__f,__nv)+" "
EndMacro
Define vd.d,vf.f,Id.d,Jd.d,Jf.f
For i=1 To 256
  vd=i
  vf=i
  For j=2 To 16
    jf=j
    jd=j
    rvf.f=Vf/jf 
    rvd.d=Vd/jd
      precis.d=(rvf-rvd)*100/rvd
    Debug _d(Vd/J,18)+_F(Vf/j,18)+_d(Vd/Jd,18)+_F(Vf/jf,18)+_n(i)+_n(J)+_d(rvf,18)+_d(rvd,18)+_d(precis,18)
  Next
Next