Page 1 sur 7

Comment connaitre le nombre d'élément d'un tableau [Résolu]

Publié : lun. 19/mars/2007 14:22
par Kwai chang caine
Bonjour à tous

Bah, voila tout est dans le titre :D

Quelqu'un saurait il, si il y a une fonction qui permet de connaitre le nombre d'éléments qui sont dans un tableau.
Dans l'exemple suivant, il faudrait qu'il remonte 5 :

Code : Tout sélectionner


Dim a.s(100)

For i = 1 to 5
 a(i) = str(i)
next

Merci et bonne journée

Publié : lun. 19/mars/2007 14:39
par Anonyme2
Comme je ne comprend pas bien ta question, voici une réponse qui ne correspond peut être pas.
Procédure donnée par Rings sur le forum anglais

http://www.purebasic.fr/english/viewtopic.php?t=8267

Code : Tout sélectionner

Dim MYArray.b(4711)

Procedure Ubound(*Array)
 ProcedureReturn PeekL(*Array-8)
EndProcedure

Debug Str(UBound(@MyArray(0)))

Publié : lun. 19/mars/2007 17:15
par Kwai chang caine
Bonjour DENY

Merci de ta réponse 8) , mais apparement le code que tu m'a donné renvois le dimensionnement du tableau.

Ce que j'aurais aimé avoir c'est le dernier element inscrit dans le tableau.

Par exemple si un tableau est dimensionné a 100.

Code : Tout sélectionner

Dim Tableau(100)
Et que je lui dit juste que :

Code : Tout sélectionner

Tableau(1) = "premier"
Tableau(2) = "second"
Je voudrais savoir si il y a un autre moyen simple d'obtenir le nombre du dernier enregistrement c'est a dire "2" dans ce cas.
Cela evite de rechercher encore des elements dans un tableau alors que on en a jamais écris autant.
Comme ça on gagne du temps dans les boucles qui vident les tableaux dans une listview par exemple.

Code : Tout sélectionner

Dim Tableau.s(100)
Tableau(1) = "premier"
Tableau(2) = "second"

For i = 1 To 100
  
 If Trim(Tableau(i)) = ""
  i - 1
  Break
 EndIf  

Next 

Debug Str(i) + " est le dernier element du tableau"

Publié : lun. 19/mars/2007 18:01
par Anonyme2
Je pense que cela n'est pas possible simplement.

On est pas obligé de remplir un tableau dans l'ordre, on peut stocker des éléments de manière aléatoire.

Si le tableau n'a que des valeurs numériques, les emplacements mémoires existent et sont mis à 0 à l'initialisation. Donc quel valeur définie un élément vide ?

Si le tableau n'a que des chaines, on peut définir une chaine vide comme élément de comparaison, mais il faudra tester chaque chaine et si le tableau est presque plein, voire plein, la scrutation en suivant ne fera qu'augmenter le temps puisqu'il faudra l'ajouter au temps de remplissage de la listview.

On peut scruter l'élément qui est au milieu et considérer que s'il est vide, les suivants sont vides, donc on scrute l'élément qui est à la moitié de la moitié etc jusqu'à trouver le dernier élément rempli, mais cela suppose que le remplissage n'est pas aléatoire.

Une autre solution est de tenir un compteur à jour qui ajoute ou supprime un élément en fonction de l'évolution du tableau.

Un truc de Flype que j'utilise pas mal c'est de cacher le gadget avant remplissage puis de l'afficher ensuite, le gain de temps est énorme!



Il y a encore une solution c'est de faire des redim avec chaque manipulation mais là c'est très lourd .

