parsing stringa

Buongiorno ragazzi,

sono riuscito a passare le stringhe dal mio webserver alla barra degli indirizzi.
Adesso ottengo una stringa tipo questa:
GET /L1on=Ciao&L1off=aaa&L2on=bbbbb&L2off=ccc&L3on=ddd&L3off=eeee&L4on=mmmmmmm&L4off=qqff=qq

poichè la lunghezza delle stringhe è variabile come potrei fare per inserirle in 8 stringhe separate il testo?

Buongiorno anche a te.
Io sinceramente non ho capito la domanda.
"per inserirle in 8 stringhe separate il testo" che vuol dire?

Si scusa, mi sono spiegato male.

Dalla stringa di partenza che mi arriva tramite il comando GET vorrei ricavarne 8 più piccole.

Praticamente come questo esempio
GET /L1on=Ciao&L1off=aaa&L2on=bbbbb&L2off=ccc&L3on=ddd&L3off=eeee&L4on=mmmmmmm&L4off=qqff
stringa1: Ciao
stringa2:aaa
stringa3: bbbbb
stringa4:ccc
stringa5: ddd
stringa6:eeee
stringa7: mmmmmmm
stringa8:qqff

il problema è che tutti i testi hanno una lunghezza variabile. Quindi non posso dire leggi da tot a tot

Devi usare le funzioni che sono in string.h ...
... in particolare guarda strchr() con la quale ti vai a cercare i vari separatori e la strncpy() con cui ti copi i vari pezzi.

Ovviamente io parlo del tipo string puro del C, ovvero array di char, non della classe String () ]:smiley:

Guglielmo

Per inciso ...

... naturalmente è anche possibile la strada di un ciclo di FOR che scansiona carattere a carattere la stringa e identifica i vari separatori e, sempre con un secondo ciclo di FOR, è possibile spostare carattere a carattere dei pezzi da una parte all'altra, ma, contrariamente ad altre "pessime funzioni" che si possono trovare in giro, quelle presenti nella AVR libc, sono scritte in modo molto efficiente :wink:

A suo tempo provai a rimpiazzare alcune di queste con i cicli FOR e il risultato fu ... un codice più grande e meno fluido ... :grin:

Guglielmo

P.S. : Non occorre includere <string.h> ... come detto fa parte della AVR libc che è inclusa automaticamente :wink:

Grazie per le risposte.

Stavo buttando giù qualche riga di codice, pensavo di fare una cosa del genere

String stringa="GET /L1on=Ciao&L1off=aaa&L2on=bbbbb&L2off=ccc&L3on=ddd&L3off=eeee&L4on=mmmmmmm&L4off=qqff";

String risultato1;
String risultato2;
void setup() {

  Serial.begin(9600);

}

void loop() {
  risultato1=risultato2=0;
  
 //legge il primo pezzo
  int firstClosingBracket1 = stringa.indexOf('='); 
  int firstClosingBracket2 = stringa.indexOf('&'); 
  for(int i=firstClosingBracket1; i<firstClosingBracket2 -1;i++){
  risultato1+=stringa.charAt(i);}  
  

//legge il secondo pezzo
  int secondClosingBracket1 = stringa.indexOf('=', firstClosingBracket1 + 1 );
  int secondClosingBracket2 = stringa.indexOf('&', firstClosingBracket2 + 1 );
  for(int i=secondClosingBracket1; i<secondClosingBracket2 -1;i++){
  risultato2+=stringa.charAt(i);} 

delay(10000);

}

Adesso non ho arduino con me ma penso che dovrebbe estrarre le prime 2 stringhe.
Secondo te come posso semplificare il codice facendo fare tutto ad un ciclo for?

Come credo fosse evidente dal mio post ... NON uso la classe String (... è da suicidio su una MCU piccolina come quella di Arduino), ma ... se ti studi il reference vedi che è possibile comunque accedere agli elementi , quindi ...

Guglielmo

