Sprintf reset scheda

type or paste code here

Buon salve a tutti
Mi scuso in anticipo per la mia scarsa competenza, ma sto avendo problemi con la formattazione sprintf che manda in reset di continuo la scheda.
In sostanza devo memorizzare delle stringhe composte sia da caratteri che da una variabile, per poi stamparle in un oled quando richiesto. su quale stringa viene fatta la memorizzazione viene deciso da una variabile.

char *memoriaPosizioneS2[] = {0,0,0,0,0,0};
char str[] = "errore pin";
int numero = 1;    
void loop() {
 sprintf(memoriaPosizioneS2[numero],"%s%d",str,numero);
Serial.println(memoriaPosizioneS2[numero]);
delay(400);
}

Cosa sbaglio? Tutto?

:warning:
Ti segnalo che, nella sezione in lingua Inglese, si può scrivere SOLO in Inglese ... quindi, per favore, la prossima volta presta più attenzione in quale sezione metti i tuoi post; questa volta esso è stato spostato, da un moderatore della sezione di lingua Inglese, nella sezione di lingua Italiana ... la prossima volta potrebbe venire direttamente eliminato. Grazie.

Ti è chiaro che è un array di puntatori a caratteri.
Cioè:

char str[] = "errore boo";
char str1[] = "errore boo1"
memoriaPosizioneS2[0] = str;
memoriaPosizioneS2[1] = str1;

Se stampi memoriaPosizioneS2[1] visualizza il contenuto di str1.
Ora però se stampi Serial.println((uin16_t)memoriaPosizioneS2[1];
Ciò che ottieni un indirizzo di memoria in cui si trova il primo carattere di str1. Ora non mi è chiaro perché usare un array di puntatori?

In ogni caso sprintf() richiede un buffer di dimensione utile + 1, cioè se devi riempire il buffer con 10 caratteri, lo devi dichiarare di 11 caratteri, per fare spazio al terminatore di C string.

Solitamente memoriaPosizioneS2 si dichiara e inizializza così:

char *memoriaPosizioneS2[] = { "mia", "tua", "sua", "nostra"};

Ora è tardi e sono cotto, per adesso prenditi questi link: array, contenuto RAM, LCD sprintf, arduino memset()

Ne riparliamo domani così capisco la tua necessità.

Ciao.

Provo a spiegarti un poco, come aggiunta "divulgativa" a quanto correttamente ha scritto Maurotec.

Tu con questa istruzione:
sprintf(memoriaPosizioneS2[numero],"%s%d",str,numero);
stai scrivendo una stringa (quella generata dalla sprintf tramite il formato ed i due parametri) ad un indirizzo di memoria puntato da memoriaPosizioneS2[1]. A parte che l'indice di un vettore parte da zero e non da uno, ma con l'array così definito:
char *memoriaPosizioneS2[] = {0,0,0,0,0,0};
quell'array non alloca alcuno spazio nel quale memorizzare le stringhe ma contiene solo indirizzi a 0 (zero!) che non puoi usare, e crasha tutto.

La soluzione è semplice anzi, è quella "più semplice" per te, poi ci sono altre possibilità ma evito di confonderti le idee con altro. Tu devi allocare lo spazio massimo previsto per ogni stringa definendo l'array ad esempio in questo modo:
char memoriaPosizioneS2[6][30];
In questo caso prevedi 6 stringhe da un massimo di 30 byte l'una (quindi 29 caratteri più terminatore), e a quel punto la sprintf() funzionerà correttamente.

Purtroppo questa è la conseguenza di pessimi esempi che troviamo in continuazione sia su internet che, incredibilmente, tra gli esempi dell'IDE. Quante volte abbiamo detto che le due righe:

char *ssid[] = "theSSID";        // your network SSID (name)
char *pass[] = "thePswd";        // your network password

... che molto spesso di trovano negli esempi, sono fuorvianti e diseducative? La gente poi si convince che la sintassi corretta, per definire una stringa di caratteri, è quella con il puntatore, non capendo cosa in realtà si sta facendo! :roll_eyes:

Guglielmo

Intanto grazie per la risposta
Allora provo a spiegarmi, in sostanza devo stampare degli errori su un oled, quando la prima pagina è piena voglio che la funzione che ho creato vada a salvare in maniera consecutiva L’ errore su una delle 6 “memorie”,L’ errore può essere di due tipi quind(es. “errore inversione pin” int numeroPin1, int numeroPin2), oppure (es. “errore pinInterrotto” int numeroPin). Poi queste “memorie” verranno stampate quando tramite un pulsante si cambierà pagina. Quindi la mia idea è quella di creare queste “memorie” con appunto le char con il puntatore in modo da poterle riempire con i vari errori indicando la posizione tramite le parentesi quadre. Le stringhe le ho dichiarate 0,0,0,0,0,0 perché effettivamente sono vuote e vanno riempite, poi si magari potevo merci dei caratteri iniziali a caso.

In sostanza si possono verificare più errori e devi prendere nota di questi. Tu li vuoi salvare gli errori già convertiti in C string per poi visualizzarli ok anche se non mi piace. A me piace salvare gli errori in variabili bool (magari campi di struct) poi la routine che deve mostrare l'errore converte la struct in array locale, chiama la funzione per stampare con argomenti riga, colonna e il testo da stampare salvato in memoriaPosizioneS2 che chiamerei errorList dichiarata locale a alla funzione.

Comunque tu lo vuoi così e allora @docdoc qui ti ha suggerito come creare il buffer composto da 6 C string ognuna grande 29 caratteri. https://forum.arduino.cc/t/sprintf-reset-scheda/1031835/4?u=maurotec

Ciao.

Se hai già delle stringhe (char array) con gli errori, se vuoi che l'array con le 6 memorie "punti" a quelli devi assegnare ad ognuno di quegli elementi l'indirizzo della stringa desiderata. Sai come si fa?
Se invece, come immagino, gli errori sono stringhe che costruisci tu, allora non c'è problema, definisci l'array come ti ho detto (magari poi nella setup inizializzalo comunque a stringhe vuote scrivendo \0 come primo carattere) e ci scrivi dentro con la sprintf(), ed infine avrai una funzione che "estrae" i messaggi e li manda sull'Oled (più una che inserisce un nuovo messaggio ed una che rimuove l'ultimo, per farne una coda FIFO).

