Array di char e Itoa

seguendo il consiglio di fabpolli, sto cominciando a prendere dimestichezza con le stringhe classiche e la funzione itoa… ho buttato giù un esmepio che sembra funzionare… che dite?

grazie

#include <stdio.h>
#include <stdlib.h>

char prova[15]="il mio valore:";
int valorepioggia = 42;

// itoa

char prova3[2];
int valorepioggia3 = 42;



void setup() {
  // put your setup code here, to run once:
 Serial.begin(9600); // Start de seriele monitor op 9600 baud.

Serial.println(prova);
Serial.println(valorepioggia);


Serial.println(prova);
itoa(valorepioggia3, prova3, 10);  // perchè 10?
Serial.println(valorepioggia3);


}

void loop() {
  // put your main code here, to run repeatedly:

}

simosere:
itoa(valorepioggia3, prova3, 10); // perchè 10?

Perché vuoi la conversione in decimale, no? Cerca sempre i reference delle funzioni per le quali hai dubbi…

Comunque se vuoi mettere il valore 42 in na stringa, la variabile prova3 non puoi dimensionarla a 2 caratteri perché ti serve sempre spazio per il terminatore di stringa (\0). Visto che la variabile è “int”, ti suggerirei di dimensionarla opportunamente per poter contenere il valore massimo, più uno. Ad esempio, se hai al massimo 4 cifre metti 5 (o più, parliamo di pochi byte…):

char prova3[5];

Dopo che hai seguito il consiglio di docdoc in merito alla lunghezza dell'array il passo successivo è concatenare le due stringhe per farlo ci sono almeno due strade, intanto te ne suggeriscno una propedeutica all'apprendimento dell'uso dei vettori di caratteri ovvero la funzione strncat, prova a stampare la tua stringa e il valore con un unica print su seriale

eccomi:

ma quindi la funzione itoa in parole spicciole serve a trasformare un valore int o float in una stranga classica o array sdi char corretto?

cmq:

#include <stdio.h>
#include <stdlib.h>

// stringa classica. ricordarsi il terminatore, un carattere in più




char prova[15]="il mio valore:";
int valorepioggia = 42;


// con itoa trasformo un volore fisso o float in array di char

char prova3[5];
int valorepioggia3 = 42;



void setup() {
  // put your setup code here, to run once:
 Serial.begin(9600); // Start de seriele monitor op 9600 baud.


 

Serial.println(prova);
Serial.println(valorepioggia);


Serial.println(prova);
itoa(valorepioggia3, prova3, 10);
Serial.println(valorepioggia3);


strncat (prova, prova3, 20);
Serial.println(prova)+(prova3);




}

void loop() {
  // put your main code here, to run repeatedly:

}

No, itoa converte un intero in un array di char non un float o cose simili, solo interi.
Strncat è usato male, torna a studiarlo :slight_smile: indizio il terzo parametro è errato
La Serial.print è aberrante e dimostra che non hai capito a cosa serve la strncat, non cercare di bruciare i tempi per terminare il tuo progetto, arrivi poco lontano… :wink:

Anzi mi correggo il terzo parametro sarebbe anche corretto ma è la dimensione dell'array che non va bene se metti quel valore come terzo parametro

Credo di aver capito… o meglio spero…

strncat (prova, prova3,5 );
Serial.println(prova)

In pratica strncat “appiccica” prova3 a prova dicendo ad arduino che la parte da appiccicare deve essere di 5 caratteri…

E di conseguenza stampando solo prova dovrebbe stampare anche prova3… al momento sono senza pc… è occupato da mio figlio… eheheh nn provato e potrei averla sparata grossa… eheheh

ho modificato il codice come accennato sopra e sembra funzionare:

#include <stdio.h>
#include <stdlib.h>

// stringa classica. ricordarsi il terminatore, un carattere in più




char prova[15]="il mio valore:";
int valorepioggia = 42;


// con itoa trasformo un volore fisso(int) in array di char o stringa classica

char prova3[5];
int valorepioggia3 = 42;



void setup() {
 // put your setup code here, to run once:
Serial.begin(9600); // Start de seriele monitor op 9600 baud.




Serial.println(prova);
Serial.println(valorepioggia);


Serial.println(prova);
itoa(valorepioggia3, prova3, 10);
Serial.println(valorepioggia3);


strncat (prova, prova3, 5);
Serial.println(prova);




}

void loop() {
 // put your main code here, to run repeatedly:

}

simosere:
#include <stdio.h>
#include <stdlib.h>