P.S. : Occhio che a giocare con il tipo String con solo 2 KB di SRAM ... porta facilmente ad andare fuori di memoria ... ]:smiley:

blasted:
Secondo te come posso semplificare il codice facendo fare tutto ad un ciclo for?

Beh, di sicuro non puoi sperare di memorizzare tutte le 8 stringhe.
Ne hai sempre 8? A volte possono essere 3? Magari domani cambi il programma e le stringhe saranno 10 ?

Ogni volta che leggi una stringa ottieni uno dei valori e lo usi.
Oppure piazzi questi valori ottenuti in un array. Ma con gli String è facile che esaurisci la SRAM.
Se sono valori numerici allora puoi convertirli da stringa a numero e lo metti in un vettore di .. long? quanto sono grossi?

Nel for usi il secondo blocco di codice facendo partire firstClosingBracket1 e firstClosingBracket2 a zero.
Cancella risultato1 e tieniti risultato2. Dentro a risultato2 hai la frase che ti serve. La usi e poi azzeri risultato2.
Il tutto in un ciclo fino a che hai analizzato tutta la stringa.

P.S. ma la parte Lon e Loff non ti serve distinguerla?

nid69ita:

blasted:
Secondo te come posso semplificare il codice facendo fare tutto ad un ciclo for?

Beh, di sicuro non puoi sperare di memorizzare tutte le 8 stringhe.
Ne hai sempre 8? A volte possono essere 3? Magari domani cambi il programma e le stringhe saranno 10 ?

@Nid:

Nid ... di sicuro c'è solo la Morte ... ]:smiley: ]:smiley: ]:smiley:

Certo che potrebbe ... basta scrivere un buon "parser" che analizza carattere a carattere, identifica inizio e fine elemento (grazie ai delimitatori) e salva i vari pezzi ... un ciclo FOR principale con dei clicli interni ... ma ... ripeto, non credo ne valga la pena, specie se usi le string del C ... :roll_eyes:

Guglielmo

@Guglielmo, mi sono spiegato male.
Non può in un for pretendere di memorizzare in 8 variabili diverse risultato1, risultato2, etc. fino a 8 :grin:

Può usare array, ma @Blasted è partito da variabili semplici.

@Nid :

No, è vero, però basta che usi un array dimensionato per il massimo e ... invece di risultato1, risultato2, ecc. avrai risultato[ i ] dove i è un indice gestito nel FOR ... ]:smiley:

Guglielmo

