Convertir un char en décimale

Salut !

Pour un projet je dois récupérer une trame de 3 octets dans le port série séparé par un point virgule ex: "11111111;00000000;11111111" j'ai donc trouvé comment récupérer les octets et le séparer le problème c'est qu'ils sont stockés dans une tableau char et je doit les convertir en décimal(je suis obligé c'est dans l'énoncé) mais je n'ai pas trouvé comment faire.

`const int LONGUEUR_STRING_MAX = 100;  // taille maxi de l'objet String`
`const int LONGUEUR_ITEM_MAX   = 9;   // nbr de caractères maxi de l'item`
`const int NBR_ITEMS_MAX       = 3;   // nbr d'items maxi`

`char delimiter[] = ";";     // délimiteur`
`char *item[NBR_ITEMS_MAX];  // tableau des éléments découpés`

`char text[LONGUEUR_STRING_MAX];`

`void setup() {`
 ` Serial.begin(115200);`
 
 ` String str = "11111111;01010101;00000000";`
 
  `char text[LONGUEUR_STRING_MAX];`
 ` str.toCharArray(text, sizeof(text));  // copie dans un tableau de char`
 
  `int nbr_items = 0;`
 
  `char* token = strtok(text, delimiter);`
  `while (token != nullptr && nbr_items < NBR_ITEMS_MAX)`
 ` {`
    `item[nbr_items++] = token;`
    `token = strtok(nullptr, delimiter);`
  `}`
 
  `int a = item[0];`
 `Serial.println(a);`
  
`}`
 
`void loop() {`
  `// code principal, en boucle infinie`
`}`

Par exemple item[0] contient 11111111 et le moniteur série renvoie 2200 mais je voudrais qu'il renvoie 255

par exemple avec item[0] = 00011001 on obtiendrait 25

je pense qu'il faudrait transformer le char en binaire puis le binaire en décimale mais je ne trouve pas comment faire

Merci par avance.

Bonjour et bienvenue

Merci de prendre quelques minutes pour lire les bonnes pratiques du forum francophone et les appliquer.

En particulier, la mise en forme du code avec les balises code

Cela ne fonctionne pas.
item[] est un tableau de char. Pour le convertir en entier il faudrait faire un atoi()

Cela ne fonctionne pas.
item[] est un tableau de char. Pour le convertir en entier il faudrait faire un [atoi()]

Quand j'utilise cette fonction on me dit qu'on ne peut pas convertir un char** en int.

qu'est-ce que tu as passé comme arguments à atoi()?

en fait c'est un tableau de char*
il faut appeler atoi() sur chaque élément (3 fois, donc)

D’une part atoi() nécessite que la chaîne soit terminée par un caractère nul. Il faut donc qu’il y soit - strtok() va le mettre pour vous au moment de segmenter la chaîne donc ça c’est OK mais vous ne voulez pas lire un entier - par exemple 10000000 ça ne tiendra pas sur 2 octets.

Si vous êtes garanti qu’il y a toujours les 8 bits (par exemple 00000011 et pas juste 11 pour dire 3(dec)) alors il suffit de parcourir le tableau jusqu’au séparateur (le ; et le caractère nul de fin de chaîne) ou juste avec une boucle for de 7 à 0 et regarder si c’est 1 ou 0 (pour s’assurer que c’est une entrée correcte) et d’ajouter au cas où c’est 1 la puissance de 2 correspondant à la position (27 pour le premier caractère, puis 26, 25… jusqu’à 20.

Merci J-M-L pour cette réponse rapide et très claire mais je n'arrive pas à comparer la valeur de mon tableau avec 1 ou 0

  for (int t=0; t < 8; t++)
  {
   if(item[0][t] == 1)
   {
     Serial.println("c'est un 1")
   }
   else if(item[0][t]) == 0)
   {
     Serial.println("c'ets un 0");
   }
  }
}

par exemple ici il ne comprend pas item[0][t] == 1 comment je peux vérifier que la valeur de mon tableau est un 1 ou un 0.

(dans cet exemple item[0] = 11111111)

bonjour,

essaye avec :

if(item[0][t] == '1')

@5_cylindres a raison. c'est avec un caractère que vous devez comparer (le code ASCII du symbole 1), pas le nombre 1. Donc on met des simple apostrophe autour du symbole pour dire que l'on veut sa valeur en tant que caractère ASCII

