J’ai créé une liste chainée simple qui fonctionne.
Lorsque je la détruis je ne peux pas en reconstruire une autre.
Ce doit être ma fonction:
void detruireListe(); qui dysfonctionne mais où?
voici tout mon code
#include <Streaming.h>
/***************************************************************/
#include "arduino.h"
//****************************************************************
struct tNode
{
tNode *pPrec;
tNode *pSuiv;
String str;
};
//...
tNode *pDebut = NULL,
*pDernier = NULL;
//*****************************************************************
void ajout(tNode *pEl)
{
if (pDebut == NULL) // le premier
{
pDebut = pDernier = pEl; // celui ci est premier et dernier
pEl->pSuiv = NULL; // pas de suiv
pEl->pPrec = NULL; // pas de prec
}
else
{
// a la suite du dernier cree
// modif le dernier cree
tNode *pPrec = pDernier; // reouvrir le dernier cree
pPrec->pSuiv = pEl; // actualiser son champ suiv par celui cree
// celui cree
pEl->pPrec = pDernier; // actualiser le champ prec de celui ci
pEl->pSuiv = NULL; // pas de suiv à celui ci
pDernier = pEl; // actu memorise le dernier qui est celui ci
}
}
void ajouterAvecValeur( String s)
{
tNode *pEl = new tNode; // creation d'une nouvelle struct
ajout(pEl); // ajouter en fin
pEl->str = s; // actualiser le champ
}
void detruireListe()
{
tNode *pDetruire = pDebut;
while (pDetruire->pSuiv != NULL)
{
pDetruire = pDebut; // ouvrir le premier
pDebut = pDetruire->pSuiv; // le suiv devient le premier
free(pDetruire); // libere le pointeur
}
pDebut = NULL; // pointe sur vide
}
void affiche()
{
tNode *pAfficher = pDebut ;
while (pAfficher->pSuiv != NULL)
{
pAfficher = pDebut;
pDebut = pAfficher->pSuiv;
Serial << pAfficher->str << "\t";
}
Serial << endl;
}
///////////////////////////////////////////////////////////////////////////////////////////////
void setup()
{
Serial.begin(9600);
Serial<<"prêt"<<endl;
ajouterAvecValeur("un");
ajouterAvecValeur("deux");
ajouterAvecValeur("trois");
ajouterAvecValeur("quatre");
affiche();
// JUSQU'ICI CELA FONCTIONNE
detruireListe();
//APRES PLUS RIEN
ajouterAvecValeur("cinq");
ajouterAvecValeur("six");
ajouterAvecValeur("sept");
affiche();
}
void loop() {
// put your main code here, to run repeatedly:
}
Sur un petit micro-processeur vous n'avez pas intérêt à trop jouer avec l'allocation dynamique....
êtes vous sûr d'avoir besoin d'une liste chaînée ?
si vous savez combien au max votre application aura à en gérer, allouez un tableau de pointeurs sur Strings et vous gagnez comme cela tous les pointeurs.. (et on essaye d'éviter aussi la classe String d'ailleurs)
J'ai vu sur des exemples Web que l'on pouvait spliter un message reçu et stocker les différentes valeurs sur une liste chainée au lieu d'un tableau.
N'ayant jamais fait de liste chainée, j'ai voulu essayer juste pour savoir... D'où mes maladresses.
Eviter les String j'en suis d'accord et je suis tombé sur un écueil:
Le remplacer par un tableau de caractères serait moins gourmand mais la réponse du compilateur m'en a dissuadé.
En gros je ne sais pas l'inclure et le manipuler dans le code
dom0834:
En gros je ne sais pas l’inclure et le manipuler dans le code
comment feriez vous?
j’avais posté il n’y a pas très longtemps ce bout de code sur le forum anglais
#define PRE_ALLOCATE_MEMORY true // set it to false if you want to use dynamic memory allocation through strdup()
const uint8_t maxNbofCommand = 20;
const uint8_t maxLengthofCommand = 63;
char serialBuffer[maxLengthofCommand + 1]; // +1 as we want to add a trailing '\0' to terminate a cSrting
uint8_t commandIndex = 0;
#if PRE_ALLOCATE_MEMORY
char listOfCommands[maxNbofCommand][maxLengthofCommand + 1];// +1 as we want to add a trailing '\0' to terminate a cSrting
#else
char* listOfCommands[maxNbofCommand];
#endif
boolean getCommand()
{
static byte currentIndex = 0;
boolean commandReady = false;
while (!commandReady) {
int c = Serial.read();
if (c != -1) { // -1 means nothing to read
switch (c) {
case '\n': // end marker --> command complete?
serialBuffer[currentIndex] = '\0'; // terminate the c-string
currentIndex = 0; // get ready for next time
commandReady = true;
break;
case '\r': // ignore CR
break;
default: // otherwise if we have room left, store the incoming char
if (currentIndex < maxLengthofCommand) serialBuffer[currentIndex++] = (char) c;
break;
}
} else break;
}
return commandReady;
}
bool addCommandToList(const char* aCommand)
{
bool commandAdded = false;
if (commandIndex < maxNbofCommand) {
#if PRE_ALLOCATE_MEMORY
strncpy(listOfCommands[commandIndex], aCommand, maxLengthofCommand); // http://www.cplusplus.com/reference/cstring/strncpy/
listOfCommands[commandIndex][maxLengthofCommand] = '\0'; // to be sure it's properly terminated
commandIndex++;
commandAdded = true;
#else
listOfCommands[commandIndex] = strdup(aCommand); // https://en.cppreference.com/w/c/experimental/dynamic/strdup
if (listOfCommands[commandIndex] == NULL) {
Serial.println(F("ERROR: SRAM IS FULL"));
} else {
commandIndex++;
commandAdded = true;
}
#endif
} else {
Serial.println(F("ERROR: COMMAND BUFFER FULL"));
}
return commandAdded;
}
void printListOfCommands()
{
for (byte i = 0; i < commandIndex; i++) {
Serial.print(i);
Serial.write('\t');
Serial.println(listOfCommands[i]);
}
Serial.println(F("--------------------------"));
}
void setup()
{
Serial.begin(115200);
#if PRE_ALLOCATE_MEMORY
Serial.println(F("STATIC ALLOCATION"));
#else
Serial.println(F("DYNAMIC ALLOCATION"));
#endif
Serial.println(F("Ready"));
}
void loop()
{
if (getCommand())
if (addCommandToList(serialBuffer)) printListOfCommands();
}
ça écoute le terminal série (ouvert à 115200 bauds et avec CR+LF comme fin de ligne) et chaque phrase que vous entrez est stockée dans un tableau. le tableau a un nombre d’entrée limitées (par la constante maxNbofCommand) et chaque ligne entrée a au maximum maxLengthofCommand caractères.
au début du code il y a un #define PRE_ALLOCATE_MEMORY true // set it to false if you want to use dynamic memory allocation through strdup()qui permet soit d’avoir une allocation dynamique de l’espace de stockage des lignes reçues, soit une allocation statique dans un tableau à 2 dimensions fixes, c’est fait dans ce bout de code
#if PRE_ALLOCATE_MEMORY
char listOfCommands[maxNbofCommand][maxLengthofCommand + 1];// +1 as we want to add a trailing '\0' to terminate a cSrting
#else
char* listOfCommands[maxNbofCommand];
#endif
donc suivant que vous mettez PRE_ALLOCATE_MEMORY à true ou false ça va faire de la gestion statique ou dynamique.
ce code ne gère pas la suppression d’un élément mais en cas de mémoire dynamique il suffirait de mettre le pointeur à NULL et lors de l’ajout au lieu d’y aller en séquence jusqu’à la fin, il faudrait parcourir le tableau pour trouver la première case vide.