Questi non servono su Arduino, “stdio” e “stdlib” sono già inclusi nella libreria AVR (…Arduino\hardware\tools\avr\avr\include).

docdoc: Questi non servono su Arduino, "stdio" e "stdlib" sono già inclusi nella libreria AVR (...Arduino\hardware\tools\avr\avr\include).

grazie docdoc,

allego il codice con i commenti e attendo il passaggio successivo... grazie:

// stringa classica. ricordarsi il terminatore, un carattere in più

char prova[15] = "il mio valore:";
int valorepioggia = 42;


// con itoa trasformo un volore fisso(int) in array di char o stringa classica

char prova3[5]; // prova3 si riferisce a valorepioggia3, il valore massimo che può avere int è 4+1 del terminatore, quindi diventa 5
int valorepioggia3 = 42;



void setup() {
  // put your setup code here, to run once:
  Serial.begin(9600); // Start de seriele monitor op 9600 baud.

  // stampo su seriale la stringa classica senza convertire in array valore pioggia

  Serial.println(prova);
  Serial.println(valorepioggia);

   // stampo su seriale la stringa classica prova e converto con itoa in array valorepioggia3  e lo stampo su seriale


  Serial.println(prova);
  itoa(valorepioggia3, prova3, 10);
  Serial.println(valorepioggia3);


// con strncat unisco le due stringhe in modo da concatenarle su un'unica riga, in pratica dico di unire prova3 a prova, 5, in questo esempio è la lunghezza della stringa che si deve unire,
// perchè è il valore massimo che int può avere è di quattro + il terminatore


  strncat (prova, prova3, 5);
  Serial.println(prova);




}

void loop() {
  // put your main code here, to run repeatedly:

}

simosere: allego il codice con i commenti e attendo il passaggio successivo... grazie:

Ok, e qual è la domanda relativa al "passaggio successivo"?

Intanto ti lancio qualche indicazione, perché temo che ancora ci siano varie cose su cui non hai ancora ragionato.

Primo, tu definisci:

char prova[15] = "il mio valore:";

per questa stringa hai esattamente 15 caratteri ossia i 14 caratteri di "il mio valore:" seguito dal terminatore. Ma se poi fai:

strncat (prova, prova3, 5);

e prova3[] contiene 3 caratteri, ossia la stringa "42" (il valore di "valorepioggia2), non ti pare che il risultato abbia una lunghezza maggiore di quella che può contenere prova[15] ? La destinazione di strcat() (o la variante strncat) deve avere una dimensione sufficiente a contenere TUTTO il risultato. Quindi se prevedi che il valore possa avere al massimo 3 cifre, più i 14 della stringa iniziale, più il terminatore, dovresti definire prova[] con almeno 18 caratteri. Se poi usi la strncat() (ma perché?) con 5 come numero massimo di caratteri da concatenare, allora dovresti arrivare ad inizializzarla con almeno 14+5+1 = 20 caratteri.

In generale per operazioni come queste definisco UNA variabile globale (quindi allocata una sola volta) che uso come "buffer" temporaneo di dimensione adeguata, ad esempio se ti serve come buffer di linea di un LCD da 20 caratteri farò:

char buf[20] = "";

Quindi posso iniziare ad inserire le stringhe e mostrarle, ad esempio (nota che la prima è strcpy):

Serial.println(prova);
itoa(valorepioggia3, prova3, 10);
Serial.println(valorepioggia3);
strcpy(buf, "il mio valore:");
strcat(buf, prova3);
Serial.println(buf);

A parte questo, magari ti sarà più utile studiare la sprintf() che la strncpy() ed evitare pure la itoa() e quindi anche la stringa prova3[], visto che per fare quello che stai facendo ti basta a quel punto una sola riga:

Serial.println(prova);
sprintf(buf, "il mio valore:%d", valorepioggia3);
Serial.println(buf);

Ciao DocDoc,

fabpolli si è gentilmente concessi aiutarmi, dandomi le indicazioni necessarie per prendere dimestichezza con gli array di char per arrivare poi ad essere in grado(spero) di andare a modificare una parte di codice complesso che sto usando dove utilizzo Stringhe non classiche, e pian piano mi sta facendo fare dei passaggi per prenderci confidenza...

quindi chiedevo, ammesso che finora avevo fatto tutto correttamente, quale era il prossimo passaggio!!! son curioso!!! :)

char prova[15] = "il mio valore:";

per questa stringa hai esattamente 15 caratteri ossia i 14 caratteri di "il mio valore:" seguito dal terminatore. Ma se poi fai:

strncat (prova, prova3, 5);