1 Like

Nel pezzo che posti, oltre a quello che ti hanno detto, c'e' un'altro errore (anche di logica)
Se puoi memorizzare 6 msg, tu nella loop usi "numero" che dovrebbe andare da 0 a 5, quindi limitandolo.
Per fortuna che non hai nel loop un numero=numero+1;
Se metti numero=numero+1; allora deve aggiungere subito dopo

numero=numero+1;
if(numero>5) numero=0;

(e ovviamente int numero=0; e non 1)

ragazzi definendo l' array come suggerito da docdoc funziona esattamente come volevo, siete stati tutti dei grandi grazie. Poi in realtà non ho capito il perchè devo definirlo cosi quindi se mi date qualche suggerimento su dove andare a studiare sarebbe apprezzato. Per quel che riguarda i consigli di altri modi, sicuramente più corretti, per svolgere lo stesso lavoro ne prendo spunto magari per imparare qualcosa ma per il momento sono troppo avanzati per me.

Cerca in internet con le parole "Arduino Tiziana Marsella" dovresti trovare un pdf scritto da una prof. di libera visione. E' utile per chi inizia. Vedi pagina 21

Anche un buon libro sul C è utile (arduino lo programmi in C/C++)
NON il libro di Kernighan & Ritchie (quello bianco con la C azzurra) perchè NON è per principianti.

1 Like

Ottimo grazie mille

C'è anche QUESTO, liberamente scaricabile :wink:

Guglielmo

1 Like

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