Retourner un string depuis une classe

Bonjour a tous et merci pour le temps que vous passerez a lire ce post, voir a y répondre.
je débute en C++.
Je cherche a créer une classe qui pourra recevoir un string (longueur de 10 ou 12 char), l'inverser, mémoriser la dernière valeur inversée et pouvoir la retourner a loisir.
voici ce que j'essaye de faire (ca ne compile pas).
le .h

#include <Arduino.h>
#include<iostream>
#include<string>
class string_transfer{
	
public:
std::string ReverseString(std::string s);
private:
std::string str;
};

le cpp

#include "string_transfer.h"
#include <iostream>
#include <algorithm>
#include <iterator>

using namespace std;

string string_transfer::ReverseString(string &s){
    string rev(s.rbegin(), s.rend());
	str=s;
    return rev;
}
string string_transfer::getlaststring(){
	return str;
}	

et enfin le ino

#include <Arduino.h>

#include "string_transfer.h"
string_transfer st;

void setup(){
	Serial.begin(9600);
    String str = "This string shall be reversed";

    Serial.println(str);
    String rev = st.ReverseString(str);
	Serial.println(rev);
}
void loop()
{
}

Le projet final est une lecture de tension 220 sur plusieurs entrees et la selection de relais en fonction de parametres pre-definis. ca fonctionne sans classe mais ca marchera mieux avec (code plus simple et plus lisible). je souhaite simplement pouvoir modifier et sauvegarder le nom de l'entree (string) a l'interieur de la classe.
J'ai egalement essaye avec un char[] mais sans succes.
merci pour votre aide.
Amicalement
Merci pour votre aide.

Ce ne serait pas déjà

:

