Forum: Mikrocontroller und Digitale Elektronik sprintf mit dynamischen Format


von Godi S. (godi22)


Lesenswert?

Hallo,

ich möchte gerne ein dynamisches Format auf sprintf anwenden.

Also ich habe eine Funktion der ich das Format (zb: "%u;%f;%f\n") als 
String übergebe.
Die dazugehörenden Werte befinden sich in einem Array (konkret im 
SDRAM).
Nun möchte ich die Werte aus dem Array (SDRAM) formatiert auslesen.
Leider funktioniert es nicht, nur die Pointer der Funktion sprintf zu 
übergeben.

z.B.
1
char buffer[1024]; // buffer in dem der formatierte String hineingeschrieben werden soll
2
sprintf(buffer, format, sdram);  //format: Pointer auf den Format String; sdram: Pointer auf den SDRAM bzw irgendeinen buffer wo die Werte drinn stehen

Gibt es da irgendeine Lösung dafür oder muss ich dies über schleifen 
zusammenbasteln?
(Würde mir gar nicht gefallen ;) )

Ziel ist es in dem SDRAM beliebige Werte abzuspeichern und je nach 
Bedarf diese formatiert auslesen zu können um in eine csv Datei auf der 
SD-Karte zu schreiben.


godi

von Nicolas S. (Gast)


Lesenswert?

Tja, beim AVR-GCC

http://www.nongnu.org/avr-libc/user-manual/group__avr__stdio.html#ga4c04da4953607fa5fa4d3908fecde449

will der snprintf einen Zeiger auf einen konstanten String. Mehrere 
konstante Strings hinterlegen ist kein Problem.

von Yalu X. (yalu) (Moderator)


Lesenswert?

godi S. schrieb:
> Leider funktioniert es nicht, nur die Pointer der Funktion sprintf zu
> übergeben.

Doch das geht.

Was hast du denn versucht, was hast du erwartet, und was ist stattdessen
passiert?

von Cyblord -. (cyblord)


Lesenswert?

Nicolas S. schrieb:
> Tja, beim AVR-GCC
>
> 
http://www.nongnu.org/avr-libc/user-manual/group__avr__stdio.html#ga4c04da4953607fa5fa4d3908fecde449
>
> will der snprintf einen Zeiger auf einen konstanten String. Mehrere
> konstante Strings hinterlegen ist kein Problem.

Das const bedeutet hier aber nur, dass der String in der Funktion nicht 
verändert wird.

von Yalu X. (yalu) (Moderator)


Lesenswert?

godi S. schrieb:
> sprintf(buffer, format, sdram);  //format: Pointer auf den Format
> String; sdram: Pointer auf den SDRAM bzw irgendeinen buffer wo die Werte
> drinn stehen

Jetzt sehe ich erst, wo der Hund begraben liegt: Du willst die von
sprintf anzuzeigenden Werte nicht als Einzelargumente, sondern als
Byte-Array übegeben. Das geht so nicht, hat aber nichts mit dem
dynamischen Formatstring zu tun.

Du bräuchtest eine Funktion ähnlich vsprintf, die als drittes Argument
keine va_list, sondern ein Byte-Array entgegen nimmt. Die gibt es
(zumindest in C99) nicht. Auch eine Überführung des Byte-Arrays in eine
va_list geht m.W. nur auf "schmutzige" und unportable Art und Weise.

von Godi S. (godi22)


Lesenswert?

Yalu X. schrieb:
> godi S. schrieb:
>> Leider funktioniert es nicht, nur die Pointer der Funktion sprintf zu
>> übergeben.
>
> Doch das geht.
>
> Was hast du denn versucht, was hast du erwartet, und was ist stattdessen
> passiert?

Was ich mir erwarte bzw was ich gerne möchte:
Die Übergabe der Variablen Liste (ab Parameter 3) als Array wo die Werte 
der Parameter in richtiger Reihenfolge gespeichert sind.
zB:
1
char buffer[1024]; // Der Buffer wo der String hingespeichert werden soll
2
3
4
// Meine Werte
5
uint32_t myUint = 1234;
6
float myFloat1 = 1.234;
7
float myFloat2 = 2.345;
8
9
typedef union Data {
10
  uint32_t ui;
11
  float f;
12
  uint8_t bytes[4];
13
} Data;
14
15
Data data[3];
16
17
data[0].ui = myUint;
18
data[1].f = myFloat1;
19
data[2].f = myFloat1;
20
21
// sprintf normal benutzen
22
sprintf(uffer, "myUint: %u; myFloat1: %f; myFloat2: %f;", myUint, myFloat1, myFloat2);
23
24
// So wie ich es gerne haben würde
25
char format = "myUint: %u; myFloat1: %f; myFloat2: %f;";
26
sprintf(buffer, format, data);
27
// Aus dem data Array sollen die Werte automatisch ausgelesen werden.
28
// Damit kann der format String beliebig gestaltet werden ohne dass die Parameterliste angepasst werden muss


Was habe ich bisher Versucht:
sprintf(buffer, format, data);

Was ist passiert:
Eine Exception wurde vom AVR32 ausgelöst
1
.org  0x034
2
  // Data Address (Read).
3
_handle_Data_Address_Read:
4
  rjmp $

von Godi S. (godi22)


Lesenswert?

Yalu X. schrieb:
> godi S. schrieb:
>> sprintf(buffer, format, sdram);  //format: Pointer auf den Format
>> String; sdram: Pointer auf den SDRAM bzw irgendeinen buffer wo die Werte
>> drinn stehen
>
> Jetzt sehe ich erst, wo der Hund begraben liegt: Du willst die von
> sprintf anzuzeigenden Werte nicht als Einzelargumente, sondern als
> Byte-Array übegeben. Das geht so nicht, hat aber nichts mit dem
> dynamischen Formatstring zu tun.
>
> Du bräuchtest eine Funktion ähnlich vsprintf, die als drittes Argument
> keine va_list, sondern ein Byte-Array entgegen nimmt. Die gibt es
> (zumindest in C99) nicht. Auch eine Überführung des Byte-Arrays in eine
> va_list geht m.W. nur auf "schmutzige" und unportable Art und Weise.

Ja genau das will ich. ;)
Wie könnte ich dies am besten lösen?
Den Code von sprintf abwandeln?

von (prx) A. K. (prx)


Lesenswert?

godi S. schrieb:
> Was ich mir erwarte bzw was ich gerne möchte:
> Die Übergabe der Variablen Liste (ab Parameter 3) als Array wo die Werte
> der Parameter in richtiger Reihenfolge gespeichert sind.

Schau mal bei vsprintf vorbei.

Die spannende Frage dabei ist allerdings, was die richtige Ordnung der 
Liste ist. Denn vsprintf erwartet die in exakt so, wie der Compiler sie 
bei varargs-Funktionen erzeugt. Das ist prima, wenn du es genau dafür 
verwenden willst, also für eine eigene Funktion wie printf, deren 
Paremeter du nach unten durchreichen willst. Weniger prima, wenn du das 
Zeug fabrizieren willst.

Wenn du also damit keine va_list verarbeiten willst, dann solltest du 
ein eigenes sprintf-Analogon basteln, wenn du dich nicht auf eine 
bestimmte Compiler-Release festlegen willt.

: Bearbeitet durch User
von Godi S. (godi22)


Lesenswert?

Vielen Dank mal für die Info.

Da werde ich mich erst mal einlesen müssen, bis ich weitere ergebnisse 
habe. :)
Aber vielleicht hat schon mal jemand so was realisiert und kann mir den 
code zukommen lassen. ;)

von Karl H. (kbuchegg)


Lesenswert?

> Ziel ist es in dem SDRAM beliebige Werte abzuspeichern und je
> nach Bedarf diese formatiert auslesen zu können um in eine csv
> Datei auf der SD-Karte zu schreiben.

