Hallo zusammen, ich nutze den Microsoft Visual Studio Compiler 2010 unter Windows 7. (Ich nutze ihn als MEX-Compiler für Matlab, aber das ist für die Fragestellung vermutlich nicht relevant - er verhält sich wie in der normalen Konsole.) In meinem Programm sind *printf*-Aufrufe, die ich auf meine eigene putchar-Routine umleiten will (so, wie ich es beim AVR-GCC oder beim ARM-GCC gewohnt bin). Nur wie schiebt man dem stdout seine eigene putchar unter? Viele Grüße W.T.
Die MSVC StreamsIO Bibliothek sieht so was nicht vor. Du kannst so etwas ähnliches machen, in dem du: - Mit _pipe() zwei pipe file desriptoren erstellst. - Mit _fdopen() aus dem beschreibbaren handle wieder einen FILE* machst. Auf den kannst du jetzt mit fprintf() schreiben. - Einen thread startest, der das lesbare Ende der pipe ausliest und weiterverarbeitet.
Hallo Luther, danke für die Antwort. > - Mit _pipe() zwei pipe file desriptoren erstellst. > - Mit _fdopen() aus dem beschreibbaren handle wieder einen FILE* machst. > Auf den kannst du jetzt mit fprintf() schreiben. > - Einen thread startest, der das lesbare Ende der pipe ausliest und > weiterverarbeitet. Das klingt nicht so, als ob es Spaß machen würde. Also wird es vermutlich auf eine eigene Implementierung für printf hinauslaufen. Viele Grüße W.T.
Walter Tarpan schrieb: > Das klingt nicht so, als ob es Spaß machen würde. Also wird es > vermutlich auf eine eigene Implementierung für printf hinauslaufen. und warum nicht einfach sprintf verwenden? Was willst du denn genau machen?
Hier ist Code für ein printf, das auf vsnprintf aufbaut und eine selbstdefinierte putchar-Funktion aufruft:
1 | #include <stdio.h> |
2 | #include <stdlib.h> |
3 | #include <stdarg.h> |
4 | |
5 | // Beispiel-putchar fuer Sperrschrift
|
6 | |
7 | int myputchar(int c) { |
8 | putchar(c); |
9 | putchar(' '); |
10 | return c; |
11 | }
|
12 | |
13 | int myprintf(const char * restrict format, ...) { |
14 | char * buffer; |
15 | va_list args; |
16 | int i, ret; |
17 | |
18 | // Formatierung zur Probe, um die Laenge der Ausgabe bestimmen
|
19 | |
20 | va_start(args, format); |
21 | ret = vsnprintf(NULL, 0, format, args); |
22 | va_end(args); |
23 | |
24 | if(ret <= 0) |
25 | return ret; |
26 | |
27 | // Puffer fuer vsnprintf anlegen
|
28 | |
29 | buffer = malloc(ret+1); |
30 | if(buffer == NULL) |
31 | return -1; |
32 | |
33 | // Endgueltige Formatierung
|
34 | |
35 | va_start(args, format); |
36 | ret = vsnprintf(buffer, ret+1, format, args); |
37 | va_end(args); |
38 | |
39 | // Ausgabe mit selbstdefinierter putchar-Funktion
|
40 | |
41 | for(i=0; i<ret; i++) |
42 | myputchar(buffer[i]); |
43 | |
44 | free(buffer); |
45 | |
46 | return ret; |
47 | }
|
48 | |
49 | #define printf myprintf
|
50 | |
51 | |
52 | // Beispielaufruf
|
53 | |
54 | int main(void) { |
55 | printf("Ergebnis: %d\n", 12345); |
56 | return 0; |
57 | }
|
Nachteilig ist der zweimalige Aufruf von vsnprintf, der für die Bestimmung der erforderlichen Puffergröße benötigt wird. Du kannst dieses Problem evtl. auf zweierlei Weise umgehen: 1. Wenn du weißt, wie lang jede Ausgabe maximal werden kann, kannst du mit einem statischen Puffer arbeiten und kommst damit mit einem einzelnen vsnprintf aus. 2. Falls deine Laufzeitbibliothek asprintf o.ä. unterstützt, kannst du dieses anstelle der beiden vsnprintf verwenden.
Hallo Peter, ich drehe mal Deine Zeilen um: > Was willst du denn genau machen? Ich nutze Matlab, um Funktionen, die bislang auf einem STM32 und einem ATmega644 laufen zu testen. Dafür habe ich mir (u. A.) eine kleine Display-Emulation geschrieben, die die Grafik-Display-Ausgabe in Matlab darstellt. Hauptzweck der Sache sind natürlich Tests einiger Fixpoint-Routinen gegen die Ergebnisse der Floating-Point-Routinen in Matlab. Und da sowohl mit AVR-GCC als auch ARM-GCC sich die printf-Funktionen auf jede Schnittstelle umleiten lassen, ist der legacy code - insbesondere die Testfunktionen - gespickt mit Ausgaben über printf, hauptsächlich aus dem Grund, daß ich dann nicht überall besondere header einbinden muß, sondern stdio ausreicht. Peter II schrieb: > und warum nicht einfach sprintf verwenden? > Der Hauptgrund ist lediglich: Ausgabe mit sprintf braucht zwei Zeilen, Einbindung einer Headerdatei für die Ausgabefunktion und einen globalen Stringpuffer. Nichts Weltbewegendes. Nur Komfort. Und jetzt suche ich auf dem PC nach dem gleichen Komfort wie am µC. Viele Grüße W.T.
:
Bearbeitet durch User
Hallo Yalu, danke für den Vorschlag. Das dürfte sich ziemlich komfortabel umsetzen lassen. Mit snprintf und einem festen Puffer wird das sogar sehr übersichtlich. Vielen Dank und viele Grüße W.T. P.S.: Zu früh gefreut. Der "restrict" ist C99, das kann der MSVC nicht. Aber wenn ich das Detail weglasse funktioniert es auf Anhieb.
:
Bearbeitet durch User
Walter Tarpan schrieb: > P.S.: Zu früh gefreut. Der "restrict" ist C99, das kann der MSVC nicht. > Aber wenn ich das Detail weglasse funktioniert es auf Anhieb. Ja, lass es weg. Ich habe es hauptsächlich deswegen hingeschrieben, damit myprintf die gleiche Signatur wie (C99-)printf hat.
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
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.