Problema con la classe String

Saluti a tutti.
Una cosa mi fa diventare matto. Qui sotto una funzione che non va e non riesco a capire perché (dentro ho messo dei print di debug):

String G_VERSION = "?????";  // variabile globale

// ricava la versione dalla fine del nome di questo file che deve essere xxxxxx_M_m.ino dove M è il numero versione maggiore e m quello minore
String getVersion() {
  //return G_VERSION="1.9";
    Serial.print(__LINE__);
  Serial.print(" FILE:");
  Serial.println(__FILE__);
  G_VERSION = "D:\\SorgentiMiei\\Arduino\\Zorko\\Freza-Nova\\FrezaBig_1_9\\FrezaBig_1_9.ino";
// questa in realtà dovrebbe essere G_VERSION=__FILE__;
  Serial.print(__LINE__);
  Serial.print(" V:");
  Serial.println(G_VERSION);
  G_VERSION = G_VERSION.substring(G_VERSION.lastIndexOf('\\') + 1);
  Serial.print(__LINE__);
  Serial.print(" V:");
  Serial.println(G_VERSION);
  G_VERSION = G_VERSION.substring(G_VERSION.indexOf('_') + 1);
  Serial.print(__LINE__);
  Serial.print(" V:");
  Serial.println(G_VERSION);
  G_VERSION.remove(G_VERSION.lastIndexOf('.'));
  Serial.print(__LINE__);
  Serial.print(" V:");
  Serial.println(G_VERSION);
  G_VERSION.replace("_", ".");
  Serial.print(__LINE__);
  Serial.print(" V:");
  Serial.println(G_VERSION);
  return G_VERSION;
}

Mi visualizza questo:
18:03:25.833 -> 459 FILE:D:\SorgentiMiei\Arduino\Zorko\Freza-Nova\FrezaBig_1_9\FrezaBig_1_9.ino
18:03:25.915 -> 463 V:
18:03:25.915 -> 467 V:
18:03:25.915 -> 471 V:
18:03:25.915 -> 475 V:
18:03:25.947 -> 479 V:

