Svuotare Stringa

Ricevo dei dati da un modem gsm i quali vengono salvati in una stringa tmp:

    while(Serial.available()>0){
      tmp=tmp.concat(byte(Serial.read()));
    }
    Serial.println(tmp);

se pero poi do il comando

    tmp="";

questa non viene svuotata cioè se la ristampo il contenuto è uguale a quello precedente. Come posso fare??

Grazie

tmp = String('');

Grazie, poi provo :slight_smile:

forse è meglio fare
free(tmp); //rilasci l'area dei memoria della stringa
tmp = String(''); //crei un nuovo oggetto Stringa

altrimenti crei garbage in ram

Grazie lesto!! Proverò allora questo modo.

Basterebbe mettere alla prima posizione della stinga uno zero. Cosí termina lí.
Ciao Uwe

uwefed, sembra corretto, ma se poi lavori con length della stringa etc... mi sa che ti ritornano valori sballati. Dipende se queste variabili sono ricalcolate al volo o bufferizatte, e se il settaggio del carattere gestisce questo caso particolare.

Ciao lesto
Non ho provato ma credo che se chiama la funzione che Ti da la lunghezza della stringa lo calcola in quel momento.
Ciao Uwe

non è solo la lunghezza della stringa in se, ma anche le malloc che fa internamente etc... metti caso che ha lunghezza 5, tu forzi l'1 a essere '\0', ma che succede a quelle dopo? e se poi concateni, concateni dopo l'1 o dopo il 5? bho

Per non susictare malintesi sforzo il 0 non l'1.

Ma ho lo stesso problema se la stringa é prima lunga 10 caratteri e po la carichi con una parla da 5 caratteri?

Ciao Uwe

Per non susictare malintesi sforzo il 0 non l'1.

okok, il problema si presenta per qualsiasi valore < della lunghezza della stringa

Ma ho lo stesso problema se la stringa é prima lunga 10 caratteri e po la carichi con una parola da 5 caratteri?

dipende come lo fai.
Se forzi i caratteri al suo interno mettendo lo '\0' al 6 elemento hai lo stesso problema di cui sopra, se invece crei un'altra istanza di stringa e giochi con i puntatori rischi di creare garbage ma il metodo è corretto.. (la soluzione che ho proposto, in pratica)

edit: comunque ripeto, bisogna testare come lavora la String, sono solo supposizioni

lesto:
edit: comunque ripeto, bisogna testare come lavora la String, sono solo supposizioni

Concordo anch io.
Ciao Uwe

lesto:
bisogna testare come lavora la String, sono solo supposizioni

Ma se ci sono i sorgenti, cosa devi testare? Basta leggerli. (hardware/arduino/cores/arduino/WString.cpp)

In ogni caso, nella versione attuale:

  1. la lunghezza non viene ricalcolata (ritorna il membro _length).
  2. assegnare una nuova stringa con = rialloca la memoria solo se la stringa nuova e' piu' grande.
  3. l'operatore [] fa pena... ]:slight_smile:
  4. mai usare free su un oggetto. Se serve veramente un free della stringa e non dell'oggetto devi in questo caso estendere la classe ed implementare a manina il free

