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
Funktion mit variabler Parameterliste: Parameterliste weiterreichen?
01.03.2015, 13:44 (Dieser Beitrag wurde zuletzt bearbeitet: 01.03.2015 15:13 von HaWe.)
Beitrag #1
Funktion mit variabler Parameterliste: Parameterliste weiterreichen?
hi, wie kann ich eine Funktion mit einer variablen Parameterliste entwerfen, so dass diese intern eine weitere Funktion mit genau derselben (variablen) Parameterliste als Hilfsfunktion aufruft?

also z.B
Code:
#include <stdio.h>
#include <stdarg.h>

int fprintfln ( FILE * stream,  char format[], ... ) {
  char sbuf[100];
  va_list arguments;

   // irgendwie pointer * oder & auf arguments...?
  sprintf(sbuf, format, & arguments ); // ???
  //
  //
  stream->println(sbuf);
  //
}

Selbst die Anzahl der Parameter aus einem verschachtelten Formatstring zu ermitteln ist schon mehr als schwierig (nur die "%" zu zählen reicht sicher nicht aus, s.z.B. %% oder ähnliches).
der Grund hierfür ist, dass ich die gesamte Bandbreite, die C für den Formatstring bietet, nutzen möchte, ich kann aber nicht alles, was es da gibt, selber implementieren; sprintf kann das aber, und um um die Parameterformatierung mit allen Möglichkeiten auszuschöpfen , möchte ich daher sprintf die komplizierte Formatierarbeit überlassen, um dann mit dem Ergebnis-String weiterzuarbeiten.

Ich weiß aber nicht, wie ich die drei Punkte " ... " als Parameter intern an sprintf weiterreichen kann.
Alle Beiträge dieses Benutzers finden
Diese Nachricht in einer Antwort zitieren
01.03.2015, 16:13
Beitrag #2
RE: Funktion mit variabler Parameterliste: Parameterliste weiterreichen?
versuch das mal

// Argumentenzeiger konstrukten
va_list arguments;
// Argumentenzeiger auf das letzte bekannte Argument verweisen
va_start(arguments,format);
// Argumentenzeiger um die Anzahl Bytes des letzten Arguments inkrementieren
va_arg(arguments,char*);

// irgendwie pointer * oder & auf arguments...? --- arguments ist schon ein Pointer, und & wäre die Referenz nicht der Pointer
sprintf(sbuf, format, arguments ); // ???

// Argumentenzeiger dekonstrukten
va_end(arguments);
Alle Beiträge dieses Benutzers finden
Diese Nachricht in einer Antwort zitieren
01.03.2015, 18:59 (Dieser Beitrag wurde zuletzt bearbeitet: 01.03.2015 19:01 von HaWe.)
Beitrag #3
RE: Funktion mit variabler Parameterliste: Parameterliste weiterreichen?
hi, danke für deinen Vorschlag!
ich habe ihn jetzt erstmal ohne File-Funktion als Testform geschrieben, um zu sehen was das interne sprintf macht:
Code:
/*
program: demo multi var args
multivargs 0007
Sketch: 1.6.0
This example code is in the public domain.
*/

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

char sbuf[512];

char * fprintfln (char * str,  char fmtstr[], ... )
{
    va_list arguments;                    

    va_start(arguments,fmtstr);

    va_arg(arguments,char*);

    // irgendwie pointer * oder & auf arguments...? --- arguments ist schon ein Pointer, und & wäre die Referenz nicht der Pointer
    sprintf(sbuf, fmtstr, arguments ); // ???
  
    va_end ( arguments );                  // Cleans up the list

    return str;                    
}





void setup()
{
  char * sptr;

  Serial.begin(9600);
  Serial.println("#: Serial() started");


  sptr = fprintfln(sbuf, "%s %d %f", "Teststring", 2, PI );
  
  Serial.print( "sbuf=");Serial.println( sbuf);
  Serial.print( "sptr=");Serial.println( sptr );


}

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

Ausgabe:
Code:
#: Serial() started
sbuf= 2 0.000000
sptr= 2 0.000000

da stimmt also irgendwas noch nicht.. Undecided

so wie ich es kenne, erwartet va_start auch die Argumentenliste in Verbindung mit ihrer Elemente-Anzahl
va_start ( arguments, num );
das haben wir hier ja nicht, und num kenne ich ja nicht.
Ist das der Fehler eventuell ?
Alle Beiträge dieses Benutzers finden
Diese Nachricht in einer Antwort zitieren
01.03.2015, 19:47
Beitrag #4
RE: Funktion mit variabler Parameterliste: Parameterliste weiterreichen?
lass mal das inkrementieren weg
va_arg(arguments,char*);
eine num
"so wie ich es kenne, erwartet va_start auch die Argumentenliste in Verbindung mit ihrer Elemente-Anzahl"
braucht er nicht, das sprintf zählt sich die anzahl argumente aus dem formatstring zusammen.

hier noch eine verschärfte variante
char * fprintfln (char * str, char fmtstr[], va_list arguments )
{
sprintf(sbuf, fmtstr, arguments );

return str;
}
Alle Beiträge dieses Benutzers finden
Diese Nachricht in einer Antwort zitieren
01.03.2015, 19:50 (Dieser Beitrag wurde zuletzt bearbeitet: 01.03.2015 19:51 von HaWe.)
Beitrag #5
RE: Funktion mit variabler Parameterliste: Parameterliste weiterreichen?
danke, stimmt, du hast recht!

habe jetzt folgendes probiert - mit vsprintf - und es funktioniert!

Besten Dank für deine Tipps! Smile

Code:
/*
program: demo multi var args
multivargs 0007
Sketch: 1.6.0
This example code is in the public domain.
*/

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

char sbuf[512];


char * fprintfln ( char * str, const char fmtstr[], ... ) {

   va_list arguments;
    
   va_start( arguments, fmtstr);

   vsprintf(sbuf, fmtstr, arguments);    
  
   // später für files:
   // stream->print(sbuf); // oder println, je nachdem
  
   va_end( arguments );

   return str;
}





void setup()
{
  char * sptr;

  Serial.begin(9600);
  Serial.println("#: Serial() started");


  sptr = fprintfln(sbuf, "%s %d %f", "Teststring", 2, PI );
  
  Serial.print( "sbuf=");Serial.println( sbuf);
  Serial.print( "sptr=");Serial.println( sptr );


}

void loop()
{
  // nothing happens after setup
}
Alle Beiträge dieses Benutzers finden
Diese Nachricht in einer Antwort zitieren
04.03.2015, 19:28 (Dieser Beitrag wurde zuletzt bearbeitet: 04.03.2015 19:40 von HaWe.)
Beitrag #6
RE: Funktion mit variabler Parameterliste: Parameterliste weiterreichen?
jetzt stecke ich allerding leider wieder fest -
ich versuche fscanf() per fscanf_() nachzubilden.

Ich kann einen string mit 5 Variablen in ein File schreiben (%s, %d, %d, %f, %f): korrekt !
Ich kann diesen string in fscanf_() aus diesem SD File lesen (korrekt),
ich zähle in fscanf_() korrekt 5 gescannte Variablen (== Rückgabewert von vsscanf ),
dieser Wert (5) ist auch der Rückgabewert von fscanf_() per return.

aber dann hängt das Programm sich auf:
kein Rücksprung ins aufrufende Programm, es wird absolut nichts mehr angezeigt, auch nicht einmal der returnte Wert !

was mag da schief laufen... ?

Code:
/*
SD card: fprintf_() und fscanf_()
ver 0.01
*/

#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];



//********************************************************************************​***********  
int fscanf_ ( File * stream, const char fmtstr[], ... ) {
   const char maxstrsize = 1024;
   char   str[maxstrsize];
   va_list   args;  
   int32_t   i=0, cnt=0;
   int16_t   chr;
  
   va_start( args, fmtstr );
  
   strcpy(str, "");
   while ( stream->available() ) {    
      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 );  

   // #debug
   Serial.print("fscancnt:"); Serial.println(cnt);
   va_end ( args );
  
   return cnt;
}


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

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

   return num;
}

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


void setup()
{
  int16_t  p, i, cnt;
  char     sval[20];
  int16_t  ival, n, m;
  double   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, "%s %d %d %f %f\n", "Testvalues:", 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, "%s %d %d %f %f", sdata, &m, &n, &x, &y);
    //---------------------------------------------------------------------------------

       // Testausgabe:
       Serial.println(cnt);   //  <<<<<<<<<<<<<<<<<<<<  keine Ausgabe mehr !!! <<<<<<<<<<<
       Serial.println();
       Serial.println(sdata);
       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
}


Debug-Ausgabe:
Code:
#: SD Initializing...
#: ...SD OK !      
#: test.txt exists    
#: Removing test.txt      
#: test.txt  N/A    
#: Writing strings to test.txt
fprintf_:Testvalues: 1 2 3.141593 4.567890

#: test.txt closed.  

