Archiv verlassen und diese Seite im Standarddesign anzeigen : Arduino Sketch: 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
:
#include <stdio.h>
#include <stdarg.h>
int fprintfln ( FILE * stream, char format[], ... ) { // gefaketes und modifiziertes fprintf
char sbuf[100];
va_list arguments;
// irgendwie pointer * oder & auf arguments...?
sprintf(sbuf, format, & arguments ); // ???
//
//
stream->println(sbuf);
//
}
[/code]
Mit stdarg kannst du doch eh deine ganzen Parameter fertig formatiert in einen string schreiben und denn einfach ausgeben. Dazu brauchts kein sprintf mehr.
mfg
wie genau meinst du das? Ganz soweit fortgeschritten mit stdarg.h bin ich noch nicht...
meinen Aufruf hatte ich geplant z.B. (als vereinfachtes Beispiel, wie bei fprintf)
#include <SPI.h>
#include <SD.h>
File myFile;
int fprintfln ( FILE * stream, char format[], ... ) // Implementierung
{
//
//
//
}
void loop()
{
//
fprintfln( &myFile, "%s %d %f", "Teststring", 2, PI ); // Aufruf z.B. im Hauptprogramm
//
}
wie soll das jetzt allein per stdarg gehen?
So:
int fprintfln ( FILE * stream, const char format[], ... ) {
char sbuf[100];
va_list vl;
va_start(vl, format);
vsprintf(sbuf, format, vl);
stream->println(sbuf);
va_end(vl);
}
mfg
hallo,
noch eine Anschlussfrage:
gibt es eine Möglichkeit herauszubekommen, welche Anzahl an Argumenten das C-Programm ermittelt hat (Zuweisung an eine Int-Variable)?
nicht nur bei Übergabegabe einer festen Anzahl
va_start( arguments, num);
sondern auch bei Übergabe eines fmt-Strings
va_start( arguments, fmtstr);
weiß ja C, mit welcher Anzahl man es zu tun hat.
Bei va_start( arguments, num); ist es offensichtlich - aber wenn ich intern nur fmtstr kenne, wie kann ich C das Geheimnis der Anzahl aus der Nase ziehen?
so nach dem Motto
num=arg_cnt(fmtstr) oder num=arg_cnt(arguments) o. ä.?
Ansonsten müsste man umständlich erst die Anzahl der '%' zählen und die Zahl der "%%" doppelt wieder abziehen... :-/
...weiß ja C, mit welcher Anzahl man es zu tun hat.
Nicht zwingend. Es wird wohl eher mit while(...){...} realisiert sein.
Hast du das schon probiert?:
int fscanf_ ( File * stream, const char fmtstr[], ... ) {
...
// #debug
Serial.print("fscancnt:"); Serial.println(cnt);
va_end ( args );
Serial.println("Nach va_end(args)...");
return cnt;
}
1. Nicht so wichtig: cnt hast du mal als int16_t, int32_t und als int in der Rückgabe von fscanf.
2. Was passiert wenn du die Funktion fscanf zu einer void-Funktion machst? Ich habe die Vermutung, das da beim Rücksprung im Stack irgendwas schiefläuft. Aber warum?
habe alles durchprobiert:
- komplett alle int-Typen als int16_t : keine Änderung
- fscanf_ als void: auch keine Änderung :(
Probiers mal mit kürzeren Bufferlängen. Falls du einen Arduino Uno benutzt bist du mit 2*1024 Bytes schon bei genau 2kB, was der SRAM-Größe entspricht. Da aber der Stack auch Platz braucht, ist das schon ein Problem.
ich verwende einen Due...
habs aber trotzdem probiert mit kürzeren Buffern => leider auch keine Änderung... :(
keine versierten C- und Sketch-Spezialisten hier im Forum, die SD cards mit Arduino nutzen und das Programm selber mal testen und debuggen können?
int16_t fscanf_ ( File * stream, const char fmtstr[], ... ) {
const char maxstrsize = 1024;
char str[maxstrsize];
va_list args;
int16_t i=0, cnt=0;
int16_t chr;
Also entweder liest du dir keine Fehlermeldungen des Compilers durch oder der Arduino-Compiler ist absoluter Schrott.
Und durch die Fehlerhafte Stringgröße schreibst du wahrscheinlich irgendwohin und rennst dann hier ins Nirvana:
Serial.print("fscanstr:"); Serial.println(str);
Zudem ist es auch ziemlich schlecht, hier nicht auf maxstrsize zu überprüfen!
strcpy(str, "");
while ( stream->available() ) {
chr = stream->read() ;
if (chr>=0 && chr!='\n') {
str[i]=(char)chr;
++i;
}
else break;
}
mfg
Ein char ist ein uint8 = 0-255.
Und ein normaler Compiler würde dich darauf hinweisen, dass hier ein Overflow stattfindet.
mfg
Könnte es daran liegen, dass es ein 32bit Prozessor ist? Und eigentlich sollten float und double eigentlich das selbe sein... :roll:
mfg
ja, stimmt, ich arbeite meist mit dem Due!
Da muss man auch im Vergleich zum AVR sehr mit int aufpassen (32 bit statt 16),
und char ist unsigned im Gegensatz zum AVR (signed) - außer bei Ausgabestrings für Serial().
Damit es dann aber sowohl mit ARM als auch AVR funktioniert, verwende ich daher möglichst die C11 Typen ( zumindest wo ich dran denke^^).
Powered by vBulletin® Version 4.2.5 Copyright ©2024 Adduco Digital e.K. und vBulletin Solutions, Inc. Alle Rechte vorbehalten.