Verifica formato stringa C

di il
15 risposte

Verifica formato stringa C

Salve a tutti
sto sviluppando un programma in C sul rasberry con Debian, per recuperare valori dei sensori di temperatura.

Ho un problema con un formato di un valore che ogni tanto cambia.
Mi spiego meglio: il valore della temperatura che dovrebbe essere 18.55, ad un certo punto mi viene recuperato 185.5.

Di seguito il codice

void Raspy_DS18B20(char *ip_sn,char *sensore,char *area,char *device) { //Sensore DS18B20 collegato al raspberry
  char devPath[128]; // Path to device
  char buf[256];     // Data from device
  char tmpData[6];   // Temp C * 1000 reported by device
  char path[] = "/sys/bus/w1/devices";
  ssize_t numRead;
  char temperature[6];

        // Assemble path to OneWire device
  sprintf(devPath, "%s/%s/w1_slave", path, ip_sn);

  int fd = open(devPath, O_RDONLY);
  if(fd == -1)
  {
    perror ("Couldn't open the w1 device.");
  }

  while((numRead = read(fd, buf, 256)) > 0)
  {
    strncpy(tmpData, strstr(buf, "t=") + 2, 5);
    float tempC = strtof(tmpData, NULL);
    tempC=tempC/1000;
    snprintf(temperature,6,"%f",tempC);
    printf("%f\n",tempC);
    printf("%s\n",temperature);
    syslog(LOG_DAEMON || LOG_WARNING,"DS18B20 camera Float: %f\n",tempC);
    syslog(LOG_DAEMON || LOG_WARNING,"DS18B20 camera String: %s\n",temperature);
  }

  close(fd);

  memset(StringaSQL, 0, 200);
  sprintf(StringaSQL, "INSERT INTO TemperatureLOG (TimeLog,Zona,Sensore,T,U) VALUES (CURRENT_TIMESTAMP,'%s','%s',%s,'0')", area, sensore, temperature);
  printf("insert: %s\n",StringaSQL);

  insertMySQL(StringaSQL);

}

La mia idea è di fare un check che il formato della temperatura sia sempre del formato
- ##.## oppure
- #.## oppure
- ##.#

Accetto ovviamente anche suggerimenti per modificare il mio codice (ammetto non essere il massimo) in quanto il problema del valore con la virgola modificata, non è dato dal sensore, ma sono quasi sicuro dal codice.

Grazie in anticipo a tutti per l'aiuto

