Question Code à propos des randoms?

Bonjour, j’essaie d’appeler des fonctions de façon aléatoire, mais je ne comprends pas ce qui cloche dans mon code.

La première idée était celle-ci et elle fonctionne. La fonction est bien appelée de façon (pseudo)-aléatoire et s’exécute correctement.

void randomFonction()
{
  int randomNumber = 0;
  randomNumber = random (1, 6);
  if (randomNumber == 1) {fonction1();}
  if (randomNumber == 2) {fonction2();}
  if (randomNumber == 3) {fonction3();}
  if (randomNumber == 4) {fonction4();}
  if (randomNumber == 5) {fonction5();}
}

Evidemment, si j’ai 300 fonctions aléatoires, le code devient méga lourd… Donc, l’idée suivante serait celle-ci :

void randomFonction()
{
  int randomNumber = 0;
  randomNumber = random (1, 6);
  char buf[13];
  sprintf(buf,"fonction%d();",randomNumber);
  (buf);

  Serial.println (buf); // histoire de vérifier que le résultat de mon machin écrit bien un nom de fonction valide. 
  delay (1000);
}

Sur le moniteur série, je vois bien se succéder de façon pseudo-aléatoire les différentes fonctions: fonction2(); fonction4(); fonction1(); Etc.

Par contre, les fonctions respectives en question ne se lancent pas… pourquoi?

ps: indulgence please, je débute :)

Ce que tu veux faire n’est pas du C, ce n’est pas possible en C.
En C le nom des fonctions doit être connu dès la compilation. Toi tu fabriques des noms à l’éxécution, ça ne peut pas marcher.

Si tu as 300 fonctions, tu peux créer un tableau de pointeurs sur fonction :

#include <stdio.h>
void f1 ( void ) { printf ( "1\n" ); }
void f2 ( void ) { printf ( "2\n" ); }

void (*Tableau[2])(void) = { f1, f2 };

int main ( void )
{
  Tableau[0]();
  Tableau[1]();
  return 0;
}

Arf, ce n'est vraiment pas facile en autodidacte...on trouve tellement d'infos contradictoires...

J'essaie de m'en sortir avec un bouquin en C/C++ effectivement, car je ne cesse de lire partout que le langage d'arduino est "une sorte de" ou "'très proche de" C, C++", mais c'est quand même dingue qu'il ne soit pas définit plus précisément que cela...

Bref, à mon stade, impossible de dire si ça fonctionnera ou pas sur l'arduino quand je pioche des infos dans des contextes C/C++ du coup...

N'y aurait-il pas moyen de solutionner le problème sur base de ce que j'ai déjà apporté? Etant donné que le serial monitor m'affiche bien : fonction1(); etc. N'est-il pas possible d'imaginer que le résultat de cette expression parfaitement formulée soit "rapatriée" comme une ligne de code qui s'exécute? Cette logique est-elle vraiment incompatible dans le langage Arduino? Si oui, pourquoi?

babette: J'essaie de m'en sortir avec un bouquin en C/C++ effectivement, car je ne cesse de lire partout que le langage d'arduino est "une sorte de" ou "'très proche de" C, C++", mais c'est quand même dingue qu'il ne soit pas définit plus précisément que cela...

il n'y a pas de "langage Arduino". le langage dans l'IDE c'est le C++

Arduino c'est un environnement de développement donc ils vous fournissent en plus des librairies et un outil pour faciliter la compilation et la structuration de votre code (avec setup() et loop()). Bcp des fonctions possibles (fournies dans les librairies) sont liées au matériel (port Série, gestion des pins, protocoles, etc)

Vous pourriez coder avec n'importe quoi d'autre qui génère un binaire en langage machine adapté à votre micro-processeur.

--> Donc pour le langage, apprenez le C et le C++.

ensuite bien sûr comme il n'y pas de clavier, d'écran, de disque dur etc - certains tutos génériques que vous trouverez pour le C ou C++ ne fonctionneront pas pareil. Pour afficher sur votre Arduino par exemple, il faut envoyer le texte sur le port Série et connecter l'arduino à votre ordinateur


Pour votre question, non ce n'est pas possible; Le langage C ou C++ n'est pas interprété, il n'y a pas de runtime (ni d'OS sur la carte); Les noms de fonctions ont complètement disparus lorsque votre code arrive sur votre arduino. il ne reste plus que des adresses mémoires et de bouts de code à exécuter. c'est le compilateur (et le linker) qui génère tout cela pour vous. donc quand vous déclarez le tableau de fonctions comme proposé par biggilvoid (*Tableau[2])(void) = { f1, f2 };vous définissez un tableau et dites au compilateur en détaillant le type avec cette écriture un peu compliquée que la tableau contient les adresses mémoires où le code à exécuter commence et qu'il y en a 2.

Le compilateur sait alors où il a rangé les fonctions, stocke l'adresse de ces fonctions dans le tableau et vous pouvez donc déclencher une des fonctions puisque vous savez où elles sont.

Si vous voulez bien comprendre, lisez un cours sur l'architecture des ordinateurs (ou des micro-contrôleurs) - vous comprendrez mieux ces notions de mémoires, code executable, ram, pile, tas etc... qui sont importantes

Dans un programme C (ou C++), on définit une fonction par (par exemple) :

int mafonction ( int n ) {
  /* ... faire quue chose */
  return resultat;
}

Lorsque que le compilateur rencontre ceci, il note bien que mafonction est une fonction, qui prend un argument de type int et renvoie au final un int. Il génère le code (en assembleur bas niveau) correspondant à la recupération de l’argument, les traitements internes à la fonction et la mise à disposition du résultat. Il garde tout ça en mémoire (sa mémoire de compilateur).
Plus loin, le compilateur trouve ceci (par exemple) :

int ret = mafonction ( 4 );

D’abord, il identifie par la syntaxe qu’il s’agit d’un appel de fonction, deuxio il cherche dans ses tables s’il connait effectivement une fonction qui possède ce nom (mafonction) et qui prend en argument un int.
Si tout est OK, il note que cette ligne de code appelle la fonction nommée mafonction, en lui passant l’argument 4 et en rangeant le résultat dans la variable ret.
Il faut noter qu’à ce stade, le contenu de la fonction appelée n’a pas besoin d’être connu. Dans mon exemple il est connu, mais en cas d’appel à une fonction d’une bibliothèque externe, ce n’est pas le cas, mais ce n’est pas grave : le compilateur place dans le code assembleur généré un appel à la fonction.

Quand le compilateur (le traducteur) a fini son travail, on passe à la phase de l’édition des liens (le linker). Le linker est un programme qui récupère tous les petits bouts de code - pas bien finis - générés par le compilateur, et qui résoud tous les appels de fonctions. S’apercevant qu’à un moment on a besoin de la fonction mafonction, il va :

  • placer le code de la-dite fonction dans le programme (assembleur) qu’il génère, à une certaine adresse,
  • placer cette adresse dans le code à l’endroit où le fonction est appelée.

A la fin, le programme exécutable est produit, terminé, complet.
A partir de ce moment tous les noms de fonctions et de variables ont disparu !

Donc on ne peut plus, quand le programme est lancé, re-fabriquer des noms de choses qui existaient avant la compilation, pour s’en servir d’une manière ou d’une autre. Le programme lancé n’a aucune idée de ce que la chaîne de caractères “mafonction” signifie !

OK, c’est un peu compliqué, mais ça marche comme ça - pour un langage compilé tel que le C ou le C++.

Wouaw, merci bcp pour ces infos. Je pense comprendre correctement l’idée de la distinction entre langage machine et code, bien sûr. Mais, je me disais que, peut-être, un nom généré pourrait être rapatrié grâce à une bibliothèque développée pour cela comme nom d’appel d’une fonction déjà détaillée dans le sketch. Certes, le genre de processus est un peu saugrenu, mais pourquoi pas dans le fond. Puisque Void .....() peut être interprété par le micro-controleur comme fonction, pourquoi ne pas imaginer un processus qui dirait: fais des caractères qui ont été générés un mot et si ce mot correspond à une fonction précitée et marquée par un Void (afin qu’il identifie la différence entre ce mot et une fonction pertinente pour lui), exécute la?

Ce que tu proposes, c'est d'inventer un nouveau langage de programmation. Il en existe déjà un très grand nombre, et certains peuvent sans doute faire ce que tu veux. Malheureusement, l'IDE Arduino marche en C++ et en C++ seulement, il va falloir faire avec.

Plutôt que de vouloir changer le monde, je te conseille d'étudier l'exemple que j'ai donné, qui est pleinement fonctionnel pour ce que tu veux faire (et infiniment plus simple que de réécrire une chaîne de compilation).

ok, ok, je ne vais pas inventer un nouveau langage :) Peux-tu m'expliquer un peu mieux la solution que tu proposes ou me donner des références plus complètes que je pourrai consulter concernant cette structure en tableau?

critique constructive: (ne prenez pas cela personnellement, on a tous débuté et dit beaucoup de sottises :)) )

Tout votre délire sur le mot clé void n’a absolument aucun sens... lisez un tuto C et C++ et ensuite revenez lire votre délire et ça vous fera rigoler :)

Votre histoire n’a aucun sens non plus - c’est pas en inventant un truc super compliqué qui doit mémoriser dans le peu de mémoire de votre arduino un nom de fonction histoire de pouvoir faire plus tard une recherche coûteuse par comparaison de texte que vous allez progresser. Désolé de vous le dire mais c’est une très mauvaise idée - c’est typiquement la définition d’un problème XY - vous voulez faire X mais vous êtes tellement convaincu que la solution est Y que vous posez une question pour qu'on vous aide à faire Y en pensant que c’est la meilleure solution et n'en démordez pas... ben non - c’est nul comme idée que ce soit sur petit micro contrôleur sans OS et sans run time et sur un gros... pourquoi gaspiller des resources informatiques (si la fonctionnalité n'est pas en standard dans le langage en tout cas - il y a des langages où on ne put par récupérer des pointeurs sur fonctions)... il faut faire comme indiqué en utilisant des pointeurs de fonctions.

Vous faites un google sur C++ tableaux pour apprendre ce qu’est un tableau et C++ pointeur sur fonction et vous aurez toutes les infos nécessaires

Mais vraiment avant de vous plonger la dedans commencez pas la base. Un cours sur le langage C et la structure de base d’un ordinateur - une fois cela acquis vous aurez fait un immense pas en avant avec de solides fondations sur lesquelles bâtir