Pages: [1]   Go Down
Author Topic: [résolu] Problème concaténation  (Read 1225 times)
0 Members and 1 Guest are viewing this topic.
Metz
Offline Offline
Newbie
*
Karma: 0
Posts: 17
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

Hello,

Je galère à récupérer une variable appelée par une opération de concaténation avec l'index d'itération, je ne sais pas comment faire ça en C.
Pareil pour la déclaration... voici un petit exemple  smiley-wink

Code:
 
 for (byte i = 0 ; i < 5 ; i++){
       int 'variable'+i = analogRead('A'+i) ; // int capteur0 = analogRead(A0);
  }
 

Pour le moment je tourne avec des tableaux...mais il doit y avoir une astuce pour ce type de concaténation.

Si quelqu'un aurait la gentillesse de m'indiquer la syntaxe correcte smiley
Merci beaucoup.
« Last Edit: July 05, 2012, 03:28:47 am by AspiGeek » Logged

Bretagne
Offline Offline
Edison Member
*
Karma: 16
Posts: 1398
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Salut,

malheureusement, ce n'est pas un code interprété comme le PHP ou javascript... le nom de variable (la chaîne de caractère) disparaît à la compilation, laissant place à un pointeur (numérique : word ou unsined int). par les pointeurs, tu pourrais t'en sortir, mais je ne maitrise pas du tout l'utilisation des pointeurs. en attendant :

Code:
int capteur[5];

 for (byte i = 0 ; i < 5 ; i++){
       capteur[i] = analogRead(A0 + i) ; // capteur[i] = analogRead(Ai);
  }
A0 est une constante numérique dans le core arduino ( = 14 chez UNO si je ne me trompe). donc A0 + 1 = A1 = 15, et A0 + 5 = A5 = 19.

en remplaçant capteur par ptr_capteur + (2 * i) , je te donne un début de code qu'un expert en pointeurs corrigera je l'espère :

Code:
int capteur0, capteur1, capteur2, capteur3, capteur4, capteur5;  // déclarer les 6 variables en consécutif!
pointer ptrCapteur;  // je ne sais même pas comment déclarer un pointeur... la honte!

 for (byte i = 0 ; i < 5 ; i++){
      ptrCapteur = *capteur0 + (2 * i);  // assigne le pointeur sur la bonne variable
      ptrCapteur = analogRead(A0 + i) ; // capteur0 = analogRead(A0);
  }

Les deux codes ci-dessus feront exactement la même chose, mais j'ai dans l'idée que le premier est peut-être plus simple et plus sûr, selon l'utilisation ultérieure des variables dans ton soft... le premier code sera plus rapide.
« Last Edit: July 01, 2012, 12:41:10 am by Super_Cinci » Logged

Moselle (FR)
Offline Offline
Edison Member
*
Karma: 16
Posts: 1307
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Bonjour,

Salut,

malheureusement, ce n'est pas un code interprété comme le PHP ou javascript... le nom de variable (la chaîne de caractère) disparaît à la compilation, laissant place à un pointeur (numérique : word ou unsined int). par les pointeurs, tu pourrais t'en sortir, mais je ne maitrise pas du tout l'utilisation des pointeurs. en attendant :

Pour la partie pointeur, voir l'excellent tuto d'osaka : http://arduino.cc/forum/index.php/topic,101780.0.html
@+
icare
Logged

2B OR NOT(2B) = FF
Arduino 1.0.5 + Notepad++ (sous Linux Fedora et/ou Windows)

Ile-de-France (92 sud), France
Offline Offline
Edison Member
*
Karma: 24
Posts: 2055
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

Les deux codes ci-dessus feront exactement la même chose, mais j'ai dans l'idée que le premier est peut-être plus simple et plus sûr, selon l'utilisation ultérieure des variables dans ton soft... le premier code sera plus rapide.

Non.
Ces 2 codes montrent faiblesse ou erreur.

La Faiblesse

