IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

Arduino Discussion :

Encore une question avec char et String


Sujet :

Arduino

  1. #1
    Membre habitué
    Homme Profil pro
    bricoleur
    Inscrit en
    Octobre 2014
    Messages
    293
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Oise (Picardie)

    Informations professionnelles :
    Activité : bricoleur
    Secteur : Alimentation

    Informations forums :
    Inscription : Octobre 2014
    Messages : 293
    Points : 145
    Points
    145
    Par défaut Encore une question avec char et String
    Bonjour le Forum,
    je replonge dans les questions mainte fois éculées des char et String.
    Je défini deux pointeurs de type char ainsi:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    const char* nomJour[] = {"Dim", "Lun", "Mar", "Mer", "Jeu", "Ven", "Sam"};
    const char* nomMois[] = {"janv.", "fevr.", "mars", "avril", "mai", "juin", "juil.", "aout", "sept.", "oct.", "nov.", "dec."};
    Je veux ensuite créer un String pour pouvoir afficher sur un écran:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    String jourDtr(){
      return (nomJour[dtg.nJour] + " " + String(dtr.dJour) + " " + nomMois[dtr.nMois] + " " + String(dtr.annee));
    }
    La compilation plante avec le message suivant:
    invalid operands of types 'const char*' and 'const char [2]' to binary 'operator+'
    J'ai trouvé une solution en faisant ceci:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    String jourDtr(){
      String nJ = nomJour[dtg.nJour];
      return (nJ + " " + String(dtr.dJour) + " " + nomMois[dtr.nMois] + " " + String(dtr.annee));
    }
    Si quelqu'un pouvait m'expliquer le pourquoi du plantage de la compile et s'il y a une solution plus élégante que la mienne?
    Merci
    Michel

  2. #2
    Expert confirmé

    Homme Profil pro
    mad scientist :)
    Inscrit en
    Septembre 2019
    Messages
    2 711
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : mad scientist :)

    Informations forums :
    Inscription : Septembre 2019
    Messages : 2 711
    Points : 5 390
    Points
    5 390
    Par défaut
    Pourquoi ne pas afficher simplement par petits bouts sans construire la String… c’est juste du gâchis de mémoire….

    Sinon il faut sans doute transformer vos cString en String pour faire la concaténation
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    String(nomJour[dtg.nJour]) + String(" ") + String(dtr.dJour) + String(" ") + String(nomMois[dtr.nMois]) + String(" ") + String(dtr.annee)
    (Il y a des chances que ça fonctionne si juste le premier élément de la concaténation est une String car l’opérateur addition qui sera appelé sera celui surchargé de la classe String)

  3. #3
    Membre émérite
    Avatar de jpbbricole
    Homme Profil pro
    Retraité des réseaux informatiques
    Inscrit en
    Février 2013
    Messages
    1 012
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Suisse

    Informations professionnelles :
    Activité : Retraité des réseaux informatiques
    Secteur : High Tech - Électronique et micro-électronique

    Informations forums :
    Inscription : Février 2013
    Messages : 1 012
    Points : 2 341
    Points
    2 341
    Par défaut
    Bonsoir mormic

    Travailles tu avec une RTC, si oui, la quelle?
    Pour tes problèmes de String et l'erreur de compilation, tu peux remplacer const char* par const String, ou dans ta concaténation tu fait précéder tes variables de type char* en tableau par (String)nomJour[dtg.nJour]

    Je n'ai pas essayé mais il ma semble que j'avais fait ainsi.

    Cordialement
    jpbbricole
    L'expérience est la seule chose qu'il ne faut acheter que d'occasion!

  4. #4
    Membre habitué
    Homme Profil pro
    bricoleur
    Inscrit en
    Octobre 2014
    Messages
    293
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Oise (Picardie)

    Informations professionnelles :
    Activité : bricoleur
    Secteur : Alimentation

    Informations forums :
    Inscription : Octobre 2014
    Messages : 293
    Points : 145
    Points
    145
    Par défaut
    Bonsoir Messieurs

    merci jpbbricole pour ta solution qui doit être un cast si je ne me trompe pas et qui fonctionne parfaitement.
    Je vais ton utiliser cette méthode.
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    String jourDtr(){
      return ((String)nomJour[dtg.nJour]+ " " + String(dtr.dJour) + " " + nomMois[dtr.nMois] + " " + String(dtr.annee));
    }
    oui j'utilise un RTC, un DS1307.

    merci Jay M pour ta réponse. En fait je construis ce String car je l'utilise à plusieurs endroits dans mon prog et j'ai pensé judicieux je le faire ainsi.
    Sinon je n'ai pas compris pourquoi les String(" ").

    Merci encore

  5. #5
    Membre émérite
    Avatar de jpbbricole
    Homme Profil pro
    Retraité des réseaux informatiques
    Inscrit en
    Février 2013
    Messages
    1 012
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Suisse

    Informations professionnelles :
    Activité : Retraité des réseaux informatiques
    Secteur : High Tech - Électronique et micro-électronique

    Informations forums :
    Inscription : Février 2013
    Messages : 1 012
    Points : 2 341
    Points
    2 341
    Par défaut
    Bonsoir mormic

    As-tu aussi essayé avec timestamp?
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
     
    DateTime now = rtc.now();
    String timeStampFull = now.timestamp(DateTime::TIMESTAMP_FULL);
    String timeStampDate = now.timestamp(DateTime::TIMESTAMP_DATE);
    String timeStampTime = now.timestamp(DateTime::TIMESTAMP_TIME);
    Bonne soirée
    Cordialement
    jpbbricole
    L'expérience est la seule chose qu'il ne faut acheter que d'occasion!

  6. #6
    Expert confirmé

    Homme Profil pro
    mad scientist :)
    Inscrit en
    Septembre 2019
    Messages
    2 711
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : mad scientist :)

    Informations forums :
    Inscription : Septembre 2019
    Messages : 2 711
    Points : 5 390
    Points
    5 390
    Par défaut
    Citation Envoyé par mormic Voir le message
    .
    Sinon je n'ai pas compris pourquoi les String(" ").
    C’était juste pour l’homogénéité de l’expression.
    Attention à ces usages de la classe String (concaténation et création dynamique), vous risquez un morcellement de la mémoire suivant ce que vous faites et ça pourrait faire un crash à terme

  7. #7
    Membre habitué
    Homme Profil pro
    bricoleur
    Inscrit en
    Octobre 2014
    Messages
    293
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Oise (Picardie)

    Informations professionnelles :
    Activité : bricoleur
    Secteur : Alimentation

    Informations forums :
    Inscription : Octobre 2014
    Messages : 293
    Points : 145
    Points
    145
    Par défaut
    Bonjour jpbbricole

    Non je n'ai pas essayé timeStamp. Je le ferai dans un prochain projet car pour l'instant je suis très avancé sur celui-là. De plus, une structure équivalente me permet de stocker les infos lus d'un module GPS (date, time, lat, etc) et je crains qu'en modifiant un truc cela chamboule tout.

    Bonjour Jay M
    Attention à ces usages de la classe String (concaténation et création dynamique), vous risquez un morcellement de la mémoire suivant ce que vous faites et ça pourrait faire un crash à terme
    Je comprends que la classe String n'a pas bonne presse dans le milieu des programmeurs. Mais qu'est-ce que ça facilite les choses surtout pour quelqu'un comme moi qui vient de Visual Basic.
    j'admets que l'utilisation de String n'est pas bon pour la mémoire mais comment faire simplement ce que j'ai besoin avec une solution dans les règles de l'art?

    Quoiqu'il en soit, je vous remercie énormément pour l'aide précieuse que vous apportez aux abonnés de ce forum.
    Cordialement
    Michel

  8. #8
    Expert confirmé

    Homme Profil pro
    mad scientist :)
    Inscrit en
    Septembre 2019
    Messages
    2 711
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : mad scientist :)

    Informations forums :
    Inscription : Septembre 2019
    Messages : 2 711
    Points : 5 390
    Points
    5 390
    Par défaut
    Citation Envoyé par mormic Voir le message
    Je comprends que la classe String n'a pas bonne presse dans le milieu des programmeurs. Mais qu'est-ce que ça facilite les choses surtout pour quelqu'un comme moi qui vient de Visual Basic.
    j'admets que l'utilisation de String n'est pas bon pour la mémoire mais comment faire simplement ce que j'ai besoin avec une solution dans les règles de l'art?l
    Elle n'a pas bonne presse parce que de nombreux débutants ne comprennent pas les besoins en mémoire liés à cette classe et sur un petit UNO la mémoire vient vite à manquer... ça crée ensuite des planages qui semblent aléatoires ou des comportements erratiques car des opérations sur une String ne vont plus être effectuées par la classe par manque de mémoire - mais sans vous le dire bien sûr...

    Une solution pour limiter les risques:
    - ne pas faire de String dynamique autant que faire se peut
    - pré-allouer l'espace pour les chaînes avec reserve()
    - banir la concaténation avec des + à rallonges, procéder ligne par ligne
    - ne pas passer ni retourner de String avec des fonctions (utiliser des références ou variables globales)

    Sinon pour éviter la classe String,

    Gourmand en mémoire mais assez simple, on peut utiliser snprintf() qui permet de définir à quoi ressemble la chaîne résultat et là où on veut insérer le contenu de variables.
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
     
    const char* nomJour[] = {"Dim", "Lun", "Mar", "Mer", "Jeu", "Vendredi", "Sam"};
    const char* nomMois[] = {"janv.", "fevr.", "mars", "avril", "mai", "juin", "juil.", "aout", "Septembre.", "oct.", "nov.", "dec."};
    int jourNb = 17;
    int anneeNb = 2021;
    char buffer[50];
    snprintf(buffer, 50, "Nous sommes le %s %d %s %d", nomJour[5], jourNb, nomMois[8], anneeNb); // "Nous sommes le Vendredi 17 Septembre 2021"

    Si on veut faire plus économe en mémoire il faut travailler avec les foncions des bibliothèques standard du monde du C : stdlib et cstring

    https://www.cplusplus.com/reference/cstdlib/
    https://www.cplusplus.com/reference/cstring/

  9. #9
    Membre habitué
    Homme Profil pro
    bricoleur
    Inscrit en
    Octobre 2014
    Messages
    293
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Oise (Picardie)

    Informations professionnelles :
    Activité : bricoleur
    Secteur : Alimentation

    Informations forums :
    Inscription : Octobre 2014
    Messages : 293
    Points : 145
    Points
    145
    Par défaut
    bonjour Jay M

    Juste une nouvelle question: comment je dois-je typer une fonction avec un snprintf ? Là où je mettais String nomFonction(){........}

  10. #10
    Expert confirmé

    Homme Profil pro
    mad scientist :)
    Inscrit en
    Septembre 2019
    Messages
    2 711
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : mad scientist :)

    Informations forums :
    Inscription : Septembre 2019
    Messages : 2 711
    Points : 5 390
    Points
    5 390
    Par défaut
    Salut

    Le plus simple c’est d’avoir un buffer global et la fonction met à jour le buffer global.

    La fonction peut donc retourner rien (void) ou alors vous déclarez le buffer en static dans la fonction (pour qu’il soit permanent) et vous retournez un char* qui sera le pointeur sur le buffer.

    Bien sûr ça veut dire que la fonction n’est pas réentrante si vous l’appelez à nouveau ça modifie le buffer

Discussions similaires

  1. Encore une question sur les Sous-Forums
    Par Swoög dans le forum Evolutions du club
    Réponses: 12
    Dernier message: 27/05/2006, 02h17
  2. Encore une question sur les ListBox !!
    Par SebRs dans le forum Windows
    Réponses: 3
    Dernier message: 09/05/2006, 15h29
  3. Encore une question, pour retrouver 2 valeur d'une table
    Par danje dans le forum Langage SQL
    Réponses: 5
    Dernier message: 15/09/2005, 00h11
  4. Encore une question licence
    Par Neilos dans le forum C++Builder
    Réponses: 4
    Dernier message: 27/01/2005, 09h48
  5. Encore une question sur malloc
    Par IG88 dans le forum C
    Réponses: 5
    Dernier message: 23/06/2004, 15h35

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo