extraire chaine de charactere d'un String

Bonjour,

mon projet avance mais de nouveau je bloque et j'ai besoin de vos lumiéres....

le PB : je lis un DHT22 relié à un wemos ESP12 qui est configuré "serveur".
je réalise un objet String qui contient toutes les infos du DHT et autre.

Depuis un second wemos en "client" , j'envoie un requete à mon serveur et reçoit en retour le String contenant toutes mes info:
la mise en forme est :
"Temp 21.5 / Hum 65 / Relai 1 "

je veux récupérer "21.5", mais ça pourrait bien être "24.45"
et ensuite le "65", le "1", et d'autre viendront se rajouter...

comment est ce que je peut faire sachant que la longueur de la chaine varie?

j'ai vu les fonctions charAt, startsWith(), endWith(), strtok

comment dois je m'y prendre?
je peux changer la mise en forme du string de départ si des balise type et sont plus facilement reconnaissable, peut être découper la chaine ?

je m'embrouille un peu :frowning: :confused:

Tu peux utiliser la fonction strtof :

String message;
char *pEnd;
float Temp;
float Hum;
int Relais;

Temp = strtof (message, &pEnd);
Hum= strtof (pEnd, &pEnd);
Relais = atoi (pEnd);

ou Relais = strtol (pEnd, NULL);A tester...

Peut-être faut-il utiliser 2 pointeurs, je ne sais pas.

Salut

Au plus simple avec sscanf :

 char s[] = "Temp 21.5 / Hum 65 / Relai 1";
 char tmp[10];
 char c;
 float temp;
 int hum, rel;
 sscanf(s, "%s %f %c %s %d %c %s %d", tmp, &temp, &c, tmp, &hum, &c, tmp, &rel);

C'est en effet plus simple. Je ne comprends pas à quoi sert le char c : ça ne fonctionnerait pas comme ça ?

 sscanf(s, "%s %f %s %d %s %d", tmp, &temp, tmp, &hum, tmp, &rel);

Bonjour,

le 'char c' sert à capturer le caractère '/'. sscanf utilise l'espace comme séparateurs de champ. Un champ un %bidule.

Remarques :

  • le %f (f:float) n'est pas intégré par défaut (pour des raisons de place de code) dans le sscanf de bibliothèque arduino. Il faut utiliser un %s (s:string) puis faire par exemple un atof sur la capture.

  • Il est possible de placer une '*' après le % pour ne pas mémoriser la capture.

  • il est possible d'utiliser la valeur de retour de sscanf pour verifier le bon nombre de champs mémorisés (bon format de la ligne à scanner).

Exemple d'un code qui fonctionne chez moi :

char s[]="Temp 21.5 / Hum 65 / Relai 1";
char floatStr[10];
float temp;
int hum, rel, n;
n=sscanf(s, "%*s %s %*c %*s %d %*c %*s %d", floatStr, &hum, &rel);
temp=atof(floatStr);
Serial.println((String)"n:"+n); 
Serial.println((String)"temp:"+temp+" hum:"+hum+" relai:"+rel);

C'est génial sscanf :wink:

Edit :

  • j'avais oublié de déclarer n :-~
  • si la chaine à parser est dans une String il faut donner à sscanf sa représentation "chaîne de caractères à la C" obtenue facilement avec la méthode c_str(). Exemple :
String s="Temp 21.5 / Hum 65 / Relai 1";
// ...
n=sscanf(s.c_str(), "%*s %s %*c %*s %d %*c %*s %d", floatStr, &hum, &rel);
// ...

Cela marche aussi comme ceci:

	char s[] = "Temp 21.5 / Hum 65 / Relai 1";
        char floatStr[10];
	int hum, rel;
	sscanf(s, "Temp %f / Hum %d / Relai %d", floatStr, &hum, &rel);
  char s[] = "Temp 21.5 / Hum 65 / Relai 1";
  char floatStr[6];
  int hum, rel;
  sscanf(s, "Temp %s / Hum %d / Relai %d", floatStr, &hum, &rel);
  Serial.print("Temp:");
  Serial.println(atof(floatStr));
  Serial.print("Hum:");
  Serial.println(hum);
  Serial.print("Rel:");
  Serial.println(rel);

Code non testé. Pas d'ARDUINO au boulot.
@+

A oui, c'est mieux :wink:

Pas de problème à scanner les %f de ton coté ?

Sous LINUX avec GCC, non bien sûr.
Désolé je n'avais pas pensé au détail du %f non implémenté dans la lib ARDUINO.

@+

ouawww !! :o :o

ça m'a fais mal au yeux quand j'ai vu tous ces %c%s ....

je crois que je vais bosser sscanf! Génial le coup des détections de blanc et /

MERCI à vous !! o TOP

SUPERCC

Quand tu dis ;

  • Il est possible de placer une '*' après le % pour ne pas mémoriser la capture.

Qu’est ce que ça implique?
Des erreurs possible par la suite?

le '*' après le % implique juste que tu n'as pas besoin de donner l'adresse d'une variable "poubelle" lorsque tu n'es pas intéressé par la valeur scannée (économie mémoire).

Pas plus d'erreur par la suite que dans les autres cas :wink:

Un résumé des 3 versions qui fonctionnent:

// 1
char tmp[10]; char c; char floatStr[7]; int hum, rel;
sscanf(s, "%s %f %s %d %s %d", tmp, &floatStr, tmp, &hum, tmp, &rel);

// 2
char floatStr[7]; int hum, rel;
sscanf(s, "%*s %s %*c %*s %d %*c %*s %d", floatStr, &hum, &rel);

// 3
char floatStr[7]; int hum, rel;
sscanf(s, "Temp %s / Hum %d / Relai %d", floatStr, &hum, &rel);

Perso, je trouve la dernière proposée par hbachetti plus lisible.

Ok OK !! merci a toi,

c super clair !

Avec plaisir :wink: