Estrappolare parte di una stringa in C

Ciao a tutti, ho un dubbio che non riesco a risolvere.
Ho una stringa la quale è composta da lettere numeri e simboli(es new_file6.7) dentro ad un array di char.
Io vorrei estrappolare solo la parte 6.7, sapendo che non ho una lunghezza costante ma variabile.
Quindi ho pensato di scrivere quanto segue:

char cartella[20];
 char new_cartella[7];
 byte lunghezza=strlen(cartella);
 for (byte i=0;i<lunghezza;i++){
              if((cartella[i]>='0' && cartella[i]<='9')||cartella[i]=='.'){
                 strcat(new_cartella,cartella[i]);
              }
 }
 Serial.print(F("cartella new"));Serial.println(new_cartella);

in cartella è contenuta la stringa, mentre in new_cartella dovrei mettere 6.7.
Ma non funziona...
Sul seriale mi appare


potreste aiutarmi?
Grazie.

Prova così:

char cartella[20];
char new_cartella[7];
byte lunghezza=strlen(cartella);
byte pos=0;
for (byte i=0;i<lunghezza;i++){
              if((cartella[i]>='0' && cartella[i]<='9')||cartella[i]=='.'){
                 new_cartella[pos]=cartella[i];
                 pos++;
              }
 }
new_cartella[pos]=0;
 Serial.print(F("cartella new"));Serial.println(new_cartella);

Dovrebbe funzionare, comunque ho omesso di controllare che il valore di "pos" non ecceda la lunghezza dell'array, casomai aggiungilo.

Ciao, Ale.

Se i tre numeri di versione sono sempre gli ultimi 3 caratteri invece di scansionare tutta la stringa puoi fare una cosa del genere:

	char new_cartella[7];
	int lunghezza=strlen(cartella);
	for(byte i=1; i<4; i++)
	{
		new_cartella[3-i] = cartella[lunghezza-i];
	}
	new_cartella[3] = '\0';

In AVR libc, <string.h> ci sono tante belle funzioncine che fanno quelle operazioni in modo molto più elegante e veloce (la maggior parte sono scritte in assembler) ... :wink:

Guglielmo

Ciao Fabpolli, no i caratteri sono più di tre, quindi direi che la soluzione di ilguargua mi va bene...provata e fuzniona ...Grazie
Guglielmo, ho letto la libreria ma forse io non sono così bravo da usare le funzioni in maniera elegante :stuck_out_tongue_winking_eye:
sono più spartano :grimacing:
Mi fai vedere te come si può rendere il codice più elegante??
Grazie.

... in reltà stavo rispondendo a fabpolli dato che avrebbe potuto facilmente eliminare quel for per spostare i caratteri da una parte all'altra con un semplice e veloce memcpy(), inoltre, in generale, per verificare se un dato carattere è numerico, basta usare la isdigit().

Dato però che, purtroppo, non hai un numero di digit fisso (male, avresti potuto aggiungere zeri davanti per rendere il numero di lunghezza fissa), il codice di fabpolli non si può usare e quindi la soluzione di ilguargua è quella che ti va bene.

Visto comunque che parliamo di strighe classiche del 'C', che sono sempre NULL terminated, io lo avrei scritto così :slight_smile::

void setup() {
   char cartella[] = "abcdefghi123.45";
   char new_cartella[7];
   byte i, j;
   //
   delay ( 500 );
   Serial.begin ( 115200 );
   //
   i = 0;
   j = 0;
   while ( cartella[i] != 0x00 ) {
      if ( isdigit ( cartella[i] ) || cartella[i] == '.' ) {
         new_cartella[j] = cartella[i];
         j++;
      }
      i++;
   }
   new_cartella[j] = 0x00;
   //
   Serial.print ( F ( "Valore estratto = " ) );
   Serial.println ( new_cartella );
}

void loop() {

}

Guglielmo

P.S.: ma la struttura almeno è sempre quella? Ovvero, una parte alfabetica davanti con attaccato un valore numerico? Perché, se è così, forse allora si può ottimizzare ancora un pochino ... :roll_eyes:

... ovvero, se si ha SEMPRE una struttura di tipo "xxxxxxxxxNNN.NN" con 'x' caratteri alfabetici e N caratteri numerici allora, sempre ricordando di dimensionare per il massimo le strigne di origine e di destinazione, la cosa si semplifica così:

void setup() {
   char cartella[] = "abcdefghi123.45";
   char new_cartella[7];
   byte i;
   //
   delay ( 500 );
   Serial.begin ( 115200 );
   //
   i = 0;
   while ( isalpha ( cartella[i] ) ) i++;
   strcpy ( new_cartella, &cartella[i] );
   //
   Serial.print ( F ( "Valore estratto = " ) );
   Serial.println ( new_cartella );
}

void loop() {

}

Ribadisco, funziona se si ha sempre la stessa struttura, un numero non definito di caratteri alfabetici seguito da un numerico (con o senza punto decimale) e purché le due variabili siano ben dimensionate.

Guglielmo

Si, la struttura è una parte inizale alfabetica, ed una parte (variabile) numerica divisa dal punto...la parte numerica non è sempre uguale come dimensioni...

... quello NON è importante, basta che dimensioni per la massima lunghezza la stringa ricevente (nel tuo caso "new_cartella") ... se la struttura è fissa, allora va bene il mio secondo esempio :wink:

Guglielmo

Ottimo, grazie lo provo...

Guglielmo, ho provato ma c'è un limite...che giustamente non avevo considerato...
Se nella cartella vi sono caratteri come _ o - si blocca e non estrae la parte numerica.
_ o - non sono considerati caratteri??

Prova a modificare così:

while ( isalpha ( cartella[i] ) || ispunct ( cartella[i] )) i++;

Ciao, Ale.

Grazie!!
Non conoscevo queste funzioni del C...
Grazie!

Leggi qui, così ti fai una cultura! :wink:
Le funzioni del tipo "isXXXX" le trovi ad esempio in c_type.h, ma dai un'occhiata anche a tutto il resto.

Ciao, Ale.

Avrò detto e ripetuto 1000 volte su questo forum di studiarsi la AVR libc (che ti ha anche indicato ilguargua) ... è piena di moduli che semplificano parecchio la vita ... :roll_eyes:

Guglielmo

:grimacing:
RAGIONISSIMO....
Grazie.