Super merci ça fonctionne mais... j'ai un dernier problème enfin j'espère j'ai fait ce code pour convertir en décimale la trame

void loop() {

    for (int t=0; t < 8; t++) 
  {
    if(item[0][t] == '1')  // si c'est un 1
    {
      dec1 = dec1 + pow(2,e); // je multiplie 2 par l'exposant 7 puis 6 puis 5 ect et je l'ajoute au ancienne valeur pour obtenir au final la valeur décimale
      e = e - 1;
    }
  }
  Serial.println(dec1);
}

mais je sait pas pourquoi le calcul que fait l'Arduino est pas bon j'ai dec1 = 0 et e =7 mais il trouve 127 au lieu de 128

utiliser pow(), c'est prendre un marteau pour écraser une mouche.
Il y a un algorithme bien plus efficace:

  • unsigned char poids = 1;
  • unsigned char valeur = 0;
  • pour tous les caractères, en partant du dernier:
    • si caractère == '1' alors valeur += poids;
    • quelque soit le caractère, poids *= 2; (ou mieux: poids <<= 1;)

Ca marche quelque soit le nombre de caractères (entre 1 et 8 cependant)

essayez un truc comme ça (tapé ici, non testé)

char saisie[] = "11111111;01010101;00000000"; // 255;85;0

void setup() {
  Serial.begin(115200);

  char * separateurPtr = strtok(saisie, ";");
  while (separateurPtr != nullptr) {
    Serial.print("Valeur détectée en binaire : "); Serial.print(separateurPtr);
    byte valeur = 0;
    for (int i = 0; i < 8; i++) {
      if (separateurPtr[i] == '1') valeur += (1u << (7 - i));
    }
    Serial.print(" -> En numérique "); Serial.println(valeur);
    separateurPtr = strtok(nullptr, ";");
  }
}

void loop() {}

si tout va bien vous devriez voir

Valeur détectée en binaire : 11111111 -> En numérique 255
Valeur détectée en binaire : 01010101 -> En numérique 85
Valeur détectée en binaire : 00000000 -> En numérique 0

la puissance de 2 est calculée avec la formule barbare (1u << (7 - i)) qui dit de prendre la valeur 1 (en non signée - d'où le u) et de la décaler en binaire de 7 moins i positions vers la gauche, ce qui correspond à aller chercher la bonne puissance de 2. (on fait 7 - i car le premier caractère c'est 27 quand i vaut 0, ensuite 26 quand i vaut 1, puis 25 quand i vaut 2,... ➜ 7 - i donne la bonne valeur pour la puissance)

1 Like

C'est bon effectivement ça marche super bien et c'est beaucoup plus concis que mon programme. Sachant que mon programme final est aussi assez balaise, c'est parfait. J'ai réussi à l'adapter et tout fonctionne merci à tous pour votre réactivité et votre aide.

maintenant que vous avez compris comment on fait, on va vous dire qu'il existe la fonction strtoul() qui fait ça pour vous :slight_smile:

char saisie[] = "11111111;01010101;00000000"; // 255;85;0

void setup() {
  Serial.begin(115200);

  char * separateurPtr = strtok(saisie, ";");
  while (separateurPtr != nullptr) {
    byte valeur = strtoul(separateurPtr, nullptr, 2); // 2 c'est pour dire que la chaîne est en base 2, en binaire
    Serial.print("Valeur détectée en binaire : "); Serial.print(separateurPtr);
    Serial.print(" -> En numérique "); Serial.println(valeur);
    separateurPtr = strtok(nullptr, ";");
  }
}

void loop() {}

l'avantage de la fonction c'est que ça fonctionne même si vous n'avez pas des 0 en padding au début et qu'il y a un paramètre additionnel (ici j'ai mis un pointeur nul) qui permet aussi de détecter des erreurs d'analyse - si l'utilisateur a rentré quelque chose qui ne convient pas

1 Like

:smiling_face_with_tear:

J'ai vu passer cette fonction dans mes recherches mais je ne me suis pas arrêté plus que ça dessus et je regrette un peu mais au moins j'ai appris pas mal d'autres choses.

c'est pas 100% évident, mais strtoul() ça veut dire "string to unsigned long".

et il y a aussi

fonction usage
strtol string to long integer
strtoll string to long long integer
strtoull string to unsigned long long integer
strtod string to double

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.