#: reading test.txt
fscanstr:Testvalues: 1 2 3.141593 4.567890    
fscancnt:5
Alle Beiträge dieses Benutzers finden
Diese Nachricht in einer Antwort zitieren
04.03.2015, 19:46
Beitrag #7
RE: Funktion mit variabler Parameterliste: Parameterliste weiterreichen?
(04.03.2015 19:28)HaWe schrieb:  jetzt stecke ich allerding leider wieder fest -
ich versuche fscanf() per fscanf_() nachzubilden.

Ich kann einen string mit 5 Variablen in ein File schreiben (%s, %d, %d, %f, %f): korrekt !
Ich kann diesen string in fscanf_() aus diesem SD File lesen (korrekt),
ich zähle in fscanf_() korrekt 5 gescannte Variablen (== Rückgabewert von vsscanf ),
dieser Wert (5) ist auch der Rückgabewert von fscanf_() per return.

aber dann hängt das Programm sich auf:
kein Rücksprung ins aufrufende Programm, es wird absolut nichts mehr angezeigt, auch nicht einmal der returnte Wert !

was mag da schief laufen... ?

Code:
/*
SD card: fprintf_() und fscanf_()
ver 0.01
*/

#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];



//********************************************************************************​***********  
int fscanf_ ( File * stream, const char fmtstr[], ... ) {
   const char maxstrsize = 1024;
   char   str[maxstrsize];
   va_list   args;  
   int32_t   i=0, cnt=0;
   int16_t   chr;
  
   va_start( args, fmtstr );
  
   strcpy(str, "");
   while ( stream->available() ) {    
      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 );  

   // #debug
   Serial.print("fscancnt:"); Serial.println(cnt);
   va_end ( args );
  
   return cnt;
}


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

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

   return num;
}

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


void setup()
{
  int16_t  p, i, cnt;
  char     sval[20];
  int16_t  ival, n, m;
  double   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, "%s %d %d %f %f\n", "Testvalues:", 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, "%s %d %d %f %f", sdata, &m, &n, &x, &y);
    //---------------------------------------------------------------------------------

       // Testausgabe:
       Serial.println(cnt);   //  <<<<<<<<<<<<<<<<<<<<  keine Ausgabe mehr !!! <<<<<<<<<<<
       Serial.println();
       Serial.println(sdata);
       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
}


Debug-Ausgabe:
Code:
#: SD Initializing...
#: ...SD OK !      
#: test.txt exists    
#: Removing test.txt      
#: test.txt  N/A    
#: Writing strings to test.txt
fprintf_:Testvalues: 1 2 3.141593 4.567890

#: test.txt closed.  

#: reading test.txt
fscanstr:Testvalues: 1 2 3.141593 4.567890    
fscancnt:5



------------
versuche mal das Leerzeichen
bei va_end ( args ); nach va_end zu entfernen

also
va_end( args );

vielleicht war's das
Alle Beiträge dieses Benutzers finden
Diese Nachricht in einer Antwort zitieren
04.03.2015, 19:49
Beitrag #8
RE: Funktion mit variabler Parameterliste: Parameterliste weiterreichen?
danke - aber schade, leider noch keine Änderung Sad
Alle Beiträge dieses Benutzers finden
Diese Nachricht in einer Antwort zitieren
Antwort schreiben 


Möglicherweise verwandte Themen...
Thema: Verfasser Antworten: Ansichten: Letzter Beitrag
  Funktion mit Parameterübergabe - u8g torsten_156 8 396 22.06.2016 18:53
Letzter Beitrag: Pit
  Funktion in Loop einmalig ausführen Haustechno 4 644 09.03.2016 22:43
Letzter Beitrag: Haustechno
  HC-05 Modul auf Funktion prüfen. arduinofan 2 362 03.02.2016 19:18
Letzter Beitrag: arduinofan
  Eine Funktion vorher definieren ? arduinofan 23 2.010 30.12.2015 08:42
Letzter Beitrag: amithlon
  Funktion/Methode mit mehr als einem Ausgangswert Marduino_UNO 18 1.249 20.10.2015 10:30
Letzter Beitrag: Marduino_UNO
  PulseIn-Funktion unklar alpenpower 6 1.282 24.07.2015 10:05
Letzter Beitrag: Scherheinz
  auslagern von Funktion aus der void loop? MaHaI976 19 2.865 22.06.2015 20:38
Letzter Beitrag: MaHaI976
  Funktion aus Wertepunkten erstellen- wie ? HaWe 6 1.510 05.06.2015 07:53
Letzter Beitrag: HaWe
  C-Code für eine substring-Funktion: richtig ? HaWe 1 669 27.05.2015 14:01
Letzter Beitrag: HaWe
  gesucht: C-Funktion zum Einfügen eines Teilstrings in einen größeren HaWe 1 860 25.05.2015 10:30
Letzter Beitrag: HaWe

Gehe zu:


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