INFO: Dieses Forum nutzt Cookies...
Cookies sind für den Betrieb des Forums unverzichtbar. Mit der Nutzung des Forums erklärst Du dich damit einverstanden, dass wir Cookies verwenden.

Es wird in jedem Fall ein Cookie gesetzt um diesen Hinweis nicht mehr zu erhalten. Desweiteren setzen wir Google Adsense und Google Analytics ein.

Antwort schreiben 
 
Themabewertung:
  • 0 Bewertungen - 0 im Durchschnitt
  • 1
  • 2
  • 3
  • 4
  • 5
Erweiterung für SD: fprintf_, fgets_, fscanf_
08.03.2015, 17:23 (Dieser Beitrag wurde zuletzt bearbeitet: 08.03.2015 18:56 von HaWe.)
Beitrag #1
Erweiterung für SD: fprintf_, fgets_, fscanf_
hallo,
habe endlich fertig: Cool

es werden ja bekanntlich für SD-Files keine stdio.h -Funktionen unterstützt, z.B. gibt es in der SD-Klasse kein fprintf und kein fscanf,
sondern z.B. Funktionen wie (myFile).print und (myFile).println zum Schreiben,
und nur (myFile).read zum Byte-weise Lesen, was die Sache sehr umständlich macht
(z.B. ein (myFile).readln gibt es nicht, würde aber auch nicht einer C-Standard-Funktion entsprechen!)

Zum Schreiben und Lesen von Strings und formatierter Variablen in SD-Files habe ich daher eigene Funktionen
fprintf_() , fgets_() und fscanf_()
geschrieben, die praktisch genau so arbeiten wie die Originale in ANSI C.

Hier der Sourcecode:

int fprintf_ ( File * stream, const char fmtstr[], ... )
arbeitet wie das stdio.h C-Original fprintf(): Es schreibt einen string in ein file, dabei werden die Variablen/Argumente entsprechend dem formatstring als strings formatiert (gleiche Funktionsweise wie auch bei printf oder sprintf)

char * fgets_ ( char * str, int32_t num, File * stream )
Liest entsprechend der Original C-stdio.h Funktion einen string aus einem File, bis eine String-Terminierung oder ein Zeilenumbruch oder eof() oder die max Länge des übergebenen Puffers erreicht ist (je nachdem, was früher eintritt).
Im Falle dass "mein" fgets_() keine lesbaren Daten findet, wird ein Leerstring ("") zurückgegeben, kein Nullpointer NULL wie bei Original fgets(), da der Nullpointer IMO bei Sketch schwer zu handhaben ist - natürlich kann man das ändern.


int32_t fscanf_ ( File * stream, const char fmtstr[], ... );
liest einen String aus einem File und re-formatiert alle darin enthaltenen Variablen entsprechend dem Formatstring
(also %d zu int und %f zu float)
Achtung: ints müssen int32_t sein, int_16_t ist nicht erlaubt.
teilw. bekannte Probleme mit double, float funktioniert aber.


Aufruf z.B.:
Code:
File myFile;
char sdata[128];

fprintf_(&myFile, "%s\n%d\n%d\n%f\n%f\n", "EinTeststring", 1, 2, PI, 4.567890);
// schreibt die 5 Variablen (1x string, 2x int, 2x float), getrennt durch Zeilenumbrüche, in ein File.
fprintf_(&myFile, "%s %d %d %f %f", "EinTeststring", 1, 2, PI, 4.567890);
// dto, aber getrennt durch Leerzeichen, kein Zeilenvorschub.


fgets_ ( sdata, 20, &myFile );
// liest und kopiert aus der Datei einen Teilstring in den String-Buffer "sdata",
// der dann anschließend als string oder umgewandelt zu int oder float weiterverwendet werden kann.



int32_t  m, n, cnt;
float    x, y;
cnt = fscanf_ ( myFile,  "%d %d %f %f",  &m, &n, &x, &y );
// liest einen String aus einem File,
// re-formatiert alle darin enthaltenen Variablen entsprechend dem Formatstring (%d als ints, %f als floats)
// und weist sie den übergebenen Variablen m,n,x,y zu.

Sourcecode der Funktionen:

Code:
//********************************************************************************​​***********  
int fprintf_ ( File * stream, const char fmtstr[], ... ) {
   char      str[1024];
   va_list   arguments;
   int16_t   num;
    
   va_start( arguments, fmtstr);
   num = vsprintf(str, fmtstr, arguments);
   stream->print(str);
   va_end( arguments );

   return num;
}
//********************************************************************************​​***********

Code:
//********************************************************************************​***********
char * fgets_ ( char * str, int32_t num, File * stream ) {
  int32_t i = 0;
  
  strcpy(str, "");
  while (i < (num - 1)) { // got room for newline and terminating null?
    int16_t ch = stream->read();
    if (ch < 0) // end of file
      break;
    str[i++] = ch;
    if ('\n' == ch) // end of line
      break;
  }
  
  if (i) { // room in buffer for terminating null
    str[i] = 0;
    return str;
  }
  else
  return NULL; // buffer too small or immediate end of file
  // { strcpy(str, ""); return str; } // alternative
}
//********************************************************************************​***********


Code:
//********************************************************************************​​***********  
int32_t  fscanf_ ( File * stream, const char fmtstr[], ... ) {
   const  int32_t   MAXSTRSIZE = 1024;
   char   str[MAXSTRSIZE];
   va_list   args;  
   int16_t   i=0, cnt=0;
   int16_t   chr;
  
   va_start(args, fmtstr);
  
   strcpy(str, "");
   while ( (stream->available()) && (i < MAXSTRSIZE-1) ) {    
      chr = stream->read() ;
      if (chr>=0 && chr!='\n') {
           str[i]=(char)chr;      
           ++i;
      }
      else break;      
   }  
  
   str[++i] = '\0';
                                                        
   cnt = vsscanf ( str, fmtstr, args );  
   va_end(args);
  
   return cnt;
}
//********************************************************************************​​***********



Testcode für fprintf_ und fgets_():
Code:
/*
SD card: fprintf_() und fgets_()
ver 1.01
*/

#include <SPI.h>
#include <SD.h>


// SD Card
#define SD_CSpin 4
File myFile;
char fname[64];

char sdata[128];
char sbuf[128];



//********************************************************************************​***********
char * fgets_ ( char * str, int32_t num, File * stream ) {
  int32_t i = 0;
  
  strcpy(str, "");
  while (i < (num - 1)) { // got room for newline and terminating null?
    int16_t ch = stream->read();
    if (ch < 0) // end of file
      break;
    str[i++] = ch;
    if ('\n' == ch) // end of line
      break;
  }
  
  if (i) { // room in buffer for terminating null
    str[i] = 0;
    return str;
  }
  else
  return NULL; // buffer too small or immediate end of file
  // { strcpy(str, ""); return str; } // alternative
}
//********************************************************************************​***********



//********************************************************************************​***********  
int fprintf_ ( File * stream, const char fmtstr[], ... ) {
   char      str[1024];
   va_list   arguments;
   int16_t   num;
    
   va_start( arguments, fmtstr);
   num = vsnprintf(str, sizeof str, fmtstr, arguments);
   // #debug
   // Serial.println( "string to write to file="); Serial.println( str);    
   stream->print(str);
   va_end( arguments );

   return num;
}
//********************************************************************************​***********  