Mi funzionava in una versione precedente. Unica cosa ora ho incluso è la libreria LcdMenu ma senza chissà cosa (ho solo dichiarato la variabile LcdMenu(LCD_COLS,LCD_ROWS); e la struttura del menu.

Mi potete aiutare ?

saluti e grazie a tutti

ciao...che scheda usi?
dato che usi una variabile globale direttamente nella funzione...cosa succede a quella variabile nelle altre 400 e rotte righe di programma?

Mi aggiungo alla richiesta della scheda utilizzata. Prova intanto ad aggiungere subito dopo l'assegnazione questa verifica:

G_VERSION = "D:\\SorgentiMiei\\Arduino...[etc]";
if(! G_VERSION) Serial.println("Invalid G_VERSION STRING!");

perchè guardando i sorgenti si nota questo:

        // creates a copy of the assigned value.  if the value is null or
        // invalid, or if the memory allocation fails, the string will be
        // marked as invalid ("if (s)" will be false).
        String & operator = (const String &rhs);
        String & operator = (const char *cstr);
        String & operator = (const __FlashStringHelper *str);

Ciao, Ale.

...ma stai cercando di fare questo?... :slight_smile:

Questo è il codice che uso ormai da tempo senza alcun problema (considera che i commenti si riferiscono al fatto che io divido sempre i programmi in più schede, cioè più file, di cui il primo è quello che porta lo stesso nome della cartella; se metti tutto insieme, funziona ugualmente):

// NEL PRIMO FILE:
const char *percorso=__FILE__; // Dalla macro __FILE__  prende il percorso del file in uso. Questa parte  di programma,
      char ver[12];            // però, si trova  nel file/cartella  dell'IDE c_setup, in cui non è scritta la versione
                               // del programma. La versione è scritta nel file principale, che ha lo stesso nome della
                               // cartella che contiene tutti i file del programma. Questa  riga, quindi, non può stare
                               // nel setup.      
// NEL FILE c_setup:
void setup()
{
char *ver_ext=strrchr(percorso,'v'); // Va a cercare l'ultima 'v' nel percorso.
byte n_car=strlen(ver_ext)-4; // Calcola la lunghezza escludendo .ino.
strncpy(ver, ver_ext, n_car); // Copia i primi n_car caratteri da ver_ext a ver.
ver[n_car]='\0'; // Mette il terminatore in fondo.

lcd.print(ver);
}

Esempio:
Flussocanalizzatore_v1.2b:
lcd.print scrive:
v1.2b

Chiedo per curiosità, perché non va bene inserire un file version.h contenente le macro MAJ_VER, MIN_VER e PATCH_VER.
Esempio:

// the configured options and settings for commands project
#define V_MAJOR 0
#define V_MINOR 1
#define V_PATCH 1
#define STRFY(s) _STRFY(s)
#define _STRFY(s) #s
#define STRVER STRFY(V_MAJOR)"."STRFY(V_MINOR)"."STRFY(V_PATCH)

STRVER la puoi stampare con Serial.print().

Si potrebbe anche chiamare questo file v0_1_1.h e includerlo.

Ciao.

Chiedi per curiosità, poiché non va bene inserire quel file? Cioè?...

...O forse intendevi:
"Chiedo per curiosità: perché non va bene inserire un file version.h contenente le macro MAJ_VER, MIN_VER e PATCH_VER?"

Questa con il ?. Mi sono dimenticato qual'è (se esiste) il motivo di quella complicazione?

Io ho due righe nel file CMakeLists.txt:

project(vt100test VERSION 0.1.1)
configure_file(config.h.in config.h)

Con arduino il file di progetto non esiste, per cui serve creare un header file a manina, ma basta crearlo una sola volta e poi copiarlo da progetto a progetto.

PS: sono felice di non usare più arduino IDE, come lo fui quando nel 2004 dissi addio a microsoft. :smiley:

Ciao.

Fa piacere essere ricordati a distanza di anni...

Grazie, AmericanDreamer!
Trovasti la soluzione al problema.

Niente, è valorizzata e usata solo qui.

Scheda Arduino UNO semplice

G_VERSION = __FILE__;
  if(! G_VERSION) Serial.println("Invalid G_VERSION STRING!");

Infatti mi da Invalid ......
solo dopo l'assegnazione con FILE ma in un altro programmino di prova mi funziona tutto
FILE è
un const char *

Allora da esperienza remota del C la scrittura oltre la fine di una stringa (o altro)può portare a conseguenze che si ripercuotono altrove, visto che ilmio problema ha un comportamento anomalo (semplice assegnazione di un char * a un String che "non prende" probabilmente ci sarà temporalmente qualcosa prima che sporca la memoria . Devo indagare lì

Non credo, semplicemente non hai abbastanza RAM libera per allocare una stringa così lunga. In altri programmi può o meno funzionare, dipende da quanta memoria occupa il resto del programma.

Ciao, Ale.

Accidenti mi sa che hai ragione:

Lo sketch usa 15828 byte (49%) dello spazio disponibile per i programmi. Il massimo è 32256 byte.
Le variabili globali usano 1515 byte (73%) di memoria dinamica, lasciando altri 533 byte liberi per le variabili locali. Il massimo è 2048 byte.

Allora credo di aver risolto, era un problema di memoria. Avevo un'array di String con i nomi dei step dell'automa a stati finiti. L'ho eliminato (sostituito con una funzione che mi ritorna le costanti char * seguendo un switch(G_step)... case x: return "nome step". Questo consuma mem programma ma non ram variabili.
Intanto grazie a tutti per l'aiuto. Se passate di qua la cantina è piena di vino bio casareccio :grin:

Bene, comunque le "String" con Arduino UNO sono da evitare come la peste. e non parlo solo di dimensione delle stringhe, è che non essendoci un garbage collector, su UNO il rischio è che prima o poi il tutto inizi a non funzionare pià correttamente o bloccarsi del tutto perché l'allocazione della memoria con le "String" non è ottimizzata e rischia di causare una tale frammentazione della RAM che ad un certo punto non riesce più ad allocare memoria.

Quindi il mio consiglio è di rimuovere tutte le stringhe di classe "String" e sostituirle con altrettante stringhe classiche ("C string" ossia char array...), e possibilmente con allocazione statica (ossia cercare di evitare comunque di definire stringhe locali ad una singola funzione). Oppure usare SafeStrings.

Qui trovi tutte le descrizioni sul perché:

... che, parecchio tempo fa, avevamo dato già QUI, consigliando poi di usare la SafeString :wink:

Guglielmo