Publié : lun. 19/mars/2007 18:28
par Kwai chang caine
Bon bah tanpis :(
On a tellement l'habitude de voir que pure sait presque tout faire.....
Qu'on est épaté quand il cale 8O

Je ne suis pas sur, mais je crois bien qu'en GFA basic ça existait.
Il devait mémoriser en interne le plus grand indice utilisé, meme si il y avait des vides au milieu.

Quoi qu'il en soit je te remercie de ton aide précieuse.
Je te souhaite une excelente soirée.

Publié : lun. 19/mars/2007 19:00
par Anonyme2
Je n'utilise pas les tableaux ou presque pas (je les utilise rarement pour trier des données).

Je préfère et de loin les listes chainées, souples, pratiques, on connait les éléments, la liste des commandes est très bonnes, donc à utiliser sans modération et remplace les tableaux dans pas mal de cas. Pour la vitesse, je n'en sait rien, au départ c'était en assembleur mais je pense qu'elles sont en C pour la portabilité multi-plateformes.

Publié : lun. 19/mars/2007 19:19
par Flype
salut kwai,
après avoir re re lu ton post, il est clair que les listes chainees sont plus adaptées dans ton cas que les tableaux.

Publié : mar. 20/mars/2007 11:18
par Kwai chang caine
C'est vrai, ces listes chainées...... :roll:
J'y pense jamais.

En fait, comme je viens du Qbasic, GfaBasic, je ne sais pas si ça existait, mais je ne les ai découvertes qu'avec pure.
Donc je ne les utilisent pas souvent.

D'ailleurs, je ne sais pas vraiment quel est la difference fondamentale entre les deux :?:
Hors mis une deja, celle de connaitre le dernier element apparement :lol:

ça ressemble un peu a de la base de donnée.
Avec access c'est un peu ce genre d'instruction que l'on retrouve.

J'y trouve un peu lourd, surement parce que je n'y suis pas habitué.
Il faut dire que tant que l'on a pas vraiment compris tous les interets, les avantages, les tenants et les aboutissants d'une fonction on a parfois du mal a comprendre l'interet à l'utiliser. :oops:

Publié : mar. 17/avr./2007 8:25
par Kwai chang caine
Le code de DENIS venant de RING marche super pour avoir le dimentionnement d'un tableau.

Code : Tout sélectionner

Dim MYArray.b(4711) 

Procedure Ubound(*Array) 
 ProcedureReturn PeekL(*Array-8) 
EndProcedure 

Debug Str(UBound(@MyArray(0)))
Mais voila BB programmeur est jamais content(Comme tous les BB d'ailleurs :D )
BB aurait préféré sans procédures.

Donc BB a fait fonctionné son neurone et il a écrit ça en simplifiant la procédure de ring.

Code : Tout sélectionner

Dim Tablo(99999999)
TailleTablo = PeekL(@Tablo() - 8) - 1
Debug TailleTablo
ça marche, mais je voudrais savoir, si rien ne vous choque, et si je peux utiliser ça dans tous les cas.
Apparement on ne peux pas aller plus loin que 99999999

Publié : mar. 17/avr./2007 10:25
par Backup
Kwai chang caine a écrit :

Code : Tout sélectionner

Dim Tablo(99999999)
TailleTablo = PeekL(@Tablo() - 8) - 1
Debug TailleTablo
ça marche, mais je voudrais savoir, si rien ne vous choque, et si je peux utiliser ça dans tous les cas.
Apparement on ne peux pas aller plus loin que 99999999
le fait d'utiliser Tablo() signifie que tu considere que c'est un Long (.l) par defaut !! toute variable sans Type (.s,.d,.q,.b) est consideré comme un Long
et en temps que tel ne peux contenir plus de -2147483648 à +2147483647

il faudrai éventuellement tout passer en .Q ou .D
y compris PeekL, mais apparement ça marche pas :?
peut etre bien un Bug d'ailleurs, car meme Peekq(@Tablo() - 64) - 1
refuse d'afficher quoi que ce soit :?

ceci devrai afficher quelque chose non ?

Code : Tout sélectionner

Dim Tablo.q(9999999999)
TailleTablo.q = PeekQ(@Tablo.q() - 64) - 1
Debug TailleTablo
et bien non ... plantage ! pourquoi ? 8O

Publié : mar. 17/avr./2007 10:53
par Kwai chang caine
Je suis super content, car comme tu peux le voir tes longues leçons au coin du feu m'ont quand meme inculqué quelques bribes de connaissances.

En effet, j'avais essayé de tout mettre en Q moi aussi (Ouuaaahhhh) Applause en arriere plan :D

Mais comme ça n' a pas marché, je me suis dit que je ne devais pas avoir fait quelque chose de bien.

Mais je m'apperçois, grace à toi, que mon résonnement n'etait pas si mal que ça.

Evidemment, je sais bien que tu ne t'attend pas à ce que je puisse répondre à une de tes question :lol:
Donc il faudra attendre un autre des "caids" du site pour avoir une reponse.

Quoi qu'il en soit je te remercie 8)

Publié : dim. 22/avr./2007 16:57
par Flype
à mon avis il n'y a pas de bugs là dedans.

il ne faut pas oublier une chose : allouer une telle taille de tableau je veux bien mais je n'ai pas assez de RAM pour çà.
Donc on obtient un Invalid Memory Access parceque l'allocation mémoire du tableau a échouée.

pour vérifier si le tableau est bien alloué en mémoire on peut faire un Debug @MonTableau().
Si on a 0 (NULL) alors l'allocation a échouée et du coup tout PeekL() & co sont proscrit. Normal en somme.


Par ailleurs, le mieux est d'écrire une macro et non une procedure.
une procedure c'est bcp trop lent pour si peu.
Une macro au contraire fait parfaitement l'affaire - c'est typiquement le cas où elles sont préférables aux procedures.

Code : Tout sélectionner

Macro ARRAY_TYPE(ArrayName)
  PeekL(@ArrayName - 4)
EndMacro

Macro ARRAY_SIZE(ArrayName)
  PeekL(@ArrayName - 8)
EndMacro

Code : Tout sélectionner

  Debug "Taille du tableau : " + Str( ARRAY_SIZE( MonTableau() ) )
  Debug "Type du tableau : " + Str( ARRAY_TYPE( MonTableau() ) )
Ensuite il ne faut pas oublier que la taille occupée en mémoire par un tableau dépends du type (byte, long, quad, structures, ...)

on peut s'y essayer avec ce bout de code mais il ne faut pas oublier que tout çà n'est pas 'supporté' par purebasic. C'est du bidouillage pas vraiment 'futur-proof'.

Code : Tout sélectionner

  Taille = ARRAY_SIZE( MonTableau() )
  
  Select ARRAY_TYPE(MonTableau())
    Case 01 : Taille * SizeOf(Byte) 
    Case 03 : Taille * SizeOf(Word) 
    Case 05 : Taille * SizeOf(Long) 
    Case 09 : Taille * SizeOf(Float) 
    Case 11 : Taille * SizeOf(Character) 
    Case 12 : Taille * SizeOf(Double) 
    Case 13 : Taille * SizeOf(Quad) 
  EndSelect
  
  Debug Taille

Publié : lun. 23/avr./2007 8:41
par Kwai chang caine
Bonjour flype

Merci pour ces informations concernant les tableaux.
J'en prend bonne note. 8)

Ce que tu viens d'ecrire m'ammenne une question:
Est-on obligé de passer par une macro ou bien le fait de passer par une macro est encore plus rapide que de mettre le code en direct.

Exemple :

Code : Tout sélectionner

Macro ARRAY_TYPE(ArrayName) 
  PeekL(@ArrayName - 4) 
EndMacro

Debug "Type du tableau : " + Str(ARRAY_TYPE( MonTableau())) 
est-il plus rapide que:

Code : Tout sélectionner

Debug "Type du tableau : " + Str(PeekL(@ArrayName - 4)) 
ou bien cela reviens à la meme chose.
Je te pose cette question car a force de faire des procedures pour quelques lignes, je trouve que cela complique le code.Si on y rajoute encore les macros.

Je n'ai pas bien compris l'interet de créer une procedure ou une macro pour UNE ligne, puisque cela prend la meme place que de mettre la réelle instruction dans le code.
Il est vrai que cela peut permettre de simplifier la syntaxe de l'instruction ou bien de la "franciser" mais hors mis ces cas, y a t'il vraiment d'autres interets?

Encore merci de ton aide

Publié : lun. 23/avr./2007 9:12
par Flype
c'est exactement la meme chose - je veux dire c'est aussi rapide que d'ecrire la ligne directement dans le code car une macro est remplacée avant la compilation. donc oui ca permet de simplifier la lisibilité du code (en francisant si tu veux) tout en ne perdant pas en rapidité d'execution contrairement à une procedure (qui elle doit gérer l'entrée/sortie des arguments).

maintenant, non, dans l'absolu, tu n'es ni obligé d'utiliser une procedure, ni une macro, tu fais comme tu veux. c'est juste un bon conseil.

Publié : lun. 23/avr./2007 9:57
par Kwai chang caine
Merci beaucoup de ta réponse rapide.

Donc j'ai bien "imprimé" :lol: c'est pareil.
Par contre les procedures sont plus longues, d'ailleurs je crois que notre ami DOBRO m'avait déja dit qu'une procédure était aussi plus longue qu'un "GOSUB, RETURN", car en fait ce que l'on appelle une procedure en pure n'est autre qu'une instruction.
Une vraie procedure est un "GOSUB, RETURN" puisque Go SUB veux dire Go subroutine, je crois, ce qui veux dire aller a la procedure en anglais. :D

Donc the winner is :

Médaille d'or = MACRO
Médaille d'argent = Gosub return (Procedure dans les autres languages)
Médaille de bronze = Procedure (Fonction dans les autres languages)

Je suis content car les bribes de savoir que vous tentez désespérément de m'inculquer se rejoignent dans ma caboche et commence à tisser une toile.
Vous avez encore du boulot les araignées :lol: :lol: :lol:

Merci encore pour tout