e prova3[] contiene 3 caratteri, ossia la stringa "42" (il valore di "valorepioggia2), non ti pare che il risultato abbia una lunghezza maggiore di quella che può contenere prova[15] ? La destinazione di strcat() (o la variante strncat) deve avere una dimensione sufficiente a contenere TUTTO il risultato. Quindi se prevedi che il valore possa avere al massimo 3 cifre, più i 14 della stringa iniziale, più il terminatore, dovresti definire prova[] con almeno 18 caratteri. Se poi usi la strncat() (ma perché?) con 5 come numero massimo di caratteri da concatenare, allora dovresti arrivare ad inizializzarla con almeno 14+5+1 = 20 caratteri.

nel topic numero 3 avevo già postato il codice:

strncat (prova, prova3, 20);
Serial.println(prova)+(prova3);

ovviamente ho capito come comportarmi con il Serial.println quando si usa strncat(fabpolli me lo ha fatto notare... :) ) , mentre quel 20(dimensione totale di prova+ prova3) non sembrava essere giusto... mi viene in mente ora un domanda:

char prova3[5]; sarebbe il numero massimo che può avere un valore int + il teminatore... con strncat vado ad unire prova15 e prova35 servono 2 terminatori se devo concatenarli? forse si riferiva a questo fabpolli?

per i passaggi da te elencati, devo rivedermeli con calma e andarmi a vedere i reference... grazie mille!!!

Il terminatore di stringa è solo uno, come dici il suo nome termina la stringa ovvero serve per far capire alle varie funzioni che li la stringa finisce e non bisogna andare oltre, solitamente per evitare problemi di overflow dell'array o semplicemente perché si vuol finire di processare la stringa in un determinato punto. Se tu hai:

prova3[5]
prova[15]

e li vuoi unire in un terzo array questo dovrà essere grande abbastanza, dove per abbastanza si intende la somma di tutti i caratteri delle varie parti più un terminatore. Quindi quando devi dichiarare un array devi calcolare la massima lunghezza più uno 8il terminatore). Quando li unisci devi sommare i caratteri reali (nell'esempio precedente 4+14) e aggiungere uno (sempre per il terminatore). I passi successivi te li ha indicato docdoc ovvero copiare una stringa in un'altra (strncpy) e poi infine il succo reale della strada che ti avrei indicato ovvero la snprintf ma prima di approcciare a quella DEVI aver chiaro come manipolare le strighe, altrimenti farai qualcosa di sbagliato (ovvero andare oltre la dimensione dell'array in lettura o scrittura) e magari a primo impatto il programma sembra andare per poi cadere in errori strani ed incomprensibili perché hai corrotto la memoria andando oltre il consentito in un array. A differenza di docdoc le funzioni che ti ho indicato io hanno una "n" in più, la differena tra le due è che in quelle con la "n" ti costringono a dichiarare quanti caratteri usare per le varie operazioni, e già questo rende il software più sicuro, ovvero se rispetti la dimensione massima dell'array in tutte le funzioni quello che può accadere è che vedi delle stringhe tagliate ma senza incorrere in problemi con l'overflow, se usi quelle senza "n" devi essere certo che stai usando array corretti e che questi abbiano correttamente e tutti il terminatore alla fine della tua stringa.

Per farti capire meglio gli usi del terminatore potresti guardare qui dove spiega cosa fa la strtok e perché e come riesce a far "spezzare" la stringa in più parti, se riesci a seguire cosa fa la strtok, magari lavorando su carta con gli array rappresentati dai soliti quadrettoni che rappresentano ciascuno una posizione di memoria, allora il resto poi sarà un giuoco semplice :)

ok chiaro il messaggio!!! grazie ad entrambi...

posto il codice con la prova di snprintf:

ho fatto volutamente due prove, una con un buf[19] che è quello corretto e uno errato per vedere che risultato ottengo... come mai ottengo sempre un risultato giusto? nel caso buf2[5] non dovrebbe esserci un risultato "mozzato"

// stringa classica. ricordarsi il terminatore, un carattere in più

char prova[15] = "il mio valore:";
int valorepioggia = 42;


// con itoa trasformo un volore fisso(int) in array di char o stringa classica

char prova3[5]; // prova3 si riferisce a valorepioggia3, il valore massimo che può avere int è 4+1 del terminatore, quindi diventa 5
int valorepioggia3 = 42;



void setup() {
  // put your setup code here, to run once:
  Serial.begin(9600); // Start de seriele monitor op 9600 baud.

  // stampo su seriale la stringa classica senza convertire in array valore pioggia

  Serial.println(prova);
  Serial.println(valorepioggia);

   // stampo su seriale la stringa classica prova e converto con itoa in array valorepioggia3  e lo stampo su seriale


  Serial.println(prova);
  itoa(valorepioggia3, prova3, 10);
  Serial.println(valorepioggia3);


// con strncat unisco le due stringhe in modo da concatenarle su un'unica riga, in pratica dico di unire prova3 a prova, 5, in questo esempio è la lunghezza della stringa che si deve unire,
// perchè è il valore massimo che int può avere è di quattro + il terminatore


  strncat (prova, prova3, 19);
  Serial.println(prova);


  

  
char buf[19] = "";
Serial.println(prova);
snprintf(buf, "il mio valore:%d", valorepioggia3);
Serial.println(buf);

char buf2[5] = "";
Serial.println(prova);
snprintf(buf2, "il mio valore:%d", valorepioggia3);
Serial.println(buf2);





}

void loop() {
  // put your main code here, to run repeatedly:

}

poi chiedo e sarebbero le altre parti che mi servono per modificare tutte le stringhe che ho in stringhe classiche:

per valori float cosa devo vedere? per valori double? per valori const unsigned long per concatenare tre stringhe?

manca ancora tanto!!!! :)