void setup()
{
  int16_t  p, i, cnt;
  float    x;
  char     sval[20];
  int16_t  ival;
  double   fval;
  
  pinMode(SD_CSpin, OUTPUT);  
  Serial.begin(9600);
  
  sprintf(sbuf,"#: SD Initializing... ");
  Serial.println(sbuf);  

  while(!SD.begin(SD_CSpin) ) {
    sprintf(sbuf,"#: ...SD init failed ");
    Serial.println(sbuf);
    delay(1000);
  }
  
  sprintf(sbuf,"#: ...SD OK !      ");
  Serial.println(sbuf);  
  strcpy(fname,"test.txt");
  
  if (SD.exists(fname) ) {
    sprintf(sbuf,"#: %s exists     ",fname);
    Serial.println(sbuf);  
    
    sprintf(sbuf,"#: Removing %s      ",fname);  
    Serial.println(sbuf);
    
    SD.remove("test.txt");
    // removed: success ?
    if (SD.exists(fname) ) {
       sprintf(sbuf,"#: %s  exists     ",fname);  
       Serial.println(sbuf);  
    }
    else {
       sprintf(sbuf,"#: %s  N/A     ",fname);  
       Serial.println(sbuf);  
     }
  }
    
  
  // open the file. note that only one file can be open at a time,
  // so you have to close this one before opening another.  
  myFile = SD.open(fname, FILE_WRITE);
  
  if (myFile) {
    // if the file opened okay, write to it, then close file:
    sprintf(sbuf,"#: Writing strings to %s ",fname);
    Serial.println(sbuf);
    
    //---------------------------------------------------------------------------------
    // write data to file
    fprintf_(&myFile, "%s\n%d\n%d\n%f\n%f\n", "Teststring", 1, 2, PI, 4.567890);    
    //---------------------------------------------------------------------------------
  
    // close the file:
    myFile.close();
    sprintf(sbuf,"#: %s closed.   ",fname);
    Serial.println(sbuf);  
  }  
  else {
    // if the file didn't open, print an error:
    sprintf(sbuf,"#: error opening %s   ",fname);
    Serial.println(sbuf);      
  }
  
  Serial.println();
  // re-open the file for reading:
  myFile = SD.open(fname);
  if (myFile) {
    sprintf(sbuf,"#: reading %s ",fname);
    Serial.println(sbuf);  
    
    // read from the file until there's nothing else in it:
    i=0;
    cnt=1;  
    
    while (myFile.available()) {
      strcpy(sdata, "");
      fgets_ ( sdata, 20, &myFile );  
      Serial.print(cnt); Serial.print(": string raw="); Serial.println(sdata);
      Serial.println("rueckformatiert:");
      if (cnt==1) {Serial.print("str  ="); Serial.println(sdata); }
      if (cnt==2) {Serial.print("int  ="); Serial.println(atoi(sdata) ); }
      if (cnt==3) {Serial.print("int  ="); Serial.println(atoi(sdata) ); }
      if (cnt==4) {Serial.print("float="); Serial.println(atof(sdata) ); }
      if (cnt==5) {Serial.print("float="); Serial.println(atof(sdata) ); }
      ++cnt;
    }  
    
    // close the file:
    myFile.close();        
    sprintf(sbuf,"#: %s closed. ",fname);
    Serial.println(sbuf);      
  } else {
    // if the file didn't open, print an error:
    sprintf(sbuf,"#: error opening %s   ",fname);      
    Serial.println(sbuf);

  }
}

void loop()
{
  // nothing happens after setup
}


Testcode für fprintf_() und fscanf_():
Code:
/*
SD card: fprintf_() und fscanf_()
ver 0.04
*/

#include <SPI.h>
#include <SD.h>
#include <stdarg.h>
#include <stdio.h>


// SD Card
#define SD_CSpin 4
File myFile;
char fname[64];

char sdata[128];
char sbuf[128];



//********************************************************************************​​***********  
int32_t  fscanf_ ( File * stream, const char fmtstr[], ... ) {
   const  int32_t   MAXSTRSIZE = 1024;
   char   str[MAXSTRSIZE];
   va_list   args;  
   int16_t   i=0, cnt=0;
   int16_t   chr;
  
   va_start(args, fmtstr);
  
   strcpy(str, "");
   while ( (stream->available()) && (i < MAXSTRSIZE-1) ) {    
      chr = stream->read() ;
      if (chr>=0 && chr!='\n') {
           str[i]=(char)chr;      
           ++i;
      }
      else break;      
   }  
  
   str[++i] = '\0';
   // #debug
   // Serial.print("fscanstr:"); Serial.println(str);
                                                        
   cnt = vsscanf ( str, fmtstr, args );  
   va_end(args);

   return cnt;
}


//********************************************************************************​​***********  