Quote
Code:
int capteur[5];

 for (byte i = 0 ; i < 5 ; i++){
       capteur[i] = analogRead(A0 + i) ; // capteur[i] = analogRead(Ai);
  }
A0 est une constante numérique dans le core arduino ( = 14 chez UNO si je ne me trompe). donc A0 + 1 = A1 = 15, et A0 + 5 = A5 = 19.

Ce code est exact mais part du principe indiqué dans la dernière phrase.
C'est peut être vrai sur une Uno aujourd'hui mais rien ne garantie que cela ce sera toujours le cas sur d'autres catres.
Donc attention aux conclusions tirées trop rapidement.
Mieux vaut utiliser une table redirection :

Code:
int capteur[5];
uint8_t pinCapteur[5] = { A0, A1, A2, A3, A4 };

for (byte i = 0 ; i < 5 ; i++)
{
       capteur[i] = analogRead( pinCapteur[i] ) ; // capteur[i] = analogRead(Ai);
}

La grossière erreur

Quote
Code:
int capteur0, capteur1, capteur2, capteur3, capteur4, capteur5;  // déclarer les 6 variables en consécutif!
pointer ptrCapteur;  // je ne sais même pas comment déclarer un pointeur... la honte!

 for (byte i = 0 ; i < 5 ; i++){
      ptrCapteur = *capteur0 + (2 * i);  // assigne le pointeur sur la bonne variable
      ptrCapteur = analogRead(A0 + i) ; // capteur0 = analogRead(A0);
  }

DANGER: Rien ne permet d'affirmer que les variables capteur0, capteur1,... sont allouées consécutivement en mémoire. Elle le sont peut être aujourd'hui dans ce code exemple avec cette version du compilateur et cette version du linker. C'est un coup de bol.
Ce genre d'affirmation est extrêmement dangereux à faire circuler.
De plus la syntaxe est completement fausse. Au mieux, si cela avait été une technique utilisable tu aurais eventuellement pu écrire :

Code:
int *ptrCapteur = &capteur0;  // assigne le pointeur sur la première variable
for (byte i = 0 ; i < 5 ; i++)
      *(ptrCapteur+i) = analogRead(A0 + i) ; // capteur0 = analogRead(A0);

Mais comme je le disait, de toute façon cette méthode est a proscrire.


La seule réponse valable est donc la première avec les tableaux.
Logged

Barbuduino: Arduino sur Breadboard & VinciDuino: Clone Leonardo // WR703: Mini-routeur hacké // LauchPad MSP430 et Stellaris // Panda II Arduino-like .NetMF sous VisualC#
RTFC: Read That F.....g Code / RTFD: Read That F.....g Doc / RTFDS: Read That F.....g DataSheet / RTFS: Read That F.....g Schematic / Wot da ya wanna D.I.Y. today ?

France
Offline Offline
Faraday Member
**
Karma: 55
Posts: 5413
Arduino Hacker
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

Bonjour,

malheureusement, ce n'est pas un code interprété comme le PHP ou javascript... le nom de variable (la chaîne de caractère) disparaît à la compilation, laissant place à un pointeur (numérique : word ou unsined int). par les pointeurs, tu pourrais t'en sortir, mais je ne maitrise pas du tout l'utilisation des pointeurs. en attendant :
Plus généralement, dans les langages de programmation interprété les noms de variable reste en mémoire lors de l'exécution.
Il est donc possible de faire des opérations sur une chaine de caractéres puis d'utiliser cette même chaine comme nom de variable, fonction, ...

Dans un langage de programmation compilé tout disparait et ce transforme en pointeur, en structure, en registre, etc ...
Il n'est impossible d'appeler une fonction par son nom lors de l'exécution puisse cette fonction n'as plus de nom mais juste un adresse en mémoire.

Méthode simple (et optimisé) :
Code:
#define NB_CAPTEURS 5
uint16_t capteur[NB_CAPTEURS];
const uint8_t pins[] = { A0, A1, A2, A3, A4 };