D'autre part, je vois:
std::string ReverseString(std::string s);
string string_transfer::ReverseString(string &s){
-----------------------------------------------------------------------------^

De plus getlaststring n'est pas défini dans le .h

Une idée à creuser éventuellement - tapé ici, non testé

class MessageInverse
{
  private:
    static const byte maxBufferSize = 20;
    char message[maxBufferSize + 1];

    void inverser(const char *cstr) {
      message[0] = '\0';
      if (cstr) {
        size_t l = strlen(cstr);
        if (l > maxBufferSize) l = maxBufferSize;
        for (size_t i = 0; i < l; i++) message[i] = *(cstr + l - i - 1);
        message[l] = '\0';
      }
    }

  public:
    MessageInverse(const char *cstr) {inverser(cstr);}

    MessageInverse & operator =(const char *cstr) {
      inverser(cstr);
      return *this;
    }
    const char * dernierMessage() {return message;}
};

MessageInverse unMessage("dlroW olleH");

void setup() {
  Serial.begin(115200); Serial.println();
  Serial.println(unMessage.dernierMessage());
  unMessage = "egassem ertua nU";
  Serial.println(unMessage.dernierMessage());
}

void loop() {}

(il faudra définir sans doutes d'autres opérateurs et prendre en compte la règle de 3/5/0)

Écriture étrange. Pourquoi vouloir mixer les string C++ et les String ARDUINO ?
D'une part cela ne compilera que sur ESP32 ou ESP8266, d'autre part cela implique pas mal de conversions avec c_str(), dans un sens comme dans l'autre :

  Serial.begin(9600);
  String str = "This string shall be reversed";

  Serial.println(str);
  string rev = st.ReverseString(str.c_str());
  String rv = rev.c_str();
  Serial.println(rv);

Au vu du code final dans le .ino j'en doute.

Bonjour Vileroi, merci d'avoir pris le temps de me repondre.
je viens d'essayer a nouveau (car j'avais deja essaye ca)

#include <Arduino.h>
#include<iostream>
#include<string>
class string_transfer{
	
public:
String ReverseString(String s);
String getlaststring();
private:
String str;
};

avec des s minuscule, il ne reconnait pas string, avec des majuscules.
Je continue a chercher.

Merci JML,
je n'ai pas reussi a faire fonctionner ton code. J'ai certainement fait une connerie quelque part mais je vais reposer la question autrement...
voice le code que j'utilise pour la librairie de lecture de voltage et de controle de relais
le .h

//Library InOut.h Michel 25/11/21
//the target is to control Input and output 
#ifndef PIN_IN || ndef PIN_OUT
#include <Arduino.h>
//#include "ZMPT101B.h"// lib AC voltage reader
//start
#define ADC_SCALE 1023.0
#define VREF 1.7
#define DEFAULT_FREQUENCY 50
//end
#include <string>
class InOut{
	private:
	byte pinin;
	byte pinout;
	bool state;
	float u;
	const int Mv0=20;
	int prev; //=0;
	int prior; //=0;
	bool activ; //=true;
	int zero; // = 512;
	float sensitivity; // =0.0018;
	uint8_t pin;
	int lastvalue; //=0;
	std::string name;
	public:
	InOut(byte pinin, byte pinout);
	void init();
	void ON();
	void OFF();
	bool Status();
	int GetVolt();
	float calibrate();
	void setZeroPoint(int _zero);
	void setSensitivity(float sens);
	void setPrior(int Prior);
	void setPrev(int Prev);
	void setActiv(bool Activ);
	void setName(std::string _name);
	int getPrior();
	int getPrev();
	bool getActiv();
	float getVoltageDC();
	float getVoltageAC(uint16_t frequency = 50);
    std::string GetName();
};
#endif

le .cpp

#include "InOut.h"
#include <string>
InOut::InOut(byte pinin,byte pinout){
	this->pinin = pinin;
	this->pinout = pinout;
}
void InOut::init(){
	pinMode(pinout,OUTPUT);
	pinMode(pinin,INPUT);
	OFF();
	//Mv0=20;
	prev=0;
	prior=0;
	activ=true;
	zero = 512;
	sensitivity=0.0018;
	lastvalue=0;
	//name=" ";
}
void InOut::ON(){
	digitalWrite(pinout, LOW);
}
void InOut::OFF(){
	digitalWrite(pinout, HIGH);
}
bool InOut::Status(){//return LOW or false if activated and HIGH or true of not activated
	state=digitalRead(pinout);
	return state;
}
int InOut::GetVolt(){
	u=getVoltageAC();
	u=u-10;//security offset, sensor calibrated accordingly
	if(u < Mv0) {
		u=0;
	}
	if(u<lastvalue-2 || u>lastvalue+2) lastvalue=u;
	return int(lastvalue);
}
float InOut::calibrate() {
	uint16_t acc = 0;
	for (int i = 0; i < 10; i++) {
		acc += analogRead(pin);
	}
	zero = acc / 10;
	return zero;
}
void InOut::setZeroPoint(int _zero) {
	zero = _zero;
}
void InOut::setSensitivity(float sens) {
	sensitivity = sens;
}
void InOut::setPrior(int Prior){
	prior=Prior;
}
void InOut::setPrev(int Prev){
	prev=Prev;
}
void InOut::setActiv(bool Activ){
	activ=Activ;
}
void InOut::setName(std::string _name){
	name = _name;
}
int InOut::getPrior(){
	return prior;
}
int InOut::getPrev(){
	return prev;
}
bool InOut::getActiv(){
	return activ;
}
float InOut::getVoltageDC() {
	int16_t acc = 0;
	for (int i = 0; i < 10; i++) {
		acc += analogRead(pin) - zero;
	}
	float V = (float)acc / 10.0 / ADC_SCALE * VREF / sensitivity;
	return V;
}
float InOut::getVoltageAC(uint16_t frequency) {

	uint32_t period = 1000000 / frequency;
	uint32_t t_start = micros();

	uint32_t Vsum = 0, measurements_count = 0;
	int32_t Vnow;

	while (micros() - t_start < period) {
		Vnow = analogRead(pinin) - zero;
		Vsum += Vnow*Vnow;
		measurements_count++;
	}
	float Vrms = sqrt(Vsum / measurements_count) / ADC_SCALE * VREF / sensitivity;
	return Vrms;
}
std::string InOut::GetName(){
	std::string str = name;
	return str;
}

tout fonctionne sauf getname et setname
des que j'essaye de passer un string, ca ne compile pas... je suis la dessus depuis 2 jours, j'ai retourne le web sans succes.
Merci de ton aide.
Amicalement

salut hbachetti et merci pour ta reponse,
ce bout de code a ete recupere et modifie (sans succes) depuis de nombreux exemples repris sur le net. j'essaye un truc puis un autre (tout en essayant mais sans trop comprendre ce que je fais).
l'idee etant d'ajouter la possibilite d'avoir un string modifiable dans une classe.
pour l'instant (si je retire le string) ma classe InOut fonctionne mais j'aimerai pouvoir y ajouter un nom.
Je suis tres loin d'etre un bon programmeur et je ne pretend pas le devenir, j'essaye juste de comprendre et de m'ameliorer.
le premier prototype de ce projet fonctionne deja dans un bateau sans le moindre souci, l'ecran, la carte memoire, le touchscreen, tout fonctioone. simplement, toutes les fonction de lecture, de gestion de relais sont gerees sans classe, donc chaque entree a son propre code, c'est un peu le bordel et, si je dois revenir dessus dans 1 an, je ne vais plus rien comprendre, d'ou l'idee de reecrire en utilisant une classe.
J'ai copie le code original dans mon post precedent, normalement lorsque j'ai un probleme, j'aime le resoudre par moi meme mais la, je ne m'en sors pas.
Merci pour votre aide a tous.

Tout d'abord, répondre à la question. ARDUINO ou ESP ?

Désolé, j'aurai du commence par ca...
Ce projet est developpe sur Aduino Due.

Oui.
Il me semble que la DUE a suffisamment de mémoire pour éviter les problèmes de fragmentation mémoire habituels avec l'AVR et l'utilisation de string ou String.
Je dirais : éviter de mixer string et String.
Ou voir l'implémentation de J-M-L, qui n'utilise ni l'un ni l'autre.

Je n'ai malheureusement pas réussi à intégrer l'implémentation de Jml dans mon InOut (pas encore le niveau) mais je vais essayer à nouveau demain.
Je fais ça sans problème en .net mais la, ça ne compile pas pour une raison que je n'arrive pas à comprendre.
Je vis en Thaïlande et il est un peu tard, je réessayerai demain, si toutefois quelqu'un a un bout d'exemple ou un topic sur ce sujet. Soit en char[] soit en String...
Un truc genre class personnage dont l'un des attributs serait le nom...
Merci encore à tous pour votre aide

Ecrire en C quand le C++ est hors de portée.

il suffit de faire un copier coller et de compiler puis d'ouvrir le moniteur série à 115200 bauds...


sinon pour votre code il suffit de mettre la classe String, un truc comme cela devrait fonctionner

fichier v.h

#ifndef _PIN_
#define _PIN_

#define ADC_SCALE 1023.0
#define VREF 1.7
#define DEFAULT_FREQUENCY 50

class InOut {
  private:
    byte pinin;
    byte pinout;
    bool state;
    float u;
    const int Mv0 = 20;
    int prev; //=0;
    int prior; //=0;
    bool activ; //=true;
    int zero; // = 512;
    float sensitivity; // =0.0018;
    uint8_t pin;
    int lastvalue; //=0;
    String name;
  public:
    InOut(byte pinin, byte pinout);
    ~InOut();
    void init();
    void ON();
    void OFF();
    bool Status();
    int GetVolt();
    float calibrate();
    void setZeroPoint(int _zero);
    void setSensitivity(float sens);
    void setPrior(int Prior);
    void setPrev(int Prev);
    void setActiv(bool Activ);
    void setName(String _name);
    int getPrior();
    int getPrev();
    bool getActiv();
    float getVoltageDC();
    float getVoltageAC(uint16_t frequency = 50);
    String GetName();
};
#endif

fichier v.cpp

#include <Arduino.h>
#include "v.h"

InOut::InOut(byte in, byte out) : pinin(in), pinout(out) {}

InOut::~InOut() {Serial.print("destructor pour "); Serial.println(name);}

void InOut::init() {
  pinMode(pinout, OUTPUT);
  pinMode(pinin, INPUT);
  OFF();
  prev = 0;
  prior = 0;
  activ = true;
  zero = 512;
  sensitivity = 0.0018;
  lastvalue = 0;
  name = "";
}

void InOut::ON() {
  digitalWrite(pinout, LOW);
}

void InOut::OFF() {
  digitalWrite(pinout, HIGH);
}

bool InOut::Status() { //return  false if activated and HIGH or true of not activated
  state = digitalRead(pinout);
  return (state == HIGH) ? true : false;
}

int InOut::GetVolt() {
  u = getVoltageAC();
  u = u - 10; //security offset, sensor calibrated accordingly
  if (u < Mv0) {
    u = 0;
  }
  if (u < lastvalue - 2 || u > lastvalue + 2) lastvalue = u;
  return int(lastvalue);
}
float InOut::calibrate() {
  uint16_t acc = 0;
  for (int i = 0; i < 10; i++) {
    acc += analogRead(pin);
  }
  zero = acc / 10;
  return zero;
}
void InOut::setZeroPoint(int _zero) {
  zero = _zero;
}
void InOut::setSensitivity(float sens) {
  sensitivity = sens;
}
void InOut::setPrior(int Prior) {
  prior = Prior;
}
void InOut::setPrev(int Prev) {
  prev = Prev;
}
void InOut::setActiv(bool Activ) {
  activ = Activ;
}
void InOut::setName(String _name) {
  name = _name;
}
int InOut::getPrior() {
  return prior;
}
int InOut::getPrev() {
  return prev;
}
bool InOut::getActiv() {
  return activ;
}

float InOut::getVoltageDC() {
  int16_t acc = 0;
  for (int i = 0; i < 10; i++) {
    acc += analogRead(pin) - zero;
  }
  float V = (float)acc / 10.0 / ADC_SCALE * VREF / sensitivity;
  return V;
}

float InOut::getVoltageAC(uint16_t frequency) {
  uint32_t period = 1000000 / frequency;
  uint32_t t_start = micros();

  uint32_t Vsum = 0, measurements_count = 0;
  int32_t Vnow;

  while (micros() - t_start < period) {
    Vnow = analogRead(pinin) - zero;
    Vsum += Vnow * Vnow;
    measurements_count++;
  }
  float Vrms = sqrt(Vsum / measurements_count) / ADC_SCALE * VREF / sensitivity;
  return Vrms;
}

String InOut::GetName() {
  return String(name);
}

J'ai rajouté le destructeur pour qu'on puisse voir quand une instance disparait.

fichier .ino principal

#include "v.h"

InOut inoutG(2, 3); // globale
String leNomEst;

void setup() {
  InOut inoutL(4, 5); // locale
  Serial.begin(115200); Serial.println();
  inoutG.init();
  inoutL.init();

  inoutG.setName(String("Globale"));
  inoutL.setName(String("Locale"));

  // on va bien chercher le nom
  leNomEst = inoutG.GetName();
  Serial.print("Le nom obtenu est ["); Serial.print(leNomEst);
  Serial.print("] qui est bien le même que -> ");   Serial.println(inoutG.GetName());
  Serial.println();

  // si on modifie la copie  de la String ça ne change bien sûr pas dans l'instance
  leNomEst = "coucou c'est nous";
  Serial.print("Le nom modifié est ["); Serial.print(leNomEst);
  Serial.print("] qui est différent de "); Serial.println(inoutG.GetName());
  Serial.println();

  // et l'autre instance a bien un autre nom
  Serial.print("L'instance locale s'appelle bien différement -> "); Serial.println(inoutL.GetName());
  Serial.println();

  // et quand le setup va se terminer, le destruceur de inoutL va être appelé
  Serial.println("L'instance locale va disparaître et son destructeur sera appelé. ");
}

void loop() {
  Serial.println();
  Serial.print("L'instance globale existe toujours -> ");   Serial.println(inoutG.GetName());
  while (true) yield();
}

Si vous faites tourner le code et ouvrez la console série à 115200 bauds vous verrez

Le nom obtenu est [Globale] qui est bien le même que -> Globale

Le nom modifié est [coucou c'est nous] qui est différent de Globale

L'instance locale s'appelle bien différement -> Locale

L'instance locale va disparaître et son destructeur sera appelé.
destructor pour Locale

L'instance globale existe toujours -> Globale

ça a l'air de fonctionner, non ?

la fonction membre

String InOut::GetName() {
  return String(name);
}

va retourner une instance nouvelle de la classe String, indépendante de la variable d'instance.

(mais pas super d'utiliser la classe String).

Bonjour JML. Juste parfait... je ne comprends pas comment j'ai pu passer à côté...
Mais bon, ta dernière phrase m'inquiète un peu. La classe sring est à éviter partout où juste dans les classes?
Ce projet est semi professionnel et j'ai besoin de fiabilité.
Si c'est partout, je vais devoir ré-écrire certaines parties du code (pas de problème à priori)
Concernant la classe je vais essayer de virer les string et d'utiliser char[].

Je ne sais pas du tout comment faire un return char[]

Si tu peux m'aider sur ce point...
En attendant, je vais essayer de comprendre le code que tu as mis dans ton premier post.
Un grand merci pour ton aide.

Salut Jml, salut tout le monde,
bon j'ai avance un peu mais j'ai encore un leger probleme.
voici ce que j'obtien en sortie apres avoir remplace le string par char[]

Le nom obtenu est [lobale   ] qui est bien le même que -> Globale   

Le nom modifié est [[lobale   ] qui est différent de Globale   

L'instance locale s'appelle bien différement -> Locale

L'instance locale va disparaître et son destructeur sera appelé. 
destructor pour Locale

L'instance globale existe toujours -> Globale   

voici le code modifie
vm.h

#ifndef _PIN_
#define _PIN_

#define ADC_SCALE 1023.0
#define VREF 1.7
#define DEFAULT_FREQUENCY 50

class InOut {
  private:
    byte pinin;
    byte pinout;
    bool state;
    float u;
    const int Mv0 = 20;
    int prev; //=0;
    int prior; //=0;
    bool activ; //=true;
    int zero; // = 512;
    float sensitivity; // =0.0018;
    uint8_t pin;
    int lastvalue; //=0;
	static const byte maxBufferSize = 10;
    char lname[maxBufferSize + 1];
    //String name;
  public:
    InOut(byte pinin, byte pinout);
    ~InOut();
    void init();
    void ON();
    void OFF();
    bool Status();
    int GetVolt();
    float calibrate();
    void setZeroPoint(int _zero);
    void setSensitivity(float sens);
    void setPrior(int Prior);
    void setPrev(int Prev);
    void setActiv(bool Activ);
	void setName(const char *cstr);
    //void setName(String _name);
    int getPrior();
    int getPrev();
    bool getActiv();
    float getVoltageDC();
    float getVoltageAC(uint16_t frequency = 50);
	const char * getName();
    //String GetName();
};
#endif

vm.cpp

#include <Arduino.h>
#include "vm.h"

InOut::InOut(byte in, byte out) : pinin(in), pinout(out) {}

InOut::~InOut() {Serial.print("destructor pour "); Serial.println(lname);}

void InOut::init() {
  pinMode(pinout, OUTPUT);
  pinMode(pinin, INPUT);
  OFF();
  prev = 0;
  prior = 0;
  activ = true;
  zero = 512;
  sensitivity = 0.0018;
  lastvalue = 0;
  for(int i = 0 ; i<10 ; i++)lname[i] = '/0';
}

void InOut::ON() {
  digitalWrite(pinout, LOW);
}

void InOut::OFF() {
  digitalWrite(pinout, HIGH);
}

bool InOut::Status() { //return  false if activated and HIGH or true of not activated
  state = digitalRead(pinout);
  return (state == HIGH) ? true : false;
}

int InOut::GetVolt() {
  u = getVoltageAC();
  u = u - 10; //security offset, sensor calibrated accordingly
  if (u < Mv0) {
    u = 0;
  }
  if (u < lastvalue - 2 || u > lastvalue + 2) lastvalue = u;
  return int(lastvalue);
}
float InOut::calibrate() {
  uint16_t acc = 0;
  for (int i = 0; i < 10; i++) {
    acc += analogRead(pin);
  }
  zero = acc / 10;
  return zero;
}
void InOut::setZeroPoint(int _zero) {
  zero = _zero;
}
void InOut::setSensitivity(float sens) {
  sensitivity = sens;
}
void InOut::setPrior(int Prior) {
  prior = Prior;
}
void InOut::setPrev(int Prev) {
  prev = Prev;
}
void InOut::setActiv(bool Activ) {
  activ = Activ;
}
/*void InOut::setName(String _name) {
  name = _name;
}*/
void InOut::setName(const char *cstr){
	  //lname[0] = '\0';
      if (cstr) {//if chain not empty
        size_t l = strlen(cstr);//l is a pointer and contain the size of cstr
        if (l > maxBufferSize) l = maxBufferSize;//define maxbuffersize (only if > ??)
        for (size_t i = 0; i < l; i++) lname[i] = *(cstr + i );//transfer of cstrin the var name
        lname[l] = '\0';//set the first character
      }
}
int InOut::getPrior() {
  return prior;
}
int InOut::getPrev() {
  return prev;
}
bool InOut::getActiv() {
  return activ;
}

float InOut::getVoltageDC() {
  int16_t acc = 0;
  for (int i = 0; i < 10; i++) {
    acc += analogRead(pin) - zero;
  }
  float V = (float)acc / 10.0 / ADC_SCALE * VREF / sensitivity;
  return V;
}

float InOut::getVoltageAC(uint16_t frequency) {
  uint32_t period = 1000000 / frequency;
  uint32_t t_start = micros();

  uint32_t Vsum = 0, measurements_count = 0;
  int32_t Vnow;

  while (micros() - t_start < period) {
    Vnow = analogRead(pinin) - zero;
    Vsum += Vnow * Vnow;
    measurements_count++;
  }
  float Vrms = sqrt(Vsum / measurements_count) / ADC_SCALE * VREF / sensitivity;
  return Vrms;
}
const char * InOut::getName(){
	return lname;
}

le .ino

#include "vm.h"

InOut inoutG(2, 3); // globale
char leNomEst[]=("Globale   ");

void setup() {
  InOut inoutL(4, 5); // locale
  Serial.begin(115200); Serial.println();
  inoutG.init();
  inoutL.init();

  inoutG.setName(leNomEst);
  inoutL.setName("Locale");

  // on va bien chercher le nom
  *(leNomEst) = inoutG.getName();
  Serial.print("Le nom obtenu est ["); Serial.print(leNomEst);
  Serial.print("] qui est bien le même que -> ");   Serial.println(inoutG.getName());
  Serial.println();

  // si on modifie la copie  de la String ça ne change bien sûr pas dans l'instance
  *(leNomEst) = "coucou    ";
  Serial.print("Le nom modifié est ["); Serial.print(leNomEst);
  Serial.print("] qui est différent de "); Serial.println(inoutG.getName());
  Serial.println();

  // et l'autre instance a bien un autre nom
  Serial.print("L'instance locale s'appelle bien différement -> "); Serial.println(inoutL.getName());
  Serial.println();

  // et quand le setup va se terminer, le destruceur de inoutL va être appelé
  Serial.println("L'instance locale va disparaître et son destructeur sera appelé. ");
}

void loop() {
  Serial.println();
  Serial.print("L'instance globale existe toujours -> ");   Serial.println(inoutG.getName());
  while (true) yield();
}

Je cherche toujours a comprendre ou je perd cette premiere lettre...

Je te souhaite un excellent weekend
Merci encore pour ton aide...

attention c'est un '\0' qu'il faut mettre
vous devriez regarder les warning du compilateur

A mon avis String est à éviter partout, mais dans une moindre mesure sur une DUE, car elle dispose de plus de RAM que l'ATMEGA328. Mais quand on utilise une DUE c'est que l'on a besoin de mémoire, donc on va forcément en utiliser une bonne partie. Le tas sera réduit et les risques élevés.

L'inversion d'une chaîne existe en PHP existe, mais aussi en C. Il suffit de fouiller un peu. Cela s'appelle strrev() :
https://android.googlesource.com/kernel/lk/+/qcom-dima-8x74-fixes/lib/libc/string/strrev.c
remplacer unsigned char *str par char *str.

#define MAX_SIZE    200

void setup()
{
  Serial.begin(115200);
  char str[MAX_SIZE] = "0123456789";
  char buf[MAX_SIZE];
  Serial.println();
  // copie
  strncpy(buf, str, MAX_SIZE);
  buf[MAX_SIZE-1] = '\0';
  strrev(buf);
  Serial.println(str);
  Serial.println(buf);
}

Après, l'utiliser dans une classe si ça te chante ne devrait pas être insurmontable ...

Re, Je crois que je l'ai... :slight_smile:
je viens du .net, on utilise rarement les char. j'ai lu, appris et je pense partiellement compris mes erreurs. Voici le nouveau code. ca fonctionne, je souhaite juste savoir si c'est "correct"
vm.h

#ifndef _PIN_
#define _PIN_

#define ADC_SCALE 1023.0
#define VREF 1.7
#define DEFAULT_FREQUENCY 50

class InOut {
  private:
    byte pinin;
    byte pinout;
    bool state;
    float u;
    const int Mv0 = 20;
    int prev; //=0;
    int prior; //=0;
    bool activ; //=true;
    int zero; // = 512;
    float sensitivity; // =0.0018;
    uint8_t pin;
    int lastvalue; //=0;
	static const byte maxBufferSize = 10;
    char lname[maxBufferSize + 1];
    //String name;
  public:
    InOut(byte pinin, byte pinout);
    ~InOut();
    void init();
    void ON();
    void OFF();
    bool Status();
    int GetVolt();
    float calibrate();
    void setZeroPoint(int _zero);
    void setSensitivity(float sens);
    void setPrior(int Prior);
    void setPrev(int Prev);
    void setActiv(bool Activ);
	void setName(const char *cstr);
    //void setName(String _name);
    int getPrior();
    int getPrev();
    bool getActiv();
    float getVoltageDC();
    float getVoltageAC(uint16_t frequency = 50);
	const char * getName();
    //String GetName();
};
#endif

vm.cpp

#include <Arduino.h>
#include "vm.h"

InOut::InOut(byte in, byte out) : pinin(in), pinout(out) {}

InOut::~InOut() {Serial.print("destructor pour "); Serial.println(lname);}

void InOut::init() {
  pinMode(pinout, OUTPUT);
  pinMode(pinin, INPUT);
  OFF();
  prev = 0;
  prior = 0;
  activ = true;
  zero = 512;
  sensitivity = 0.0018;
  lastvalue = 0;
  for(int i = 0 ; i<10 ; i++)lname[i] = '/0'; lname[11]='/0';
}

void InOut::ON() {
  digitalWrite(pinout, LOW);
}

void InOut::OFF() {
  digitalWrite(pinout, HIGH);
}

bool InOut::Status() { //return  false if activated and HIGH or true of not activated
  state = digitalRead(pinout);
  return (state == HIGH) ? true : false;
}

int InOut::GetVolt() {
  u = getVoltageAC();
  u = u - 10; //security offset, sensor calibrated accordingly
  if (u < Mv0) {
    u = 0;
  }
  if (u < lastvalue - 2 || u > lastvalue + 2) lastvalue = u;
  return int(lastvalue);
}
float InOut::calibrate() {
  uint16_t acc = 0;
  for (int i = 0; i < 10; i++) {
    acc += analogRead(pin);
  }
  zero = acc / 10;
  return zero;
}
void InOut::setZeroPoint(int _zero) {
  zero = _zero;
}
void InOut::setSensitivity(float sens) {
  sensitivity = sens;
}

et le .ino

#include "vm.h"

InOut inoutG(2, 3); // globale
char nm[]=("Globale   ");

void setup() {
  InOut inoutL(4, 5); // locale
  Serial.begin(115200); Serial.println();
  inoutG.init();
  inoutL.init();

  inoutG.setName(nm);
  inoutL.setName("Locale");

  // on va bien chercher le nom
  Serial.print("Le nom initial est ["); Serial.print(nm); Serial.println("]");
  Serial.print("Le nom dans la variable en acces direct est ["); Serial.print(inoutG.getName());Serial.println("]");
  //*(nm) = inoutG.getName();
  strcpy(nm,inoutG.getName());
  Serial.print("Le nom obtenu est ["); Serial.print(nm);
  Serial.print("] qui est bien le même que -> ");   Serial.println(inoutG.getName());
  Serial.println();

  // si on modifie la copie  de la String ça ne change bien sûr pas dans l'instance
  //*(leNomEst) = ("coucou    ");
  strcpy(nm , "coucou");
  Serial.print("Le nom modifié est ["); Serial.print(nm);
  Serial.print("] qui est différent de "); Serial.println(inoutG.getName());
  Serial.println();

  // et l'autre instance a bien un autre nom
  Serial.print("L'instance locale s'appelle bien différement -> "); Serial.println(inoutL.getName());
  Serial.println();

  // et quand le setup va se terminer, le destruceur de inoutL va être appelé
  Serial.println("L'instance locale va disparaître et son destructeur sera appelé. ");
}

void loop() {
  Serial.println();
  Serial.print("L'instance globale existe toujours -> ");   Serial.println(inoutG.getName());
  while (true) yield();
}

Je te remercie sincèrement, j'ai appris plein de trucs, destructeurs de classes, utilisation des char, eviter les string (sauf avec ma copine), si tu as un contact pro, fais passer, le projet est implante mais non termine...

corrige :slight_smile:

oui il faut faire des strcpy - ou encore mieux des strncpy()

voilà une modif qui devrait compiler sans warning

le .ino

#include "vm.h"

InOut inoutG(2, 3); // globale
char leNomEst[maxBufferSize + 1] = "Globale";

void setup() {
  InOut inoutL(4, 5); // locale
  Serial.begin(115200); Serial.println();
  inoutG.init();
  inoutL.init();

  inoutG.setName(leNomEst);
  inoutL.setName("Locale");

  // on va bien chercher le nom
  strncpy(leNomEst, inoutG.getName(), maxBufferSize);

  Serial.print("Le nom obtenu est ["); Serial.print(leNomEst);
  Serial.print("] qui est bien le même que -> ");   Serial.println(inoutG.getName());
  Serial.println();

  // si on modifie la copie  de la String ça ne change bien sûr pas dans l'instance
  strncpy(leNomEst, "coucou", maxBufferSize);
  Serial.print("Le nom modifié est ["); Serial.print(leNomEst);
  Serial.print("] qui est différent de "); Serial.println(inoutG.getName());
  Serial.println();

  // et l'autre instance a bien un autre nom
  Serial.print("L'instance locale s'appelle bien différement -> "); Serial.println(inoutL.getName());
  Serial.println();

  // et quand le setup va se terminer, le destruceur de inoutL va être appelé
  Serial.println("L'instance locale va disparaître et son destructeur sera appelé. ");
}

void loop() {
  Serial.println();
  Serial.print("L'instance globale existe toujours -> ");   Serial.println(inoutG.getName());
  while (true) yield();
}

le .cpp

#include <Arduino.h>
#include "vm.h"

InOut::InOut(byte in, byte out) : pinin(in), pinout(out) {}

InOut::~InOut() {
  Serial.print("destructor pour ");
  Serial.println(lname);
}

void InOut::init() {
  pinMode(pinout, OUTPUT);
  pinMode(pinin, INPUT);
  OFF();
  prev = 0;
  prior = 0;
  activ = true;
  zero = 512;
  sensitivity = 0.0018;
  lastvalue = 0;
  lname[0] = '\0'; // empty cString
  lname[maxBufferSize] = '\0'; // make sure the last byte will always be null
}

void InOut::ON() {
  digitalWrite(pinout, LOW);
}

void InOut::OFF() {
  digitalWrite(pinout, HIGH);
}

bool InOut::Status() { //return  false if activated and HIGH or true of not activated
  state = digitalRead(pinout);
  return (state == HIGH) ? true : false;
}

int InOut::GetVolt() {
  u = getVoltageAC();
  u = u - 10; //security offset, sensor calibrated accordingly
  if (u < Mv0) {
    u = 0;
  }
  if (u < lastvalue - 2 || u > lastvalue + 2) lastvalue = u;
  return int(lastvalue);
}
float InOut::calibrate() {
  uint16_t acc = 0;
  for (int i = 0; i < 10; i++) {
    acc += analogRead(pin);
  }
  zero = acc / 10;
  return zero;
}
void InOut::setZeroPoint(int _zero) {
  zero = _zero;
}
void InOut::setSensitivity(float sens) {
  sensitivity = sens;
}
void InOut::setPrior(int Prior) {
  prior = Prior;
}
void InOut::setPrev(int Prev) {
  prev = Prev;
}
void InOut::setActiv(bool Activ) {
  activ = Activ;
}
/*void InOut::setName(String _name) {
  name = _name;
  }*/
void InOut::setName(const char *cstr) {
  if (cstr) {//if chain not empty
    size_t l = strlen(cstr);  //l is a pointer and contain the size of cstr
    if (l > maxBufferSize) l = maxBufferSize;//define maxbuffersize (only if > ??)
    strncpy(lname, cstr, l);
    lname[l] = '\0';  //
  }
}
int InOut::getPrior() {
  return prior;
}
int InOut::getPrev() {
  return prev;
}
bool InOut::getActiv() {
  return activ;
}

float InOut::getVoltageDC() {
  int16_t acc = 0;
  for (int i = 0; i < 10; i++) {
    acc += analogRead(pin) - zero;
  }
  float V = (float)acc / 10.0 / ADC_SCALE * VREF / sensitivity;
  return V;
}

float InOut::getVoltageAC(uint16_t frequency) {
  uint32_t period = 1000000 / frequency;
  uint32_t t_start = micros();

  uint32_t Vsum = 0, measurements_count = 0;
  int32_t Vnow;

  while (micros() - t_start < period) {
    Vnow = analogRead(pinin) - zero;
    Vsum += Vnow * Vnow;
    measurements_count++;
  }
  float Vrms = sqrt(Vsum / measurements_count) / ADC_SCALE * VREF / sensitivity;
  return Vrms;
}
const char * InOut::getName() {
  return lname;
}

le .h

#ifndef _PIN_
#define _PIN_

#define ADC_SCALE 1023.0
#define VREF 1.7
#define DEFAULT_FREQUENCY 50

const byte maxBufferSize = 10;

class InOut {
  private:
    byte pinin;
    byte pinout;
    bool state;
    float u;
    const int Mv0 = 20;
    int prev; //=0;
    int prior; //=0;
    bool activ; //=true;
    int zero; // = 512;
    float sensitivity; // =0.0018;
    uint8_t pin;
    int lastvalue; //=0;
    char lname[maxBufferSize + 1];
    //String name;
  public:
    InOut(byte pinin, byte pinout);
    ~InOut();
    void init();
    void ON();
    void OFF();
    bool Status();
    int GetVolt();
    float calibrate();
    void setZeroPoint(int _zero);
    void setSensitivity(float sens);
    void setPrior(int Prior);
    void setPrev(int Prev);
    void setActiv(bool Activ);
    void setName(const char *cstr);
    //void setName(String _name);
    int getPrior();
    int getPrev();
    bool getActiv();
    float getVoltageDC();
    float getVoltageAC(uint16_t frequency = 50);
    const char * getName();
    //String GetName();
};
#endif

vous remarquerez que j'ai rendu dispo maxBufferSize pour que vous puissiez dimensionner correctement le buffer dans le .ino et utiliser aussi cette longueur max comme paramètre de strncpy()

PS: je n'ai pas testé... :slight_smile: donc à vérifier