Quasi tutto sbagliato bravo! :slight_smile:
snprintf manca un parametro fondamentale, ti lascio alla lettura del reference per capire quale

simosere:
per valori float cosa devo vedere?
per valori double?
per valori const unsigned long
per concatenare tre stringhe?

manca ancora tanto!!! :slight_smile:

A tutte le tue domande la risposta è nella lettura del link che ti ho fornito, se lo studi vedrai che avrai le risposte alle tue domande.
Per la parte di concatenare tre stringhe occorre usare non una funzione ma escogitare un “algoritmo” per arrivare alla soluzione desiderata, prova a pensarci :wink:

Altro consiglio nelle impostazioni dell’IDE attiva i flag “compilazione” e “caricamento” posti vicino all’etichetta “Mostra output dettagliato per” e importa la combobox “Warning del compilatore” su “Tutti”, aiuta parecchio in fae di apprendimento avere subito un riscontro di eventuali errori o warning

Mancava il valore massimo della stringa... per cui:

char buf[19] = "";
Serial.println(prova);
snprintf(buf,19, "il mio valore:%d", valorepioggia3);
Serial.println(buf);

Invece nn ho capito a quale link dovrei guardare... per gli altri... guardando sia snprintf e strtok nn li trovo.... credo mi sfugga qualcosa.... :/

snprintf e sprintf su queste MCU non funziona %f ovvero per i valori float, disabilitato (troppo pesante il codice interno della lib per gestire i float) Usa dtostrf()

Per la dimensione dell'array di char puoi usare sizeof(array) oppure crea una costante:

#define K_DIMBUF 19
char buf[K_DIMBUF] = "";
snprintf(buf,K_DIMBUF, "il mio valore:%d", valorepioggia3);

oppure

char buf[19] = "";
snprintf(buf,sizeof(buf), "il mio valore:%d", valorepioggia3);

Occhio che sizeof() ritorna quanti byte occupa l'array, essendo di char (1byte) sizeof in questo caso dice anche quanti solo gli elementi. Fosse array di int allora darebbe 38 (qui su queste MCU int=2 byte)

docdoc: Questi non servono su Arduino, "stdio" e "stdlib" sono già inclusi nella libreria AVR (...Arduino\hardware\tools\avr\avr\include).

Vero, ma il mio consiglio è di imparare a metterli SEMPRE dato che, come ci si allontana dall'IDE di Arduino (che nasconde il 50% delle cose che si dovrebbero fare) e si passa a qualche cosa di diverso ... è obbligatorio metterli, quindi ... perché non prendere l'abitudine e metterli sempre? Male non fanno ;)

Guglielmo

gpb01: e si passa a qualche cosa di diverso ... è obbligatorio metterli, quindi ... perché non prendere l'abitudine e metterli sempre? Male non fanno ;)

Vero, ma insomma, se è inutile, è inutile, altrimenti sarebbe come dire che d'estate tieni comunque in macchina le catene perché se poi guido in montagna in inverno mi servono... ;)

Per cui la mia risposta è: NAH. :D

docdoc: Vero, ma insomma, se è inutile, è inutile ...

... ribadisco, SOLO con l'IDE di Arduino ... che, per altro, [u]personalmente[/u], ritengo in parte diseducativo, visto che, come esci dal "mondo semplificato" da esso creato, sbatti la faccia :smiling_imp:

Guglielmo