15 Risposte

  • Re: Verifica formato stringa C

    Non mi è chiaro il quesito, quando dici "ad un certo punto mi viene recuperato 185.5"
  • Re: Verifica formato stringa C

    oregon ha scritto:


    Non mi è chiaro il quesito, quando dici "ad un certo punto mi viene recuperato 185.5"
    nel senso che si sballa il valore, da 18.55 che mi viene restituito dalla variabile "temperature", ricevo successivamente 185.5

    Spero di essermi spiegato meglio
  • Re: Verifica formato stringa C

    Prova ad usare più caratteri nella stringa temperature. Usane 20
  • Re: Verifica formato stringa C

    oregon ha scritto:


    Prova ad usare più caratteri nella stringa temperature. Usane 20
    fatto
    ma ho un modo per ripulire/resettare in qualche modo maggiormente efficace le variabili?
  • Re: Verifica formato stringa C

    rdie77 ha scritto:


    oregon ha scritto:


    Prova ad usare più caratteri nella stringa temperature. Usane 20
    fatto
    ma ho un modo per ripulire/resettare in qualche modo maggiormente efficace le variabili?
    Ho fatto altra prova, estrapolando la funzione in un programma a se stante
    Codice
    
    void main() { //Sensore DS18B20 collegato al raspberry
      char devPath[128]; // Path to device
      char buf[256];     // Data from device
      char tmpData[6];   // Temp C * 1000 reported by device
      ssize_t numRead;
      char temperature[6];
    
            // Assemble path to OneWire device
    
      int fd = open("/sys/bus/w1/devices/28-0516b33933ff/w1_slave", O_RDONLY);
      if(fd == -1)
      {
        perror ("Couldn't open the w1 device.");
      }
    
      while((numRead = read(fd, buf, 256)) > 0)
      {
        strncpy(tmpData, strstr(buf, "t=") + 2, 5);
        printf("tmpData %s\n",tmpData);
    
    float f;
    //sscanf(tmpData, "%f", &f);
    f = atof(tmpData);
    f=f/1000;
    //printf("%f\n",f);
    printf("diviso:%f\n",f);
    
    snprintf(temperature,6,"%2.2f",f);
    
    
    //f=printf("%2.2f\n",f);
    //printf("%2.2f\n",f);
    printf("formattato:%s\n",temperature);
    
      }
    
      close(fd);
    
    
    }
    
    

    OUTPUT
    
    [17:26:28] root@raspy:/var/www/script/script_c/TEST# ./ds18b20_new
    tmpData 19437¦¦v37 01 4b 46 7f ff 0c 10 d9 : crc=d9 YES
    37 01 4b 46 7f ff 0c 10 d9 t=19437
    
    diviso:19.437000
    formattato:19.44
    [17:26:30] root@raspy:/var/www/script/script_c/TEST# ./ds18b20_new
    tmpData 194376¦v37 01 4b 46 7f ff 0c 10 d9 : crc=d9 YES
    37 01 4b 46 7f ff 0c 10 d9 t=19437
    
    diviso:194.376007
    formattato:194.3
    
    Lanciando il programma più volte, sembra che per qualche motivo qualche volta mi fallisce il /1000...dove sbaglio?come posso risolvere?
  • Re: Verifica formato stringa C

    rdie77 ha scritto:


    
    [17:26:28] root@raspy:/var/www/script/script_c/TEST# ./ds18b20_new
    tmpData 19437¦¦v37 01 4b 46 7f ff 0c 10 d9 : crc=d9 YES
    37 01 4b 46 7f ff 0c 10 d9 t=19437
    
    [17:26:30] root@raspy:/var/www/script/script_c/TEST# ./ds18b20_new
    tmpData 194376¦v37 01 4b 46 7f ff 0c 10 d9 : crc=d9 YES
    37 01 4b 46 7f ff 0c 10 d9 t=19437
    
    Scommetto che non hai pensato di prendere come valore l'ultimo!
    t=19437
    Magari nella documentazione c'è scritto...
  • Re: Verifica formato stringa C

    È dura senza documentazione.

    Nel frattempo io proverei a inserire tmpData[5] = 0;
    appena dopo strncpy(tmpData, ...
  • Re: Verifica formato stringa C

    .
  • Re: Verifica formato stringa C

    nicolap ha scritto:


    rdie77 ha scritto:


    
    [17:26:28] root@raspy:/var/www/script/script_c/TEST# ./ds18b20_new
    tmpData 19437¦¦v37 01 4b 46 7f ff 0c 10 d9 : crc=d9 YES
    37 01 4b 46 7f ff 0c 10 d9 t=19437
    
    [17:26:30] root@raspy:/var/www/script/script_c/TEST# ./ds18b20_new
    tmpData 194376¦v37 01 4b 46 7f ff 0c 10 d9 : crc=d9 YES
    37 01 4b 46 7f ff 0c 10 d9 t=19437
    
    Scommetto che non hai pensato di prendere come valore l'ultimo!
    t=19437
    Magari nella documentazione c'è scritto...

    Ma infatti io prendo l'ultimo valore.
    Infatti nel codice postato c'è
    
    strncpy(tmpData, strstr(buf, "t=") + 2, 5);
    
    per questo credo che il problema sia della divisione, che per qualche motivo che non riesco a capire, non funziona sempre bene
  • Re: Verifica formato stringa C

    rdie77 ha scritto:


    per questo credo che il problema sia della divisione, che per qualche motivo che non riesco a capire, non funziona sempre bene
    Secondo me, ma magari mi sbaglio, l'ultimo byte di tmpData è diverso da zero per motivi ignoti. O hai disattivato l'inizializzazione a zero delle variabili oppure lo stai sovrascrivendo in qualche modo. Prova a forzarlo a zero
  • Re: Verifica formato stringa C

    rdie77 ha scritto:


    Ma infatti io prendo l'ultimo valore.
    Infatti nel codice postato c'è
    
    strncpy(tmpData, strstr(buf, "t=") + 2, 5);
    
    per questo credo che il problema sia della divisione, che per qualche motivo che non riesco a capire, non funziona sempre bene
    Secondo me quella riga di codice è sbagliata: cosa succede se strstr non trova il testo "t="?
    Poi usi la funzione "read" per leggere un file di testo, pessima idea.

    @weierstrass: documentazione ne trovi anche troppa: google "raspberry pi 1-wire ds18b20"...
  • Re: Verifica formato stringa C

    nicolap ha scritto:



    @weierstrass: documentazione ne trovi anche troppa: google "raspberry pi 1-wire ds18b20"...
    Sì ma c'è un driver di mezzo: quel chip comunica due byte sul bus 1-wire, non certo le stringhe che ricevi tu. Dovresti trovare e spulciare la documentazione ufficiale di quel driver, non degli esempi su internet

    In ogni caso, a me non pare ragionevole che tmpData abbia il sesto byte diverso da zero con uno strncpy da cinque byte, io indagherei su quello. Poi se ti sembra la strada sbagliata sei padrone dellle tue azioni
  • Re: Verifica formato stringa C

    Weierstrass ha scritto:


    nicolap ha scritto:



    @weierstrass: documentazione ne trovi anche troppa: google "raspberry pi 1-wire ds18b20"...
    Sì ma c'è un driver di mezzo: quel chip comunica due byte sul bus 1-wire, non certo le stringhe che ricevi tu. Dovresti trovare e spulciare la documentazione ufficiale di quel driver, non degli esempi su internet

    In ogni caso, a me non pare ragionevole che tmpData abbia il sesto byte diverso da zero con uno strncpy da cinque byte, io indagherei su quello. Poi se ti sembra la strada sbagliata sei padrone dellle tue azioni
    Quello è l'output del driver. Se non ti piace lo interroghi direttamente, altrimenti fai il parse e basta.
    strncpy(tmpData, strstr(buf, "t=") + 2, 5);
    In questo codice ci sono almeno 3 errori e 1 orrore:
    1) il valore restituito da strstr viene usato senza controlli: un classico e comunissimo casi di NON controllo dell'input;
    2) vengono usate delle costanti (2 e 5). Se il 2 può anche essere accettato il 5 ASSOLUTAMENTE NO! Devi contare quanti caratteri ci sono fino al successivo terminatore; o fino alla fine del buffer usato;
    3) non hai letto con attenzione il manuale:
    function
    <cstring>
    strncpy

    char * strncpy ( char * destination, const char * source, size_t num );

    Copy characters from string
    Copies the first num characters of source to destination. If the end of the source C string (which is signaled by a null-character) is found before num characters have been copied, destination is padded with zeros until a total of num characters have been written to it.

    No null-character is implicitly appended at the end of destination if source is longer than num. Thus, in this case, destination shall not be considered a null terminated C string (reading it as such would overflow).

    destination and source shall not overlap (see memmove for a safer alternative when overlapping).
    La parte in grassetto: qua la spiegazione https://www.geeksforgeeks.org/why-strcpy-and-strncpy-are-not-safe-to-use/

    Mi rendo conto che sia complesso ma spero che sia comunque abbastanza chiaro!
  • Re: Verifica formato stringa C

    nicolap ha scritto:


    Mi rendo conto che sia complesso ma spero che sia comunque abbastanza chiaro!
    Veramente a me è chiaro il problema.

    Il mio suggerimento è banalmente questo (lo riscrivo):
    
        strncpy(tmpData, strstr(buf, "t=") + 2, 5);
        tmpData[5] = 0;
        printf("tmpData %s\n",tmpData);
        float f; 
        f = atof(tmpData);
    
    Vediamo che dice l'autore del topic e se ne viene a capo
Devi accedere o registrarti per scrivere nel forum
15 risposte