je suis en train de me faire des nœuds au cerveau, à croire qu'apprendre le C++ est trop compliqué pour mon âge (j'ai appris mes premiers rudiments de prog. avec le pascal... il y a plus de 30 ans puis delphi et lazarus. Dur dur la transition</ma vie>)
Bref, je n'arrive pas à trouver et comprendre la structure d'une fonction qui permette de retourner un tableau de caractères... J'ai cru comprendre que les Strings étaient à éviter (sans vraiment comprendre pourquoi) et que la fonction devait retourner un pointeur (charabia pour un pascalien de mon faible niveau)... Bref je coule.
Pour le contexte, il s'agit de formater une valeur (nombre + unité) pour l'afficher ensuite sur un LCD
Pas de soucis, si tu sais faire du pascal, il y a aucune raison que tu n'arrive pas à faire du c++
tu dois avoir plusieurs façon de l'écrire, mais un tableau de caractère(char) pour une fonction, s'écrit sous forme d'un pointeur de tableau de caractère.
c'est à dire l'adresse du premier octet de ton tableau de caractère.
Attention, cela peut marcher car la fonction retourne l'adresse d'une chaîne constante.
Mais dans la demande il est précisé que la fonction formate une chaîne de caractères.
Ceci serait mieux :
dans le triturage de chaîne j'aimerai remplacer le point décimal . par la virgule francophone , mais result.replace('.',','); m'envoie paitre à la compilation (request for member ‘replace’ in ‘result’, which is of non-class type ‘char [15]’)
C'est important pour une utilisation pédagogique (je casse les pieds à mes élèves pour ça, il me faut être un peu cohérent
Oui, mon exemple correspond uniquement au type renvoyé par la fonction, dans son cas, il ne faut pas renvoyer un pointeur sur une variable qui aurait était alloué dans la fonction sans le mot clé static, qui empêche sa destruction à la sortie de la fonction.
Une alternative serait de faire une allocation mémoire si plusieurs valeur de result peuvent exister en même temps.
Dans ce cas il faudrait gérer la libération de la mémoire, lorsque les différentes instances ne sont plus utils.
Pas sûre d'être très claire
Oui tout à fait, mais l'utilisation de la même variable "static" dans plusieurs appel successif de la fonction peut engendrer des effets indésirables.
Du coup je ne suis pas sûre que ce soit bien de conseiller de passer par une variable static, qui est retourner par une fonction.
En tout cas moi cela me gêne, même si c'est bien moins compliqué que la gestion d'allocation mémoire.
Il n'y a pas d'obligation d'allouer dynamiquement.
Une fonction peut très bien recevoir un pointeur sur la chaîne destinatrice, avec de préférence la taille. Dans ce cas c'est l'appelant qui se débrouille pour fournir la chaîne et la longueur.
Oui tout à fait, il y a plusieurs alternative, l'allocation dynamique en est qu'une parmi d'autre.
Mais comme c'est moche, ce n'est pas ce qui me viens en premier en tête
et du coup on change beaucoup le prototypage de la fonction.
Je veux bien à l'occasion me pencher sur les subtilités mais comme remarqué par hbachetti, quelle est la solution conseillée aux débutants ?
Juste pour ne pas faire d'erreur grossières :
la mémoire allouée par static dans la fonction est détruite à la sortie de la fonction... ---> c'est bon, pas besoin de s'en soucier.
l'utilisation de la même variable "static" dans plusieurs appel successif de la fonction peut engendrer des effets indésirables. ---> ce sera le cas : potentiellement plusieurs 100aines de fois durant l'acquisition des mesures. Quels sont les effets indésirables ?
Malheureusement la vrai bonne réponse est comme toujours une réponse peu apprécié des débutants, ca dépend de ce que tu fais
la mémoire allouer automatiquement dans une fonction est détruite à la sortie de la fonction, d'un coté sa simplifie l'utilisation, de l'autre cela empêche de l'utiliser en dehors de la fonction.
L'utilisation de la variable static n'est pas gênante si tu l'utilise 100 ou 1000 fois.
Elle peut être gênante si tu te sers de cette variable pour stocker plusieurs informations différentes en simultanée, car le deuxième appel à cet fonction écrasera les données contenue dans la variable.
Si tu utilise séquentiellement l'information contenue dans la variable, il n'y aura aucun problème.
Si tu as besoin d'appeler plusieurs fois la fonction et d'utiliser les différents contenus en même temps, il vaut mieux créer plusieurs variables et de donner un pointeur sur chacune des variables, comme l'a indiqué @hbachetti
Après d'un point de vue personnel, je ne trouve pas forcément plus compliqué à appréhender de faire l'allocation dynamique dans la fonction et de libérer la mémoire lorsque l'on a fini de l'utiliser.
Mais je fais confiance à @hbachetti
Dans mon domaine (pas arduino donc) j'abuse largement de ce genre de réponse (avec « ça dépend » et « c'est pas simple ») donc pas de souci, je comprends
Il s'agit de l'utiliser (enfin les utiliser : il risque d'en avoir plusieurs un peu différentes) pour cibler le rafraichissement d'une partie seulement d'un afficheur LCD (en lien avec ma question précédente)
Je vais m'inspirer du code de @hbachetti dès que j'en ai le temps...
Ce qu'il ne faut surtout pas faire, dans une fonction C ou C++, c'est renvoyer (par return) une information qui a été créée sur la pile par la fonction. En effet, au sortir de la fonction, la pile est détruite. Exemple à ne pas faire:
char* formater_texte ( int valeur ) {
char tab[16]; // créé sur la pile
sprint ( tab, "%d", valeur); // remplir tab
return tab; // ERREUR: le contenu de tab sera détruit au sortir de la fonction
}
@terwal dit "la mémoire allouée automatiquement dans une fonction est détruite à la sortie de la fonction", ce n'est pas exact. En cas d'allocation dynamique (par char* tab = new char[16]), on peut renvoyer le pointeur tab, c'est ok. @terwal veut parler d'allocation d'un tableau sur la pile (il dit "automatiquement")
Dans ton cas, je pense que tu vas utiliser le résultat immédiatement, pour l'afficher. Donc cela n'est pas gênant si le résultat (la chaîne static) est écrasé au prochain appel.