@nid69ita
le stringhe che la pagina web trasferisce saranno sempre 8, l'unica eccezzione è che una stringa può essere vuota. Per esempio:
GET /**L1on=&**L1off=aaa&L2on=bbbbb&L2off=ccc&L3on=ddd&L3off=eeee&L4on=mmmmmmm&L4off=qqff

P.S. ma la parte Lon e Loff non ti serve distinguerla?

no non mi interessa

Mi avete convinto :smiley: passo all'array e lascio stare le string così posso fare un ciclo for e fare tutto in automatico.
La dimensione massima è di 20.

ripensandoci, io ho 20 caratteri per 8 stringhe dovrei utilizzare una matrice o no?

blasted:
ripensandoci, io ho 20 caratteri per 8 stringhe dovrei utilizzare una matrice o no?

Si, un array bidimensionale di 8 x 21 elementi (20 caratteri + 1 ... il terminatore di stringa 0x00):

char elementi[8][21];

... il numero di elemento va da 0 a 7 ed il numero di carattere nell'elemento va da 0 a 20.

Ricorda che sia "elementi" che "elementi[ i ]" ... sono dei pointer, mentre "elementi[ i ][ j ]" è un char :wink:

Guglielmo

Scusa la curiosità (se puoi) ma che rappresentano quei 20 caratteri max? Immaginavo il valore RGB (colori) dei led, invece ?

nid69ita:
Scusa la curiosità (se puoi) ma che rappresentano quei 20 caratteri max? Immaginavo il valore RGB (colori) dei led, invece ?

Praticamente sto creando una scheda con 4 ingressi,
in base al valore logico degli ingressi l'arduino deve inviare una stringa diversa tramite seriale.
I testi però devono essere modificabili tramite un webserver.

ragazzi, sto iniziando a perdere tutti i capelli :disappointed_relieved:

sono arrivato a questo punto. Praticamente genero prima tutti gli inizi e fine dei messaggi ( e fin qui tutto funziona), dopo cerco di esportarli

    char elementi[8][21];
    int n=0;
    void htmlToHuman(String URLstring) {
      Serial.println(URLstring);

        int indexinizio[8] ;  //questo cerca gli uguali
        int indexfine[8]; //questo cerca le &

         
      for(int z=0; z<8; z++){ //cerca l'inizio e la fine
      if(z==0){
              indexinizio[z] = URLstring.indexOf("=");
               indexfine[z] = URLstring.indexOf("&");
      }else{

        indexinizio[z] = URLstring.indexOf("=", indexinizio[z-1]+1);
         if(z!=7)
          indexfine[z] = URLstring.indexOf("&", indexfine[z-1]+1);
        }//fine else
        //adesso conosco da dove iniziano a dove finiscono le lettere
      }
      
      
      for(int z=0; z<8; z++){
                  if(z!=7){
                            for(int i=indexinizio[z]; i<indexfine[z];i++){
                              elementi[z][i]=URLstring.charAt(n);
                              n++;
                              Serial.println(elementi[z][i]);
                         }
            }//se è = a 7 cioè vede la lunghezza massima della stringa
                  else
                  {
                    for(int i=indexinizio[z]; i<=URLstring.length();i++)
                    {
                        elementi[z][i]=URLstring.charAt(n); 
                        Serial.println(elementi[z][i]);
        }}
       
           n=0;        

  }// fine for principale

        return;
    }
    
        
    void setup(){ Serial.begin(9600); }
    
    
    void loop(){
      htmlToHuman("GET /L1on=Ciao&L1off=aaa&L2on=bbbbb&L2off=ccc&L3on=ddd&L3off=eeee&L4on=mmmmmmm&L4off=qqff");
      delay(10000);
    }

Secondo voi che sbaglio?

Scusa, ma perché continui ad usare la classe String e a mischiare quindi le due cose ???

void htmlToHuman(String URLstring)

Trasforma tutto in stringhe classiche del C ... <<array di char "NULL" terminated>> e lavora passo passo esaminando dall'inizio alla fine la stringa ...

Quando incontri il delimitatore di inizio ti segni il valore dell'indice in "inizio", quando incontro quello di fine ti segni il valore in "fine", (fine - inizio) ti da la lunghezza di quello che devi copiare nell'elemento, fai un banale ciclo da 0 a lunghezza e copi i caratteri, aggiungi alla fine lo 0x00 e prosegui la scansione alla ricerca del prossimo inizio ... e il tutto si ripete fino alla fine della stringa :slight_smile: ... e senza usare quelle istruzioni che lavorano sulla classe String ]:smiley:

Guglielmo

Ragazzi, ci sono riuscito rimpiazzando tutto con i vettori!

Però penso che il mio progetto non si possa completare poichè secondo me la ram dell'arduino è troppo poca.

Vi spiego cosa vorrei realizzare:
praticamente una pagina web con 8 textbox, nelle quali io scrivo dei testi (massimo 20 caratteri). Dopo, vorrei memorizzarle nella eeprom così quando lo spengo e l'accendo non perdo i testi già immessi.
I testi dopo verranno inviati tramite seriale uno alla volta.

Vi allego una parte dello sketch che si occupa di prendere i dati e inserirli nel vettore.

Beh ... 8 x 21 = 168 char ... il buffer dove li ricevi ? facciamo 200 char ? ... e siamo a 368 un altro centinaio di byte di variabili varie ? e arriviamo a 468 ... arrotondiamo a 512 ... prima di occupare i 2048 byte che ha Arduino Uno ce ne manca XD XD XD

Guglielmo