[RISOLTO] Dubbi array statico

Buongiorno a tutti,
da qualche giorno sto battendo la testa su un problema alquanto ambiguo...

Sappiamo tutti che in C le variabili (che siano singole, array ecc.) vengono allocate e deallocate in memoria stack automaticamente, contrariamente a quanto succede in caso di occupazione dinamica della memoria heap (istruzioni: malloc/ free in C e new/delete in C++).

Ho realizzato un software che deve leggere parametri da una SD card, con una directory contenente 12 file di testo, ciascuno contenente un valore decimale in formato carattere (di diversa lunghezza; alcuni contengono solo un numero singolo, altri file contengono numeri formati da più cifre).

So che ci sono metodi sicuramente migliori per effettuare storage di variabili anche su un singolo file di testo ma per ora poco importa poichè sono in fase di test.

Fin qui tutto ok, il problema sorge quando devo leggere i dati dai file di testo.

Quello che faccio io è in sostanza aprire la directory e il file di testo da cui voglio estrarre l'informazione numerica, inserirla carattere per carattere in un vettore STATICO (e qua sottolineo statico perchè è importante da tenere a mente). una volta ottenuto il vettore statico contenente il numero, viene convertito con l'apposita funzioe sscanf(vettore, "%d", &variabile).

In questo modo riesco a recepire un dato numerico sottoforma di stringa di caratteri contenuto sul file di testo carattere per carattere, convertirlo in un vettore di cratatteri, e successivamente convertirlo in un numero intero.

ovviamente, poichè ho 12 file di testo differenti, ciascuno con nome differente, di diversa lunghezza l'uno dall'altro, ho scritto 12 parti di codice molto simili tra loro. (in sostanza 12 if)
Non ho potuto eseguire una funzione con passaggio di variabile e di directory poichè non esattamente tutte quante fanno la stessa cosa e sarei finito per complicarmi parecchio la vita.

Quando il programma esce da un'istruzione if/else, tutte le variabili, array ecc. definite al suo interno dovrebbero essere eliminate.
nel mio programma sembrerebbe non essere così...

mi spiego meglio:
il codice contenuto in uno di questi 12 if, sembrerebbe prendere valori rimasti in memoria dalla lettura precedente.
Nella lettura precedente devo leggere un numero pari a 120000, che assegno ad un vettore di 6 elementi per poi convertirlo in una variabile di tipo intero.

In quella successiva devo leggere un valore pari a 1000, soltanto che quando vado a leggere il valore convertito dall'istruzione sscanf, leggo 100000, cioè come se avesse unito il valore 1000 con i due zeri rimasti in momoria da 120000.

Il dubbio mi è sorto quando, provando a scambiare l'ordine di lettura dei due file di testo (quindi prima il file di testo contenente il valore minore e poi il file di testo contenete il valore maggiore) il risultato era ok.

Qui sotto vi allego una parte del codice:

* -------------------------------------------------- DIRECTORY "CONFIG" EXISTS BUT RELATIVE_ZERO_TIMER.txt FILE DOESN'T: */
          if(SD.exists(RELATIVE_ZERO_TIMER_PATH)){
            myData = SD.open(RELATIVE_ZERO_TIMER_PATH, FILE_READ);
            if(myData){
              if(!myData.available()){
                myData.close();
              
                myData = SD.open(RELATIVE_ZERO_TIMER_PATH, FILE_WRITE);
                myData.write(DEFAULT_RELATIVE_ZERO_TIMER);

                myData.close();
              }else{
                const uint8_t MaxChar = 6;
                char CharArray[MaxChar];
                uint8_t ArrayIndex = 0;
                
                while(myData.available()){
                  char incomingChar = myData.read();
                
                  if(isDigit(incomingChar)){
                    CharArray[ArrayIndex] = incomingChar;
                    ArrayIndex++;
                  }
                }
                sscanf(CharArray, "%d", &RELATIVE_ZERO_TIMER);

                if(RELATIVE_ZERO_TIMER < 40000 || RELATIVE_ZERO_TIMER > 180000){
                  RELATIVE_ZERO_TIMER = 120000;    // reset to default value if readed value is inconsistent
                  myData.close();
                  SD.remove(RELATIVE_ZERO_TIMER_PATH);
                  myData = SD.open(RELATIVE_ZERO_TIMER_PATH, FILE_WRITE);
                  myData.write(DEFAULT_RELATIVE_ZERO_TIMER);
                  myData.close();
                    
                  error = INCONSISTENT_RELATIVE_ZERO_TIMER_VALUE;
                  errorHandler();
                }
              }
            }else{
              error = EV_POST_PUMP_TIMER_PATH_FAILURE;
              errorHandler();
            }
          }else{
            myData = SD.open(EV_POST_PUMP_TIMER_PATH, FILE_WRITE);
            myData.write(DEFAULT_EV_POST_PUMP_TIMER);
            myData.close();
          }