for (uint8_t i = 0; i < NB_CAPTEURS; ++i)
  capteur[i] = analogRead(pins[i]) ;

A0 est une constante numérique dans le core arduino ( = 14 chez UNO si je ne me trompe). donc A0 + 1 = A1 = 15, et A0 + 5 = A5 = 19.
C'est effectivement une constante, mais attention !

Depuis arduino 0023 il ne faut surtout plus raisonner en "A0 = D14 sur une UNO", etc ...
Avec les nouvelles cartes arduino (leonardo par exemple) les broches Ax peuvent trés bien se trouver en plein milieu des broches numérique !
(A6 = D4 par exemple sur la leonardo).

Ton code "analogRead(A0 + i)" est donc une source d'erreur à court comme à moyen terme smiley-wink

en remplaçant capteur par ptr_capteur + (2 * i) , je te donne un début de code qu'un expert en pointeurs corrigera je l'espère :
(...)
Aie Aie Aie ... c'est la catastrophe ...
Sur ce coup tu aurais mieux fait de rien dire smiley-wink

Ton code + annotations :
Code:
int capteur0, capteur1, capteur2, capteur3, capteur4, capteur5;  // déclarer les 6 variables en consécutif!
/* NON rien ne te dit que le compilateur ne vas pas optimiser et réaligner ces variables ! */
/* SAUF si tu lui précise qu'elles sont "volatile", mais la encore rien ne te garanti l'ordre dans lequel seront aligné les variables en mémoire */

pointer ptrCapteur;  // je ne sais même pas comment déclarer un pointeur... la honte!
/* déclaration : type * nom; -> exemple int *pointeur; */

 for (byte i = 0 ; i < 5 ; i++){
      ptrCapteur = *capteur0 + (2 * i);  // assigne le pointeur sur la bonne variable
      /* Are you procreating serious ? */
      /* *capteur0 -> erreur de compilation pure et simple, l'adresse de capteur0 est &capteur0 (& pas *) */
      /* (2 * i) n'est pas portable, mieux vaut utiliser (sizeof(int) * i) */

      ptrCapteur = analogRead(A0 + i) ; // capteur0 = analogRead(A0);
      /* Tu assignes une valeur dans un pointeur, un pointeur étant une adresse tu changes l'adresse mais pas le contenu pointé */
      /* *ptrCapteur = analogRead(A0 + i); (ne pas oublier l'accesseur étoile devant le pointeur) */
  }

Un code avec pointeurs, correct d'un point de vue syntaxique et sémantique, mais horriblement moche et pas pratique :
Code:
#define NB_CAPTEURS 5 // Nombre de capteurs

uint16_t c0, c1, c2, c3, c4; // Variables de destination
const uint16_t *ptr[] = { &c0, &c1, &c2, &c3, &c4 }; // Tableau de pointeur (agencement manuel des adresses)
const uint8_t pins[] = { A0, A1, A2, A3, A4 }; // Tableau de broches (voir remarque plus haut)

for (uint8_t i = 0; i < NB_CAPTEURS; ++i) // Boucle de parcours
  *(ptr + i) = analogRead(pins[i]); // équivalent à *(ptr[i]) = analogRead(pins[i]); // Assignation de la valeur

Edit: J'ai été grilled en beauté par barbudor smiley-zipper
« Last Edit: July 01, 2012, 04:15:26 am by skywodd » Logged

Des news, des tuto et plein de bonne chose sur http://skyduino.wordpress.com !

Ile-de-France (92 sud), France
Offline Offline
Edison Member
*
Karma: 24
Posts: 2055
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

Edit: J'ai été grilled en beauté par barbudor smiley-zipper

Chacun son tour smiley-wink

Quote
/* (2 * i) n'est pas portable, mieux vaut utiliser (sizeof(int) * i) */

j'en profite au passage pour rappeler qu'en C l'arithmétique sur les pointeur prend en compte la taille de l'objet pointé.
donc

int capteur[5];
int *PtrCapteur = &capteur[0];

