PDA

Archiv verlassen und diese Seite im Standarddesign anzeigen : Arduino Sketch: Funktion mit variabler Parameterliste: Parameterliste weiterreichen?



HaWe
01.03.2015, 15:04
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]

Wsk8
01.03.2015, 17:57
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

HaWe
01.03.2015, 19:08
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?

Wsk8
01.03.2015, 19:27
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

HaWe
04.03.2015, 16:23
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... :-/

Sisor
04.03.2015, 18:40
...weiß ja C, mit welcher Anzahl man es zu tun hat.

Nicht zwingend. Es wird wohl eher mit while(...){...} realisiert sein.

Sisor
04.03.2015, 19:44
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;
}

Sisor
04.03.2015, 20:19
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?

HaWe
04.03.2015, 20:26
habe alles durchprobiert:
- komplett alle int-Typen als int16_t : keine Änderung
- fscanf_ als void: auch keine Änderung :(

Sisor
04.03.2015, 20:51
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.

HaWe
04.03.2015, 21:07
ich verwende einen Due...

habs aber trotzdem probiert mit kürzeren Buffern => leider auch keine Änderung... :(

HaWe
08.03.2015, 09:49
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?

Wsk8
08.03.2015, 16:00
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

Wsk8
08.03.2015, 16:22
Ein char ist ein uint8 = 0-255.
Und ein normaler Compiler würde dich darauf hinweisen, dass hier ein Overflow stattfindet.

mfg

Wsk8
08.03.2015, 17:17
Könnte es daran liegen, dass es ein 32bit Prozessor ist? Und eigentlich sollten float und double eigentlich das selbe sein... :roll:

mfg

HaWe
08.03.2015, 18:02
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^^).