ad esempio (ed e' solo un esempio, non testato, non elaborato):

class String2: public String {
	public:
	    void newString(int maxStrLen) {
		free (_buffer);
		getBuffer(maxStrLen);
	    }
};

Avevo provato anche io a mettere un "\0" come primo carattere per vedere se la stringa si svuotava ma da quello che ho capito la lunghezza non variava, mi veniva infatti restituita la stringa senza il primo carattere e basta. Io non sono molto conosco il c++ in cui è scritta la libreria WString ma sarebbe utile una funzione del tipo empty() che cambi il parametro length della stringa azzerandolo.

@scjurgen hai ragione, bastava dare un'occhiata ai sorgenti :slight_smile:

sulla free mi scuso ma io arrivo da java dove se ne occupa il garbage collector... che è una bella comodità

Insomma alla fine l'oggetto String è stato implementato alla meno peggio... Se avete fatto qualche modifica postatela, che le raccolgo tutte e proponiamo una nuova versione di String, che messa così più che aiutare fà impazzire i niubbi e non solo :slight_smile:

@uwe: peggio di quel che si pensava...

Non ho capito quindi cosa devo fare :roll_eyes: ....Grazie

Non ho capito quindi cosa devo fare

Hai ragione, ci siamo persi.

In realta', tmp=""; dovrebbe resettare la stringa. Che non funzioni nel tuo specifico caso sembra dovuto ad un problema diverso. Puoi isolare il problema e' postare un po' di codice completo nel suo contesto?

poi, cerca di usare: tmp+=(byte)Serial.read();

lesto:
Se avete fatto qualche modifica postatela, che le raccolgo tutte e proponiamo una nuova versione di String, che messa così più che aiutare fà impazzire i niubbi e non solo :slight_smile:

In se, la classe va abbastanza bene. Il problema e' come viene usata, in questo caso l'incapsulamento non e' al vantaggio per un sistema come Arduino che ha veramente poche risorse.

Certo, le funzioni sono possono rendere tutte piu' robuste, ma ha un costo in termini di efficienza e memoria (sia ROM, sia RAM). Se ad esempio si modifica l'operatore [] e si controlla che non va oltre i limiti e se mette un 0 e quindi si ricalcola la lunghezza si crea un overhead. Ovviamente, diventa piu newbie friendly, ma anche meno efficiente.

Credo che la classe String e un buon compromesso tra robusto ed efficiente ma nello stesso momento facile da usare.

E' molto importante IMHO che il programmatore prende un po' di responsabilita' e' studia bene cosa fa un programmino in C per creare codice efficiente e coretto.

Allora il mio progetto è un arduino con connesso un modulo gsm. Fatta l'inizializzazione ogni 3 sec esegue questa operazione:

void check_sms(){
    int i=0;
    String tmp = String("");
    //Serial.println("controllo sms");
    Serial.print("AT+CMGL=");
    Serial.print(34,BYTE); 
    Serial.print("REC UNREAD"); 
    Serial.println(34,BYTE); 
    Serial.flush();
    delay(500);
    while(Serial.available()>0){
      tmp=tmp.concat(byte(Serial.read()));
    }
    Serial.println(tmp);
      if((i=tmp.indexOf("Changephone"))!=-1){
        //Serial.println("entro in cambio numero");
        i=tmp.indexOf("3",i);
        number=tmp.substring(i,i+10);
        for(int l=0; l<10; l++){
           EEPROM.write(l,number.charAt(l));
        }
        //Serial.println("Stampo numero da memoria: ");
        number="";
        for(int l=0; l<10; l++){
          number=number.concat(EEPROM.read(l));
        }
        String tmp = String("");
        String message = "Prova nuovo numero di ricezione errori:";
        message = message + number; 
        send_sms(message);
        Serial.println("Cancello vecchi messaggi");
        Serial.println("AT+CMGD=1,1");
        delay(500);
        while(Serial.available()>0){
          tmp=tmp.concat(byte(Serial.read()));
        }
        Serial.println(tmp);
      }
  }

praticamente vedo se ci sono nuovi sms e se presente la sottostring changephone estraggo il numero posto dopo e lo salvo in memoria, fatto questo invio un sms di prova al nuovo numero in memoria. Il fatto è che la stringa che leggo da pc appena avviato il sistema è:

AT+CMGL="REC UNREAD"
AT+CMGL="REC UNREAD" OK

non essendoci sms da leggere, giunto un nuovo sms invece certe volte riappare la scritta sopra corretta altre invece è come se andasse in blocco la seriale e mi compare

AT+CMGL="REC UNREAD"
//qualche scritta di stringhe vecchie

non quoto perché la risposta è unica per varie affermazioni.
Il problema di String, è che semplicemente esistono metodi per ingrandirla, per ridurla(substring) ma non per cancellarla, il che, secondo me, è una grave mancanza.
Bisogna quindi modificare la classe String per aggiungere un metodo clear() o simile, e chiedere che venga incluso nella libreria ufficiale.

Noto che però è stato scritto il distruttore della classe String... quindi per ora la soluzione è distruggere il vecchio oggetto stringa e crearne uno nuovo.
quindi:

tmp.~String(); //distruggo il contenuto dell'oggetto, per evitare garbage
tmp = String(); //creo la nuova classe String, i vecchi puntatori/valori sono sovrascritti perché l'area di memoria è sempre la stessa

giusto?

ypkdani:
Allora il mio progetto è un arduino con connesso un modulo gsm. Fatta l'inizializzazione ogni 3 sec esegue questa operazione:

[...]

String tmp = String("");
[...]
    if((i=tmp.indexOf("Changephone"))!=-1){
[...]
        String tmp = String("");

Hai due volte String tmp. Cosi stai facendo il shadowing del primo tmp con il secondo che in un altro blocco.

Ci sono varie cose da risolvere.

  1. buffering della seriale
  2. togliere tutti i write delle EEPROM, la EEPROM del Arduino e' 'delicata' e non dovresti scrivere cosi spesso dei dati.
  3. aggiungere controlli se i dati arrivati sono 'sani'