isString(), isNumeric()

Vous avez une idée pour améliorer ou modifier PureBasic ? N'hésitez pas à la proposer.
Mesa
Messages : 1097
Inscription : mer. 14/sept./2011 16:59

isString(), isNumeric()

Message 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.
Backup
Messages : 14526
Inscription : lun. 26/avr./2004 0:40

Re: isString(), isNumeric()

Message par Backup »

je supose que tu sais qu'il existe des fonctions qui font ça sur le forum :)

recherche avec "IsAlpha" ,"IsNumeric" par exemple :)
Dernière modification par Backup le mar. 29/oct./2013 11:08, modifié 1 fois.
Avatar de l’utilisateur
Ar-S
Messages : 9476
Inscription : dim. 09/oct./2005 16:51
Contact :

Re: isString(), isNumeric()

Message 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.
~~~~Règles du forum ~~~~
⋅.˳˳.⋅ॱ˙˙ॱ⋅.˳Ar-S ˳.⋅ॱ˙˙ॱ⋅.˳˳.⋅
W11x64 PB 6.x
Section HORS SUJET : ICI
LDV MULTIMEDIA : Dépannage informatique & mes Logiciels PB
UPLOAD D'IMAGES : Uploader des images de vos logiciels
Avatar de l’utilisateur
falsam
Messages : 7244
Inscription : dim. 22/août/2010 15:24
Localisation : IDF (Yvelines)
Contact :

Re: isString(), isNumeric()

Message 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
Configuration : Windows 11 Famille 64-bit - PB 6.03 x64 - AMD Ryzen 7 - 16 GO RAM
Vidéo NVIDIA GeForce GTX 1650 Ti - Résolution 1920x1080 - Mise à l'échelle 125%
Avatar de l’utilisateur
Micoute
Messages : 2522
Inscription : dim. 02/oct./2011 16:17
Localisation : 35520 La Mézière

Re: isString(), isNumeric()

Message par Micoute »

Et TypeOf() ?
Microsoft Windows 10 Famille 64 bits : Carte mère : ASRock 970 Extreme3 R2.0 : Carte Graphique NVIDIA GeForce RTX 3080 : Processeur AMD FX 6300 6 cœurs 12 threads 3,50 GHz PB 5.73 PB 6.00 LTS (x64)
Un homme doit être poli, mais il doit aussi être libre !
Backup
Messages : 14526
Inscription : lun. 26/avr./2004 0:40

Re: isString(), isNumeric()

Message 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:
Avatar de l’utilisateur
falsam
Messages : 7244
Inscription : dim. 22/août/2010 15:24
Localisation : IDF (Yvelines)
Contact :

Re: isString(), isNumeric()

Message 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 ?
Configuration : Windows 11 Famille 64-bit - PB 6.03 x64 - AMD Ryzen 7 - 16 GO RAM
Vidéo NVIDIA GeForce GTX 1650 Ti - Résolution 1920x1080 - Mise à l'échelle 125%
Backup
Messages : 14526
Inscription : lun. 26/avr./2004 0:40

Re: isString(), isNumeric()

Message 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 ;)
Avatar de l’utilisateur
falsam
Messages : 7244
Inscription : dim. 22/août/2010 15:24
Localisation : IDF (Yvelines)
Contact :

Re: isString(), isNumeric()

Message 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 :)
Configuration : Windows 11 Famille 64-bit - PB 6.03 x64 - AMD Ryzen 7 - 16 GO RAM
Vidéo NVIDIA GeForce GTX 1650 Ti - Résolution 1920x1080 - Mise à l'échelle 125%
PAPIPP
Messages : 534
Inscription : sam. 23/févr./2008 17:58

Re: isString(), isNumeric()

Message 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+
Il est fort peu probable que les mêmes causes ne produisent pas les mêmes effets.(Einstein)
Et en logique positive cela donne.
Il est très fortement probable que les mêmes causes produisent les mêmes effets.
Avatar de l’utilisateur
graph100
Messages : 1318
Inscription : sam. 21/mai/2005 17:50

Re: isString(), isNumeric()

Message 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
_________________________________________________
Mon site : CeriseCode (Attention Chantier perpétuel ;))
Mesa
Messages : 1097
Inscription : mer. 14/sept./2011 16:59

Re: isString(), isNumeric()

Message 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.
PAPIPP
Messages : 534
Inscription : sam. 23/févr./2008 17:58

Re: isString(), isNumeric()

Message 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
Il est fort peu probable que les mêmes causes ne produisent pas les mêmes effets.(Einstein)
Et en logique positive cela donne.
Il est très fortement probable que les mêmes causes produisent les mêmes effets.
Avatar de l’utilisateur
falsam
Messages : 7244
Inscription : dim. 22/août/2010 15:24
Localisation : IDF (Yvelines)
Contact :

Re: isString(), isNumeric()

Message 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.
Configuration : Windows 11 Famille 64-bit - PB 6.03 x64 - AMD Ryzen 7 - 16 GO RAM
Vidéo NVIDIA GeForce GTX 1650 Ti - Résolution 1920x1080 - Mise à l'échelle 125%
PAPIPP
Messages : 534
Inscription : sam. 23/févr./2008 17:58

Re: isString(), isNumeric()

Message 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  
Il est fort peu probable que les mêmes causes ne produisent pas les mêmes effets.(Einstein)
Et en logique positive cela donne.
Il est très fortement probable que les mêmes causes produisent les mêmes effets.
Répondre