Die Frage ist für mich auch, ob der ganze Ansatz mit sprintf hier 
überhaupt zielführend ist.
2 Punkte gibt es zu berücksichtigen
* zum einen ist da die Frage der Anzahl. Denn für jede %-Formatierung im 
Format-String, muss es auch einen entsprechenden Wert im 'Array' geben. 
Hast du zuviele Werte im Array, dann ist das noch nicht weiter tragisch. 
Interessant wird es dann, wenn mehr Formatier-Argumente im Formatstring 
vorhanden sind, als es überhaupt Werte gibt.
* zum anderen ist die Reihenfolge der Werte nicht uninteressant. Denn 
gerade bei einem recht universellen Mechanismus, sollte es ja eine 
Möglichkeit geben, wie ich über den Formatier-String auch noch auswählen 
kann, welchen Werte aus dem 'Array' ich eigentlich an dieser Stelle 
haben will. An diesem Punkt stehst du aber mit sprintf alleine da, das 
kann sprintf nicht.

d.h. ich würde mir hier einen eigenen Mechanismus einfallen lassen, der 
die beiden Punkte handhabt. Die Formatierangabe selbst (Feldbreite etc.) 
kann ja ähnlich wie im Formatierstring laufen. Die Frage ist ja auch, wo 
denn dieser FOrmatierstring zb herkommt und ob das überhaupt ein 
Formatierstring sein muss, oder ob man diese Angaben nicht auch anders 
an eine spezielle Funktion übergeben darf bzw. kann.

: Bearbeitet durch User
von Godi S. (godi22)


Lesenswert?

Meine Idee/Umsetzung dahinter ist folgende:
Ich habe Code der aus Simulink generiert wird.
Da dies aber zu Testzwecken verwendet wird möchte ich beliebige Werte in 
den SDRAM speichern zum mitloggen. Diese können dann entweder direkt 
über TCP/IP an Matlab gesendet werden oder auch als csv Datei auf die 
SD-Karte gespeichert werden.
Also im SDRAM befinden sich dann die Werte immer im selben Muster 
hintereinandergereiht. Dadurch weiß ich auch genau wieviele Blöcke mit 
dem selben Muster im SDRAM gespeichert sind.
Den Format-String will ich auch aus Simulink generieren lassen.
Damit aber der Code für die Speicherverwaltung nicht mit den Code der 
eigentlichen Funktion durcheinandergewürfelt wird hätte ich eben gerne 
eine Funktion in meiner Speicherverwaltung die mir als Parameter den 
Format-String entgegennimmt und wenns noch nötig ist die Größe eines 
Blockes.
Somit ist die Speicherverwaltung vollständig alleinstehend, braucht 
keine includes des generierten Codes und kann universell einsetzbar 
benutzt werden.

von DirkB (Gast)


Lesenswert?

Wenn du dich an die Eigenheiten der variablen Argumente hälst 
(Erweiterung von float auf double, integrale Typen mindestens auf int) 
geht es z.B. so:
1
#include <stdio.h>
2
#include <stdlib.h>
3
#include <stdarg.h>
4
5
typedef struct  {
6
 int    x;
7
 double z;
8
 int    xx;
9
 double zz;
10
 char   *s;
11
} __attribute__((packed)) xz; 
12
13
int main(void)
14
{
15
  int feld[5] = {1,2,3,4,8};
16
  double ffeld[5] = {1,2,3,4,8};
17
  xz  foo = {100, 3.141, 12345678, 38e5, "Hallo"};
18
19
  vprintf("%i %i %i %i %i\n",(va_list)feld);
20
  vprintf("%f %f %f %f %f\n",(va_list)ffeld);
21
  vprintf("%i %f %i %e %s\n",(va_list)&foo);
22
  puts("Ende");
23
24
  return 0;
25
}
Ausgabe:
1
1 2 3 4 8
2
1.000000 2.000000 3.000000 4.000000 8.000000
3
100 3.141000 12345678 3.800000e+006 Hallo
4
Ende

von Godi S. (godi22)


Lesenswert?

Vielen Dank für die Hilfe!

Leider habe ich das Problem, dass in meiner Funktion die definition des 
structs unbekannt ist.
Aber dies mit va_list ist eine gute Idee, kann ich sicher noch mal wo 
brauchen, und ich habe was dazugelernt. :)

Mein "sprintf" sollte eben nur aufgrund des Formatier-Strings auf die 
Elemente im Array zugreifen.
Also wenn der Parser auf zb '%u' trifft dann soll er einfach 4bytes aus 
dem Array herausnehmen und diese als uint darstellen. Danach den Pointer 
um 4Bytes erhöhen. Wenn er als nächstes '%f' findet dann einfach die 
4Bytes auf die gerade der Pointer zeigt hernehmen und diese als float 
darstellen. Pointer erhöhen usw...

Ich habe schon einen kurzen Blick in sprintf bzw vfprintf geworfen.
(http://svn.savannah.nongnu.org/viewvc/*checkout*/trunk/avr-libc/libc/stdio/vfprintf.c?revision=2191&root=avr-libc)
Wenn ich es richtig verstanden habe dann müsste es ja funktionieren wenn 
ich die va_arg Aufrufe durch ein Makro ersetze, das mir den Wert der 
nächsten xBytes zurückliefert und den Pointer eben um xBytes erhöht.

von Dirk B. (dirkb2)


Lesenswert?

godi S. schrieb:
> Mein "sprintf" sollte eben nur aufgrund des Formatier-Strings auf die
> Elemente im Array zugreifen.

Das macht doch das Beispiel von mir. vprintf hat sonst keine 
Informationen über die struct.
Die struct ist auch nur ein Hilfsmittel, um verschiedene Daten im 
Speicher abzulegen.

godi S. schrieb:
> Wenn er als nächstes '%f' findet dann einfach die
> 4Bytes auf die gerade der Pointer zeigt hernehmen und diese als float
> darstellen.

Und genau da musst du aufpassen. printf kennt kein float, sondern nur 
double. Schon immer. Es holt also nicht 4 Byte aus dem Speicher, sondern 
8.
(Genau genommen kennt printf den Specifier %lf erst seit C11. Er wurde 
vorher aber geduldet)(ja, ich weiß dass die 4 bzw. 8 Byte systemabhängig 
sind)

Die Werte müssen hintereinander im Speicher stehen, so als wären sie die 
Paramter auf dem Stack.

von Yalu X. (yalu) (Moderator)


Lesenswert?

godi S. schrieb:
> Mein "sprintf" sollte eben nur aufgrund des Formatier-Strings auf die
> Elemente im Array zugreifen.
> Also wenn der Parser auf zb '%u' trifft dann soll er einfach 4bytes
> aus
> dem Array herausnehmen und diese als uint darstellen. Danach den
> Pointer
> um 4Bytes erhöhen. Wenn er als nächstes '%f' findet dann einfach die
> 4Bytes auf die gerade der Pointer zeigt hernehmen und diese als float
> darstellen. Pointer erhöhen usw...

Genau das wird in der von DirkB vorgestellten Methode auch gemacht. Du
kannst anstelle der dort definierten Strukturen und Arrays einen
beliebigen Pointer übergeben, also bspw. auch einen, der auf den Anfang
deiner Daten im SDRAM zeigt. Probier's einfach mal aus.

Allerdings ist die Methode von der Sorte, die ich oben "schmutzig" und
unportabel bezeichnet habe, denn ihr Funktionieren hängt stark davon ab,
wie der Typ va_list intern aufgebaut ist und wie das Alignment der Daten
im Speicher ist. Auf 8-Bit-AVRs (vielleict auch auf AVR32) könnte die
Sache zu funktionieren. Auf meinem PC hingegen geht der Code nicht
einmal durch den GCC, da ein Array (bzw. ein Pointer) nicht in va_list
gecastet werden kann. va_list ist hier nämlich im Gegensatz zum AVR
nicht ein einfacher Pointer, sondern eine etwas komplexrere
Datenstruktur.

von Godi S. (godi22)


Lesenswert?

Ok, sorry habe das Beispiel beim ersten mal hinsehen falsch 
interpretiert.

Leider komme ich erst wieder am Montag zu dem AVR32 Board damit ich den 
Code Testen kann.

Ich wollte es jetzt unter Ubuntu (64Bit) mit Eclipse testen.
Leider bekommen ich folgenden Fehler:
Typkonvertierung gibt Feldtyp an

Naja ich werde es am Montag noch mal im Atmel Studio probieren.

Aber vielen Dank für eure Hilfe und Tipps! :)

: Bearbeitet durch User
von Dirk B. (dirkb2)


Lesenswert?

godi S. schrieb:
> Ich wollte es jetzt unter Ubuntu (64Bit) mit Eclipse testen.

Der Compiler und die Bitbreite vom Code sind entscheidend.

Ich hatte das mit Code::Blocks und dem mitgelieferten GCC unter 32-Bit 
Windows 7 getestet.
Da brauchte ich das __attribute__((packed)).
Bei 64-Bit kann das wieder anders aussehen.

Du kannst dir ja mal für dein System die stdarg.h ansehen.
(Und auch die Dateien die dort mit #include eingebunden werden)

von Yalu X. (yalu) (Moderator)


Lesenswert?

Dirk B. schrieb:
> Bei 64-Bit kann das wieder anders aussehen.

Da auf i86_64 Argumente variabler Anzahl nicht nur auf dem Stack,
sondern auch in Registern (sowohl GP- als auch FP-Register) übergeben
werden, wird das Vorhaben, selber eine va_list nachzubilden, um einiges
komplizierter.

Ich kann mir aber gut vorstellen, dass auf dem AVR32 die Argumente ganz
klassisch auf dem Stack übergeben werden, so dass die Methode von Dirk
B. dort durchaus funktionieren könnte.

von Godi S. (godi22)


Lesenswert?

Hallo,
ich habe Gestern noch damit herumprobiert, aber leider bin ich zu keinen 
brauchbaren Ergebnis gekommen.

Wenn ich zwei Werte (uint32 und float) gespeichert habe dann habe ich 
das Problem dass er für float Werte 8 Bytes ausgelesen hat und nicht 4.
Wenn ich ein Format von '%u%f%u%f' wollte dann hat sich der AVR32 wider 
eine Exception geworfen.

Also irgendwie funktioniert der Ansatz ein Array in eine Variable 
Argumentenliste zu Wandeln mehr schlecht als recht.

Jetzt habe ich mir die Source der Toolchain von Atmel downgeloaded und 
mir das File vfprintf.c angesehen.
Naja das beeinhaltet fast 2000 LOC!
So einfach wie ich mir das vorgestellt habe mit ein wenig umschreiben 
ist es wohl auch nicht.

Hat vielleicht jemand noch eine andere Idee?




Hier noch der link zur Atmel Toolchain (newlib):
http://distribute.atmel.no/tools/opensource/Atmel-AVR-Toolchain-3.4.2/avr32/

http://distribute.atmel.no/tools/opensource/Atmel-AVR-Toolchain-3.4.2/avr32/avr32-newlib-1.16.0.tar.gz

von Yalu X. (yalu) (Moderator)


Lesenswert?

godi S. schrieb:
> Wenn ich zwei Werte (uint32 und float) gespeichert habe dann habe ich
> das Problem dass er für float Werte 8 Bytes ausgelesen hat und nicht 4.

Mit float-Werten kann das nicht funktionieren, da diese bei der Übergabe
an Funktionen mit variabler Argumentliste immer in double umgewandelt
werden. Entsprechend erwartet das %f-Format kein float, sondern ein
double, und liest deswegen 8 Bytes. Siehe auch Hinweis von Dirk:

DirkB schrieb:
> Wenn du dich an die Eigenheiten der variablen Argumente hälst
> (Erweiterung von float auf double, integrale Typen mindestens auf int)
> geht es z.B. so:

godi S. schrieb:
> Hat vielleicht jemand noch eine andere Idee?

Welche Datentypen und welche Format-Optionen (Feldlänge, Anzahl der
Nachkommastellen usw.) brauchst du tatsächlich? Wenn es nur ein paar
wenige sind, bietet es sich an, eine stark abgespeckte Version von
vsprintf zu schreiben, die anstelle der va_list einen uint8_t-Pointer
entgegennimmt, und die auch mit 4-Byte-Floats umgehen kann.

: Bearbeitet durch Moderator
von Godi S. (godi22)


Lesenswert?

Yalu X. schrieb:
> Welche Datentypen und welche Format-Optionen (Feldlänge, Anzahl der
> Nachkommastellen usw.) brauchst du tatsächlich? Wenn es nur ein paar
> wenige sind, bietet es sich an, eine stark abgespeckte Version von
> vsprintf zu schreiben, die anstelle der va_list einen uint8_t-Pointer
> entgegennimmt, und die auch mit 4-Byte-Floats umgehen kann.

Ja das habe ich mir auch schon gedacht.
Für meinen Fall würde ich die ganzen Formatoptionen eh nicht brauchen, 
da die Werte nur in ein csv File geschrieben werden sollen.
Von den Datentypen her würden mir die 32Bit-Typen genügen.
uint32, int32, float, eventuell noch Hex.

Naja da werde ich mich dann am Montag drüberstürzen. :)

von Godi S. (godi22)


Lesenswert?

Hallo,

so jetzt habe ich das implementiert und getestet.
Funktioniert mal so weit für meinen Anwendungsfall.
Jedoch habe ich irgendwie das Gefühl, dass dies einfacher zu 
implementieren geht. ;)

Hat jemand einen Tipp für mich?

Leider unterstützt auch der AVR32 die Funktionen utoa, itoa, ftoa nicht.
1
//**********************************************************************************
2
// Valid character for the format string
3
//**********************************************************************************
4
bool valid_char_format_string(char c) {
5
  switch ((uint8_t) c) {
6
  case 'u':
7
  case 'i':
8
  case 'f':
9
  case 'x':
10
  case 'X':
11
    return true;
12
  }
13
  return false;
14
}
15
16
17
//**********************************************************************************
18
// This function print the values from an array as string (format)
19
// into the current opened file (navigator)
20
//
21
// Parameters:
22
//    fmt      ...The format as string ("%u;%i;%f;%x;%X;")
23
//    array    ...The array were the values are saved
24
//    arraySize  ...The array size in bytes
25
//
26
// Valid format types: u, i, f, x, X
27
// e.g.: "%u;%i;%f;%x;%X;"
28
// Other characters are ignored.
29
// "%%f" => isn't possible => result = %floatval and not %%f
30
//
31
// Return the written bytes
32
//**********************************************************************************
33
uint32_t print_array_to_file(char*fmt, void*array, uint32_t arraySize) {  
34
  const uint32_t bufferSize = 1024; // The buffer size
35
  char buffer[1024]; // String buffer
36
  size_t bufferLen = 0; // The current saved bytes in the string buffer
37
  buffer[bufferLen] = '\0'; // Init buffer
38
    
39
  char * ptr[100];  // The pointers to valid '%' in the format string
40
  char *tmpPtr = fmt; // Temporary pointer to the format string
41
  uint32_t ptrN = 0; // Number of pointers to valid '%' in the format string
42
43
  uint32_t nb_write = 0; // The successful written bytes to the file
44
  
45
  uint32_t iter = 0; // The iterations over the array
46
  
47
  
48
  size_t fmtLen = strlen(fmt); // The length of the format string
49
  
50
  
51
  // Find valid '%' in the format string
52
  while (ptrN < 100) {
53
    tmpPtr = strchr(tmpPtr, '%');
54
    if (tmpPtr != NULL) {
55
      if (valid_char_format_string(*(tmpPtr+1))) {
56
        ptr[ptrN] = tmpPtr;
57
        ptrN++;
58
      }
59
    }
60
    else {
61
      break;
62
    }
63
64
    tmpPtr++;
65
  } ;
66
  
67
  // Calculate the iterations
68
  if (ptrN == 0) {
69
    iter = 0;
70
  }
71
  else {
72
    iter = arraySize/(ptrN*4); 
73
  }
74
  
75
76
  // No valid '%' are available => write the format string one time and exit the function
77
  if (ptrN == 0) {        
78
    return file_write_buf((uint8_t*) fmt, fmtLen);
79
  }
80
81
82
  // Pointer to the last fmt element
83
  ptr[ptrN] = fmt+fmtLen;
84
85
86
  /*
87
   * Read the values from the array and build the string
88
   */
89
90
  // The datatype to read the correct datatype from the array
91
  typedef union  Data {
92
    unsigned int u;
93
    int i;
94
    float f;
95
  } Data;
96
  Data *data = (Data*) array;
97
98
99
  uint32_t i,j, len;
100
101
  for (i = 0; i < iter*ptrN; i+=ptrN) { // iterations
102
103
104
    for (j = 0; j < ptrN; j++) { // iteration over the format
105
      // Read the substring to the first valid '%'
106
      if (j == 0) {
107
        len = ptr[j] - fmt;
108
        memcpy(&buffer[bufferLen], fmt, len);
109
      }
110
      // Read the substring between valid '%'
111
      else {
112
        len = ptr[j] - (ptr[j-1]+2);
113
        memcpy(&buffer[bufferLen], ptr[j-1]+2, len);
114
      }
115
      bufferLen += len;
116
      
117
      
118
      // Read the values
119
      switch ((uint8_t) *(ptr[j]+1)) {
120
      case 'u':
121
        //utoa(data[j].u, &buffer[bufferLen], 10 );
122
        sprintf((char*)&buffer[bufferLen], "%u", data[i+j].u);
123
        break;
124
      case 'i':
125
        //itoa( data[j].i, &buffer[bufferLen], 10 );
126
        sprintf((char*)&buffer[bufferLen], "%i", data[i+j].i);
127
        break;
128
      case 'f':
129
        //ftoa( data[j].f,&buffer[bufferLen], 10 );
130
        sprintf((char*)&buffer[bufferLen], "%f", data[i+j].f);
131
        break;
132
      case 'x':
133
        //utoa( data[j].u, &buffer[bufferLen], 16 );
134
        sprintf((char*)&buffer[bufferLen], "%x", data[i+j].u);
135
        break;
136
      case 'X':
137
        //utoa( data[j].u, &buffer[bufferLen], 16 );
138
        sprintf((char*)&buffer[bufferLen], "%X", data[i+j].u);
139
        break;
140
141
      default:
142
        buffer[bufferLen] = '\0';
143
        break;
144
      }
145
      bufferLen = strlen((const char*)buffer);
146
      
147
      // Write the buffer to the SD-Card if the buffer is to small
148
      if (bufferSize < bufferLen+100) { 
149
        nb_write += file_write_buf((uint8_t*) buffer, bufferLen);
150
        bufferLen = 0;
151
        buffer[bufferLen] = '\0';
152
      }
153
      
154
    }
155
    // Read the substring from the last valid '%' to the end of the format string
156
    len = ptr[ptrN] - (ptr[ptrN-1]+2);
157
    memcpy(&buffer[bufferLen], ptr[ptrN-1]+2, len);
158
    bufferLen += len;
159
    buffer[bufferLen] = '\0';
160
    
161
    // Write the buffer to the SD-Card each iteration
162
    nb_write += file_write_buf((uint8_t*) buffer, bufferLen);
163
    bufferLen = 0;
164
    buffer[bufferLen] = '\0';
165
    
166
  }  
167
  return nb_write;
168
}

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.