int fprintf_ ( File * stream, const char fmtstr[], ... ) {
   char      str[1024];
   va_list   args;
   int32_t   num;
    
   va_start( args, fmtstr );
   num = vsnprintf(str, sizeof(str), fmtstr, args);
   stream->print(str);
   // #debug
  
   va_end( args );
   Serial.print("fprintf_:"); Serial.println(str);
   return num;
}

//********************************************************************************​​***********  


void setup()
{
  int32_t  p, i, cnt;
  char     sval[20];
  int32_t  ival, n, m;
  float   fval, x, y;
  // alternativ, ohne jeden Effekt: float   fval, x, y;

  pinMode(SD_CSpin, OUTPUT);  
  Serial.begin(9600);
  
  sprintf(sbuf,"#: SD Initializing... ");
  Serial.println(sbuf);  

  while(!SD.begin(SD_CSpin) ) {
    sprintf(sbuf,"#: ...SD init failed ");
    Serial.println(sbuf);
    delay(1000);
  }
  
  sprintf(sbuf,"#: ...SD OK !      ");
  Serial.println(sbuf);  
  strcpy(fname,"test.txt");
  
  if (SD.exists(fname) ) {
    sprintf(sbuf,"#: %s exists     ",fname);
    Serial.println(sbuf);  
    
    sprintf(sbuf,"#: Removing %s      ",fname);  
    Serial.println(sbuf);
    
    SD.remove("test.txt");
    // removed: success ?
    if (SD.exists(fname) ) {
       sprintf(sbuf,"#: %s  exists     ",fname);  
       Serial.println(sbuf);  
    }
    else {
       sprintf(sbuf,"#: %s  N/A     ",fname);  
       Serial.println(sbuf);  
     }
  }
    


  
  // open the file. note that only one file can be open at a time,
  // so you have to close this one before opening another.  
  myFile = SD.open(fname, FILE_WRITE);
  
  if (myFile) {
    // if the file opened okay, write to it, then close file:
    sprintf(sbuf,"#: Writing strings to %s ",fname);
    Serial.println(sbuf);
    
    //---------------------------------------------------------------------------------
    // write data to file
    fprintf_(&myFile, "%d %d %f %f\n",  1, 2, PI, 4.567890);    
    //---------------------------------------------------------------------------------
  
    // close the file:
    myFile.close();
    sprintf(sbuf,"#: %s closed.   ",fname);
    Serial.println(sbuf);  
  }  
  else {
    // if the file didn't open, print an error:
    sprintf(sbuf,"#: error opening %s   ",fname);
    Serial.println(sbuf);      
  }
  
  
  
  
  
  // re-open the file for reading:
  Serial.println();
  
  myFile = SD.open(fname);
  if (myFile) {
    sprintf(sbuf,"#: reading %s ",fname);
    Serial.println(sbuf);  
    
    // read from the file until there's nothing else in it:
    i=0;
    cnt=0;  
    strcpy(sdata, "");
    
    //---------------------------------------------------------------------------------
    cnt = fscanf_(&myFile, "%d %d %f %f", &m, &n, &x, &y);
    //---------------------------------------------------------------------------------
                            
    Serial.println("# nach Aufruf cnt=fscanf_ im Hauptprogramm");    
       // Testausgabe:
       Serial.print("returned cnt="); Serial.println(cnt);  
       Serial.println();
       Serial.println("returned reformatted variables m,n,x,y:");
       Serial.println(m);
       Serial.println(n);
       Serial.println(x);
       Serial.println(y);

    
    // close the file:
    myFile.close();        
    sprintf(sbuf,"#: %s closed. ",fname);
    Serial.println(sbuf);      
  } else {
    // if the file didn't open, print an error:
    sprintf(sbuf,"#: error opening %s   ",fname);      
    Serial.println(sbuf);

  }
}

void loop()
{
  // nothing happens after setup
}

share and enjoy! Cool
Alle Beiträge dieses Benutzers finden
Diese Nachricht in einer Antwort zitieren
Antwort schreiben 


Gehe zu:


Benutzer, die gerade dieses Thema anschauen: 1 Gast/Gäste