/* -------------------------------------------------- DIRECTORY "CONFIG" EXISTS BUT RED_ALARM_RESPONSIVENESS.txt FILE DOESN'T: */
          if(SD.exists(RED_ALARM_RESPONSIVENESS_PATH)){
            myData = SD.open(RED_ALARM_RESPONSIVENESS_PATH, FILE_READ);
            if(myData){
              if(!myData.available()){
                myData.close();
              
                myData = SD.open(RED_ALARM_RESPONSIVENESS_PATH, FILE_WRITE);
                myData.write(DEFAULT_RED_ALARM_RESPONSIVENESS);

                myData.close();
              }else{
                const uint8_t MaxChar = 4;
                char CharArray[MaxChar];
                uint8_t ArrayIndex = 0;
                
                while((myData.available())){
                  char incomingChar = myData.read();
                
                  if(isDigit(incomingChar)){
                    CharArray[ArrayIndex] = incomingChar;
                    ArrayIndex++;
                  }
                }
                
                sscanf(CharArray, "%d", &RED_ALARM_RESPONSIVENESS);

                if(RED_ALARM_RESPONSIVENESS < 500 || RED_ALARM_RESPONSIVENESS > 2000){
                  RED_ALARM_RESPONSIVENESS = 1000;    // reset to default value if readed value is inconsistent
                  myData.close();
                  SD.remove(RED_ALARM_RESPONSIVENESS_PATH);
                  myData = SD.open(RED_ALARM_RESPONSIVENESS_PATH, FILE_WRITE);
                  myData.write(DEFAULT_RED_ALARM_RESPONSIVENESS);
                  myData.close();
                    
                  error = INCONSISTENT_RED_ALARM_RESPONSIVENESS_VALUE;
                  errorHandler();
                }
              }
            }else{
              error = EV_POST_PUMP_TIMER_PATH_FAILURE;
              errorHandler();
            }
          }else{
            myData = SD.open(EV_POST_PUMP_TIMER_PATH, FILE_WRITE);
            myData.write(DEFAULT_EV_POST_PUMP_TIMER);
            myData.close();
          }


Sono convinto che il problema sia circoscritto a queste parti di codice, per cui penso non serva altro.

Non riesco a capire come mai sembra che l'array nuovo prenda tutti gli indirizzi di memoria di quello vecchio nonostante gli abbia dato una dimensione diversa e nonostante si trovino localmente in due blocchi di statement differenti.

Ringrazio anticipatamente tutti voi!!

hai certamente ragione, perché hai sbagliato approccio...
per cominciare non sono sicuro che il vettore sia realmente statico, come affermi tu
si tratta di un VLA, e non so come lo gestisca il C++ di arduino, il C++ in se e per se non ha VLA
anche se fosse C non sarei sicuro che venisse gestito in maniera statica

comunque, statico o dinamico che sia è esplicitamente dichiarato nel K&R che le variabili "locali" NON sono azzerate, quindi dopo la prima esecuzione trovi sporcizia al loro interno
ricorda poi che le stringhe le devi sempre terminare esplicitamente
soluzione?

secondo me se cambi queste tre righe:

            if(isDigit(incomingChar)){
               CharArray[ArrayIndex] = incomingChar;
               ArrayIndex++;
            }

in queste:

                 if(isDigit(incomingChar)){
                    CharArray[ArrayIndex] = incomingChar;
                    CharArray[++ArrayIndex]=0;
                 }

hai risolto

Ti ringrazio moltissimo per la risposta!
Hai ragione! non avevo tenuto conto della possibilità di poter utilizzare il pre-incremento.
Mi metto subito all'opera per vedere se tutto funziona correttamente.
Grazie ancora!! :laughing:

prego

Testato tutto e funziona in maniera eccellente! Grazie ancora.
Posso confermare il topic come risolto :slightly_smiling_face:

Attenzione anche al fatto che nel messaggio iniziale parlavi di una cifra come 120000, poi dichiari l'array di 6 caratteri : non bastano, ce ne vuole uno in più di terminazione ('\0'), altrimenti sscanf() non sa dove fermarsi...

Ciao, Ale.

Ciao Ale, Grazie per la risposta, il software per ora funziona correttamente, non so se è effettivamente un errore. Se mi dici però che per precisione sarebbe meglio dichiarare l'array con una casella in più per il carattere terminatore vedrò eventualmente di farlo.
Grazie ancora!

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.