*(PtrCapteur+i) est donc équivalent à capteur : glop
*(PtrCapteur+sizeof(int)*i) est donc équivalent à capteur[sizeof(int)*i] : pas-glop


Ce que Skywodd fait d'ailleur très bien dans sont autre code avec *(ptr + i)
« Last Edit: July 01, 2012, 04:30:52 am by barbudor » Logged

Barbuduino: Arduino sur Breadboard & VinciDuino: Clone Leonardo // WR703: Mini-routeur hacké // LauchPad MSP430 et Stellaris // Panda II Arduino-like .NetMF sous VisualC#
RTFC: Read That F.....g Code / RTFD: Read That F.....g Doc / RTFDS: Read That F.....g DataSheet / RTFS: Read That F.....g Schematic / Wot da ya wanna D.I.Y. today ?

France
Offline Offline
Faraday Member
**
Karma: 55
Posts: 5413
Arduino Hacker
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

Quote
/* (2 * i) n'est pas portable, mieux vaut utiliser (sizeof(int) * i) */

j'en profite au passage pour rappeler qu'en C l'arithmétique sur les pointeur prend en compte la taille de l'objet pointé.
donc
Oui c'est bon à préciser.

Ce commentaire est à voir dans le contexte du code de Super_Cinci.
On voyait bien que ce (2 * i) correspondait à la taille du int, mais vu que c'était pas vraiment de l'arithmétique de pointeur (voir même du C smiley-mr-green) je me suis dit que ça serait pas plus mal de le préciser.

Bref tout ça pour dire, AspiGeek si tu veut avoir à prendre de l'aspirine (oui je sait, jeu de mot de merde ...) utilise la version simple et optimisé smiley-wink
Un tableau pour les valeurs et un tableau pour les broches.
Logged

Des news, des tuto et plein de bonne chose sur http://skyduino.wordpress.com !

Metz
Offline Offline
Newbie
*
Karma: 0
Posts: 17
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

Merci à tous pour vos réponses complètes et précises, je les ai lu avec attention  smiley
Travaillant principalement sur des langages interprétés ces notions de pointeurs ne me sont pas familières malheureusement.
J'avais déjà mis en place la solution avec array, je m'interrogeais sur le fait si on pouvait sans passer via une syntaxe de concaténation particulière, un minimum de connaissance en C m'aurait donc évité cette question...

Va falloir que je m'y plonge sérieusement et prendre un peu d'aspirine  smiley-wink

Merci encore. ++
Logged

Bretagne
Offline Offline
Edison Member
*
Karma: 16
Posts: 1398
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

J'avais écrit un peu vite, c'était juste pour donner des pistes de réflexion. En effet, je suis tout à fait d'accord que :

- mes codes ne sont pas à prendre pour exemple (c'était juste l'idée d'une méthode)
- les variables peuvent se trouver n'importe-où en mémoire, donc pas forcément dans l'ordre de déclaration.
- d'une carte à l'autre, les constantes A0, A1, ..., An peuvent prendre n'importe quelles valeurs

et les autres points aussi.

je voulais juste évoquer les différentes méthodes, mais la solution avec les deux tableaux est largement préférable. Finalement, la question d'AspiGeek était juste "les noms de variables sont-ils conservés à la compilation", et nous y avons répondu, je crois  smiley-lol

on n'est donc pas trop loin de la balise [résolu].
Logged

Made in Belgium
Offline Offline
God Member
*****
Karma: 1
Posts: 756
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Yop Yop,
Juste une dernière petite explication, il faut bien comprendre que tous le code que nous écrivons ne sont que des instructions destinés au compilateur et non à la machine directement, le code (machine) résultant est tout autres.
Le type de variable (qu'il peut retravailler pour optimiser, etc) et les noms à la déclaration par exemple ne sont que des "repères" qui seront traité et disparaitrons une fois compilé.
Logged


Metz
Offline Offline
Newbie
*
Karma: 0
Posts: 17
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

Merci pour les précisions.  smiley
Logged

Pages: [1]   Go Up
Jump to: