Comment converti un char to a float ou un double

Bonjour à tous

Je m'excuse mais je me prends le chou pour faire un truc qui devrait être basic.

Je souhaite convertir un char en un float ou un double.

La truc, c'est que je dois garder les décimal.

J'arrive à le faire mais j'ai toujours deux décimal après la virgule alors que dois en garder au moins 4 ou plus.

Voici mon code

convertLat("46.524220");
double WI968C::convertLat(char* latString)        // Convert from ddmm to ddmm.mmmmm
{
 Serial.println(latString);

double latitude;
//sscanf(latString,"%f",latitude);
latitude = atof(latString);
Serial.println(latitude);
int deg = (int) latitude;
double fraction_of_a_degree = latitude - deg;
Serial.println(fraction_of_a_degree);
double minutes = fraction_of_a_degree * 60.0;
double newLatitude = deg * 100 + minutes;
return newLatitude;

}

Je dois avoir, à la fin : 4631.4532

J'ai essayé avec sscanf, strtof, strtod, et rien ne m'a afficher avec 4 chiffre après la virgule. Plus il y a de chiffres après la virgule, plus c'est précis...

Merci pour vos lumières

Que donnent les 3 Serial.print() du code ci-dessus ?

Bonjour,

Je n’arrive pas à comprendre ce que tu veux faire
Si c’est convertir la chaine en float tu l’as fait ici:

latitude = atof(latString);

Qu’est ce que tu veux faire ensuite ? convertir en degré minute seconde ? Pourquoi est ce que tu multiplies les degrés par 100 ?

Peut-être que ta variable calculée a bien le bon niveau de précision, mais que c'est seulement l'affichage de sa valeur qui est réduit aux deux premières décimales.

https://www.arduino.cc/en/Serial/Print

Dans ton float final :

Les chiffres des unités et dizaines représentent les minutes, de 00 à 59 Les chiffres des centaines et supérieures représentent les degrés Les chiffres après la virgule représentent les secondes, exprimées en partie décimalisée des minutes

Après un format de date bizarre, voici un format de latitude non moins bizarre.

Tu veux envoyer toutes ces valeurs dans quel système bizarre exactement ? :)

Hello,

Ben mon but c’est convertir
46.524220 (degre decimal)
en
4631.4532 (degre minumte, ddmm.mmmmm)

Si vous entrer 46.524220 dans le champs ‘Degre decimal’, vous verrez quand plus bas ca donne bien
DM.m : 46 31.4532

Le problème ce que mon code me retourne ceci

4631.45 (pardon, j’ai oublié de mettre le résultat que ca me retourne)

Et j’ai constaté que c’est après le

latitude = atof(latString);
Serial.println(latitude);

Qu’il perd les deux derniers décimal.

Ce code

double WI968C::convertLat(char* latString)        // Convert from ddmm to ddmm.mmmmm
{
 Serial.println(latString);
 Serial.println(strlen(latString));
 Serial.println(latString[0]);
 Serial.println(latString[1]);

double latitude = atof(latString);
//sscanf(latString,"%f",latitude);
Serial.println(latitude);
int deg = (int) latitude;
double fraction_of_a_degree = latitude - deg;
Serial.println(fraction_of_a_degree);
double minutes = fraction_of_a_degree * 60.0;
double newLatitude = deg * 100 + minutes;
Serial.println(newLatitude);
return newLatitude;

}

m’affiche

46.524220
9
4
6
46.52
0.52
4631.45

Donc je suis sûre que m’ont calcul n’est pas faux, c’est juste que je fais faux au niveau de la conversion :o)
non?

Merciiiii!

bricoleau: Peut-être que ta variable calculée a bien le bon niveau de précision, mais que c'est seulement l'affichage de sa valeur qui est réduit aux deux premières décimales.

https://www.arduino.cc/en/Serial/Print

Salut Bricolau, excuse moi, j'ai répondu avant de lire ta remarque. En effet, ca change tout!!! Merci

J'ai corrigé mes print en ajoutant un 4

Serial.println(latitude,4);

En effet, là j'ai tout qui s'affiche.

Alors en fait, ca fonctionne bien. :)

Donc je eux utiliser sans autre la variable dans la suite de mon code

newLatitude

Well done

J'ai vraiment des lacunes dans la manipulation des varaibles.

C'est bien beau d'avoir reussi a convertir les positions, mais maintenant, je dois convertir de double en char, car mon URL est contruite avec des char.

Et là, rebelotte, je n'arrive pas à avoir mon résulta

char * WI968C::convertLatLon(char* latString)        // Convert from ddmm to ddmm.mmmmm
{

  char result[strlen(latString)];
  double latitude = atof(latString);
  int deg = (int) latitude;
  double fraction_of_a_degree = latitude - deg;
  double minutes = fraction_of_a_degree * 60.0;
  double newLatitude = deg * 100 + minutes;
  Serial.println(newLatitude,4);
  snprintf(result,strlen(latString),"%f",newLatitude);
  // printf("%s",result);
   Serial.println(result);
   return result;
}

Le premier print affiche bien : 4631.4532 mais le deuxième affiche un point d'interrogation!

Je ne sais pas trp quoi mettre ici : %f. J'ai essayé plusieur truc dont %8,4f mais sans résultat....

Mais il y a pas des fonctions de base pour convertir ceci, simplement?

Chez les english, la virgule est un point. Donc... "%8.4f"

Mince pardon, oui en effet, je l'ai mal écris dans mon post. Dans mon code j'ai bien un poit mais ca bug, ca affiche ceci:

4631.4531
       ?

(y a des faux caractere vers le ?)

char * WI968C::convertLatLon(char* latString)        // Convert from ddmm to ddmm.mmmmm
{

  char result[strlen(latString)];
  double latitude = atof(latString);
  int deg = (int) latitude;
  double fraction_of_a_degree = latitude - deg;
  double minutes = fraction_of_a_degree * 60.0;
  double newLatitude = deg * 100 + minutes;
  Serial.println(newLatitude,4);
  snprintf(result,strlen(latString),"%8.4f",newLatitude);
  //printf("%s",result);
   Serial.println(result);
   return result;
}

(J'ai aussi essayé en decommentant //printf("%s",result);)

et ca , le deuxieme println() n'affiche rien

char * WI968C::convertLatLon(char* latString)        // Convert from ddmm to ddmm.mmmmm
{

  char results[sizeof(latString)];
  double latitude = atof(latString);
  int deg = (int) latitude;
  double fraction_of_a_degree = latitude - deg;
  double minutes = fraction_of_a_degree * 60.0;
  double newLatitude = deg * 100 + minutes;
  Serial.println(newLatitude,4);
  snprintf(results,sizeof(latString),"%8.4f",newLatitude);
  //printf("%s",result);
   Serial.println(results);
   return results;
}

Je suis presqu'arrivé

Serial.println(wi968c.convertLatLon("46.524220"));
char * WI968C::convertLatLon(char* latString)        // Convert from ddmm to ddmm.mmmmm
{

  char results[9];
  double latitude = atof(latString);
  int deg = (int) latitude;
  double fraction_of_a_degree = latitude - deg;
  double minutes = fraction_of_a_degree * 60.0;
  double newLatitude = deg * 100 + minutes;
  Serial.println(newLatitude,4);
  
  //Serial.println(sizeof(newLatitude));
  //Serial.println(strlen(newLatitude));

  dtostrf(newLatitude, 8, 4, results);

   Serial.println(results);
   return results;
}

Les deux Serial.println dans la fonction affiche bien le bon résultat alors que ceci

Serial.println(wi968c.convertLatLon("46.524220"));

affiche un peu n'impotre quoi, soit un 4 avec des faux caracteres...

4

Je te conseille d’ajouter cette ligne…

Serial.println(sizeof(latString));

J’ai réussi à faire quelque chose avec un code que j’ai trouvé

Serial.println(convertLatLon("46.524220"));

char *WI968C::convertLatLon(char* latString)        // Convert from ddmm to ddmm.mmmmm
{
  Serial.print(F("c."));
  Serial.println(latString);

  //char results[9];
  double latitude = atof(latString);
  int deg = (int) latitude;
  double fraction_of_a_degree = latitude - deg;
  double minutes = fraction_of_a_degree * 60.0;
  double newLatitude = deg * 100 + minutes;

  /* Conversion to String */

  int ndec = 4;
  String r = "";
  int v = (int)newLatitude;
  r += v;     // whole number part
  r += '.';   // decimal point 
  int i;
  for (i=0;i<ndec;i++) {
    // iterate through each decimal digit for 0..ndec 
    newLatitude -= v;
    newLatitude *= 10; 
    v = newLatitude;
    r += v;
  }

  Serial.println(r.length());
  /* Conversion to Char */
  char res[r.length()+1];
    
  r.toCharArray(res,r.length()+1);

  Serial.print(F("d."));
  Serial.println(res);

/* REturn the Char to be used later */
  return res;
}

Le dernier

Serial.print(F("d.");
 Serial.println(res);

M’affiche bien ce que j’attend

4631.4531

Sauf que ceci
Serial.println(convertLatLon(“46.524220”));
ne m’affiche pas ce que je souhiate pourtant je retourne bien un char.
Il m’affiche un truc tronqué:

46�2�

Je pense que tu mélanges joyeusement chaînes et pointeurs

char *toto;

la variable toto est de type char * C'est un pointeur vers un char

En clair : 1) la valeur de toto est une adresse, c'est-à-dire un nombre compris entre 0 et 65535. 2) tu peux afficher cette valeur par un sprintf(cible, "%p", toto); 3) sizeof(toto) = 2, comme tout pointeur sur arduino car c'est un système d'adressage à 16 bits. 4) à l'adresse désignée par la valeur de toto, le compilo considère qu'il y a un char.

donc en gros, un char* n'est qu'une adresse

pierrot10: ``` char * WI968C::convertLatLon(char* latString)        // Convert from ddmm to ddmm.mmmmm {

  char results[sizeof(latString)];   ... }

Là tu alloues un tableau "results" de deux caractères. Pas sûr que ce soit ce que tu voulais faire (et même sûr du contraire)

Serial.println(convertLatLon("46.524220"));

char *WI968C::convertLatLon(char* latString)        // Convert from ddmm to ddmm.mmmmm
{
  ...

  char res[...];

  ...
  return res;
}

latString n'est pas une chaine de caractère. C'est l'adresse du premier caractère d'une chaîne. D'ailleurs une chaîne cela n'existe pas vraiment en C. Par convention, c'est une suite de caractères qui démarre à une certaine adresse, et qui s'arrête lorsqu'on trouve un caractère nul.

Quand tu écris "46.524220" dans ton programme, le compilateur stocke cette chaîne de manière permanente en RAM, et la substitue par son adresse là où elle est utilisée, dans le code compilé.

Ta méthode convertLatLon retourne un char*, c'est-à-dire une adresse. Elle ne retourne pas une chaîne de caractères.

res est un tableau de char alloué de manière temporaire dans ta méthode. Tu retournes l'adresse de res, sauf qu'une fois sorti de convertLatLon, le contenu de la RAM à cette adresse est susceptible d'évoluer, puisqu'il n'est plus réservé à la variable res.

Merci bricolau pour ton explication. Je t'avoue qu'en effet c'est une grosse lacune que j'ai. Quand j'ai commencé je ne savais que faire

Serial.prinrln("Hello Word")

Et j'ai tout appris en autodidacte grâce au web et aux forum. Je suis assez fier de ce que j'ai fais aujourd'hui j'ai fais un énorme job en 3 ans, surtout quand je pense comme était mon code et mes modules, au début.

Je pense qu'il me manque une bonne formation pour compléter ces lacunes qui semble si basic, et ça me frusque (rire) de passer autant de temps alors qu'en PHP, je l'aurais fais en 5mn. Faut que je me documente plus sur les char et pointeur, c'est une évidence. Si tu as des liens ou livres à sugerer, c'est avec plaisir.

Pour revenir sur mon problème, ben ça ne marche toujours pas. Bon normal, j'ai rien fait depuis mon dernier post. (Faut dormir un peu, comme même (rire).

Ceci dit, oui j'avais déjà renarque qu'il n'était pas possible de déclarer localement un char pour utiliser sa valeur à l'extérieur de la fonction. Je devrais stocker ma valeur voulue dans un char global et revoir mon code en fonction de tes observations sur les pointeurs

Merci!!!

pierrot10: Ceci dit, oui j'avais déjà renarque qu'il n'était pas possible de déclarer localement un char pour utiliser sa valeur à l'extérieur de la fonction.

Bonjour,

Si ton char[] est déclaré à l'intérieur d'une fonction par défaut il est alloué dans la pile, donc effectivement détruit en sortant de la fonction. Par contre tu peux le déclarer 'static' et là il sera alloué statiquement et persistera à la sortie de la fonction

  static char res[...];
...
/* REturn the Char to be used later */
  return res;

Par contre la comme pour une déclaration globale la taille du tableau doit être une constante