Auteur Sujet: Tableaux et objet : création en fonction d'un paramètre  (Lu 17900 fois)

Guillaume

  • Global Moderator
  • Full Member
  • *****
  • Messages: 204
    • Voir le profil
    • Locoduino
Tableaux et objet : création en fonction d'un paramètre
« le: mai 27, 2015, 10:55:54 am »
Bonjour,
je coince sur un problème de données avec un tableau :
class essai
{
  public:
    essai(byte j=1, byte valeur=0);
    void print();
  private:
    byte n;
    byte essai[n];
};

essai::essai(byte j, byte valeur)
{
  n=j;
  for(byte i=0;i<n;i++){essai[i]=valeur;}
}

void essai::print()
{
  for(byte i=0;i<n;i++)
   {
     Serial.println(n);
     Serial.println(essai[i], DEC);
   }
}

essai essai(2);

void setup() {
   // put your setup code here, to run once:
   Serial.begin(9600);
}

void loop() {
   essai.print();
   delay(5000);
}

Mon but est de créer un tableau d'une certaine longueur dans une class en fonction d'une variable lors de la création de l'objet pour en faire tout un truc pour ma lib animlum. Je créerai avec plusieurs tableaux d'autres objets et autres variables.
J'ai donc fait ce code pour tester mais je n'y arrive pas. Un pb de portée de variable, si on le crée dans public, on n'a pas la longueur initiale et dans le constructeur il est accessible seulement dans le constructeur.

Je n'ai pas trouvé de mot clé pour faire d'une variable locale une variable globale.

Avez-vous des idées ?
G.

Pierre59

  • Sr. Member
  • ****
  • Messages: 324
    • Voir le profil
Re : Tableaux et objet : création en fonction d'un paramètre
« Réponse #1 le: mai 27, 2015, 11:55:42 am »
Bonjour

Je pense que le problème vient de l'erreur :

sketch_may27a:8: error: array bound is not an integer constant

la taille d'un tableau doit être une constante et pas une variable.

En C sur un ordinateur on ferait un "malloc()", mais sur Arduino c'est beaucoup plus délicat.

Pierre

savignyexpress

  • Invité
Re : Tableaux et objet : création en fonction d'un paramètre
« Réponse #2 le: mai 27, 2015, 12:30:41 pm »
Bonjour à tous,

Je ne pense pas que l'allocation dynamique de mémoire soit une bonne chose sur un système embarqué tel que le microcontrôleur qui équipe l'Arduino. La RAM du microcontrôleur est typiquement 2 KB pour un Atmega328 et c'est vite fait de la saturer.

Il ne faut en tout cas pas l'utiliser comme on le ferait sur un plus gros système, c'est à dire en allouant / désallouant des blocs de mémoire au fur et à mesure de l'exécution, le risque étant de fragmenter la mémoire. À la rigueur, allouer un bloc unique dans la fonction setup, si la taille nécessaire n'est pas connue à la compilation et dépend de paramètres de configuration (définis en EEPROM, via des jumpers ou par un menu de configuration par ex).

Dans sa librairie ScheduleTable, Jean-Luc effectue une allocation à la création de l'objet, cela peut être une source d'inspiration.

Pour une application en lien avec un réseau ferroviaire, j'imagine que la taille des tableaux doit être connue à la compilation ce d'autant plus qu'elle doit être liée à la configuration du réseau qui elle ne change pas à chaque exécution du programme de l'Arduino !

Meilleures salutations.

Marc-Henri

Pierre59

  • Sr. Member
  • ****
  • Messages: 324
    • Voir le profil
Re : Tableaux et objet : création en fonction d'un paramètre
« Réponse #3 le: mai 27, 2015, 12:55:33 pm »
Bonjour

Personnellement je fais des allocations/désallocations dynamiques dans le "loop()", pour des "buffers" d'images, mais je prends beaucoup précautions sur l'ordre des allocations et des désallocations.

Pierre

Guillaume

  • Global Moderator
  • Full Member
  • *****
  • Messages: 204
    • Voir le profil
    • Locoduino
Re : Tableaux et objet : création en fonction d'un paramètre
« Réponse #4 le: mai 27, 2015, 01:31:38 pm »
La class appelle ensuite à la construction d'une lib qui, elle, doit s'organiser pour être malléable. En l'occurence, pour l'exemple, il s'agit de modifier ma lib AnimLum avec certaines animations enseigne, chenillard qui dépendent actuellement de 6 DEL pour en faire une polyvalente ou l'utilisateur décide du nbre de DEL, par exemple 10.
Il est facile de faire en ne prenant pas en compte le nombre réel mais le nombre possible maximum, par contre on prend de la mémoire pour rien. D'où l'idée de créer le tableau à posteriori. La taille n'est connu que de l'utilisateur final, pas de possibilité de le mettre avant.
Mais apparemment impossible ou pas à ma portée encore puisque je ne comprends pas tout ce que vous dites. Je n'ai pas encore une connaissance parfaite.
Cela attendra donc.
G.

Jean-Luc

  • Global Moderator
  • Hero Member
  • *****
  • Messages: 1691
    • Voir le profil
Re : Tableaux et objet : création en fonction d'un paramètre
« Réponse #5 le: mai 27, 2015, 01:51:52 pm »
Tu ne peux pas déclarer statiquement un tableau dont la taille est inconnue. Il faut l'allouer dynamiquement. En C++ on utilise new

Au lieu d'avoir :

byte essai[n];

Déclare plutôt

byte *tEssai;

tEssai étant alors un pointeur vers un byte. note que cette variable membre ne peut pas avoir le même nom qu'une méthode (le constructeur)

Dans ton constructeur, tu l'alloues avant de l'initialiser

essai::essai(byte j, byte valeur)
{
  n = j;
  tEssai = new byte[j];
  for(byte i=0; i<n; i++) {
    tEssai[i]=valeur;
  }
}

Le sketch complet :

class essai
{
  public:
    essai(byte j=1, byte valeur=0);
    void print();
  private:
    byte n;
    byte *tEssai;
};

essai::essai(byte j, byte valeur)
{
  n = j;
  tEssai = new byte[j];
  for(byte i=0; i<n; i++) {
    tEssai[i]=valeur;
  }
}

void essai::print()
{
  for(byte i=0;i<n;i++)
   {
     Serial.println(n);
     Serial.println(tEssai[i], DEC);
   }
}

essai essai(2);

void setup() {
   // put your setup code here, to run once:
   Serial.begin(9600);
}

void loop() {
   essai.print();
   delay(5000);
}

Normalement il devrait y avoir une libération de la mémoire via delete ( delete tEssai[]; ) dans le destructeur.
Cordialement

Guillaume

  • Global Moderator
  • Full Member
  • *****
  • Messages: 204
    • Voir le profil
    • Locoduino
Re : Tableaux et objet : création en fonction d'un paramètre
« Réponse #6 le: mai 27, 2015, 02:26:12 pm »
C'est de la réponse ça. Merci bcp
Si je continue sur ma lancée pour créer un tableau d'objets par exemple Led dans ma biblio. Je peux mettre un pointeur dans private avec
Led *tessai;puis pour créer dans le constructeur
tessai = new Led(variable);
J'ai essayé de compiler pas d'erreur palpable, il faudra que je testes plus loin mais ce soir peut être
G.

Jean-Luc

  • Global Moderator
  • Hero Member
  • *****
  • Messages: 1691
    • Voir le profil
Re : Tableaux et objet : création en fonction d'un paramètre
« Réponse #7 le: mai 27, 2015, 02:28:32 pm »
Oui c'est ça

Par contre si tu veux créer dynamiquement un tableau d'objets, tu ne peux pas passer des arguments au constructeur. Il faut donc :
1 - une constructeur sans argument
2 - une méthode pour initialiser l'objet après sa création
Cordialement

Guillaume

  • Global Moderator
  • Full Member
  • *****
  • Messages: 204
    • Voir le profil
    • Locoduino
Re : Tableaux et objet : création en fonction d'un paramètre
« Réponse #8 le: mai 27, 2015, 02:46:54 pm »
Le new ne peut être dans le constructeur donc si le constructeur ne peut pas avoir d'arguments et doit être vide ?

Merci de ton aide
G.

Jean-Luc

  • Global Moderator
  • Hero Member
  • *****
  • Messages: 1691
    • Voir le profil
Re : Tableaux et objet : création en fonction d'un paramètre
« Réponse #9 le: mai 27, 2015, 03:00:03 pm »
Uniquement si tu alloues un _tableau_ d'objets.
Cordialement

Guillaume

  • Global Moderator
  • Full Member
  • *****
  • Messages: 204
    • Voir le profil
    • Locoduino
Re : Tableaux et objet : création en fonction d'un paramètre
« Réponse #10 le: mai 27, 2015, 09:28:06 pm »
Génial, c'est fait, je vais changer la librairie pour incorporer cette donnée, la biblio changera d'ailleurs pas mal.
Si le constructeur n'accepte pas d'arguments, je dois tout changer pour mettre toutes les animations au même point afin d’homogénéiser le tout.
G.