Standardausgabe umleiten und wieder zurücksetzen?
-
Hallo,
ich benutze in meinem Programm eine Funktion, die die Standardausgabe und eingabe in 2 Dateien umleitet.
Nun brauche ich anschließend aber wieder den normalen Zustand, da ich wieder etwas ausgeben möchte (das wäre alleine nicht das Problem, es gibt ja noch stderr), aber vorallem wieder etwas vom Benutzer einlesen möchte.
Kann man die Umleitung irgendwie wieder rückgängig machen?Danke
Floriank
-
mir fällt nichts portables ein, aber vielleicht kannst du unter POSIX-Systemen man: fdopen(3) nehmen und damit wieder die Standard I/O-Devices öffnen.
-
kannst du mir noch etwas genauer sagen was du meinst?
Ich bin eher ein Laie im Programmieren, muss es eben nur für meine Diplomarbeit tun. Was genau sind Posix Systeme und wie kann ich da fdopen benutzen, so daß die Standards wieder geöffnet werden?
Ich programmiere mit Visual Studio 8 unter Windows.
Danke
floriank
-
Hi,
irgendwie kapier ich dein Problem nicht, du kannst doch zwei Zeiger auf FILE benutzen und zwischendurch in der Konsole lesen und schreiben.
-
Auch liese sich dazu was finden:
cheers
-
Afaik gibt es zwar einen Weg, stdin und Co umzubiegen auf Dateien (freopen()), aber keinen Weg, sie anschließend wieder zurückzusetzen auf die "normalen" IO-Kanäle. Wenn du wirklich regelmäßig zwischen Datei und Konsole switchen willst, gib den Ausgabefunktionen doch das jeweilige Ziel-FILE mit (oder schick die Ausgaben an ein global definiertes FILE, das du bei Bedarf umhängen kannst:
FILE* logout = fopen("logfile.txt","w"); FILE* mystdout=stdout; void print() { fprintf(mystdout,"Hallo, da bin ich.\n"); } int main() { print();//Ausgabe landet auf der Konsole mystdout=logout; print();//Ausgabe landet im Log-File }
-
Hallo,
mein Problem liegt allerdings darin, daß ich eine Funktion aufrufe, die ich nicht selber geschrieben habe, welche aber z.B. immer wieder putchar() usw. benutzt. Diese macht am Anfang folgendes:
freopen(source,"rb", stdin); freopen(dest,"wb", stdout);
Wobei source und dest Pfade von Dateien beinhalten (const char*).
In die Funktion kann ich nur sehr schwer eingreifen, um dies zu ändern.Nun möchte ich nach diesem Funktionsaufruf allerdings Eingaben vom Benutzer zulassen, wie z.B.:
int variante; printf("Welche Kompressionsvariante soll angewendet werden?\n"); printf("(1) gzip / zlib \n"); printf("(2) range coder \n"); printf("(3) szip \n"); cin >> variante;
Das printf kann ich durch fprintf(stderr,...) ersetzen, das ist mir klar. Aber wie kann ich die Eingabe verlangen, ohne wieder auf die Standard "IO-Kanäle" zurück zu kommen.
Ich habe für das Rücksetzen nichts gefunden und wenn ich mir die Vorschläge so angucke, d´scheint es wirklich nicht zu gehen.
Gibt es eine andere Möglichkeit etwas einlesen zu lassen?Danke
-
Unter Windows geht es so:
freopen("CONIN$", "r", stdin); freopen("CONOUT$", "w", stdout); freopen("CONOUT$", "w", stderr);
-
floriank schrieb:
mein Problem liegt allerdings darin, daß ich eine Funktion aufrufe, die ich nicht selber geschrieben habe, welche aber z.B. immer wieder putchar() usw. benutzt.
hi,
eine andere möglichkeit wäre es, 'putchar()' zu überladen. zu dem zweck schreibst du eine eigene putchar()-funktion (gleiche signatur wie das original), und dann sagts du dem linker, dass er nicht putchar() aus der stdlib, sondern deine funktion einbinden soll. in der eigenen funktion kannst du dann die bytes hinschicken, wo du willst...
-
windows schrieb:
Unter Windows geht es so:
freopen("CONIN$", "r", stdin); freopen("CONOUT$", "w", stdout); freopen("CONOUT$", "w", stderr);
Hallo,
vielen Dank für die Hilfe. Nun klappt es genau so, wie ich mir das vorgestellt habe.
Danke und ein schönes Wochenende
floriank
-
pale dog schrieb:
eine andere möglichkeit wäre es, 'putchar()' zu überladen.
putchar ist ein Makro. Also umdefinieren. Allerdings ist es mindestens genauso schwer, die Auswirkungen dieses Tricks abzuschätzen, wie diesen wilden HackWW^Wdiese Funktion zu reparieren.
-
Bashar schrieb:
putchar ist ein Makro.
schreibt das der C standard vor?
ich kann mich dunkel an eine c-library erinnern, bei der man die putchar() funktion selber schreiben musste, um die bytes irgendwo hinzuschieben...
-
pale dog schrieb:
Bashar schrieb:
putchar ist ein Makro.
schreibt das der C standard vor?
Ups, mein Wissen ist veraltet. Es scheint, dass zumindest C99 das nicht vorschreibt, aber explizit die Möglichkeit einräumt, dass Standardlibraryfunktionen zusätzlich als Makros definiert sind. Um also den Linker-Trick anwenden zu können, müsste man mindestens noch #undef putchar angeben.
-
Kann man in C überhaupt Funktionen überladen, wäre mir neu, kenne das nur von C++.
-
void overload(){} void overload( int i ){} main(){}
--------------------Konfiguration: main - Win32 Release-------------------- Kompilierung läuft... main.c E:\MyProjects\Forum\main.c(285) : error C2084: Funktion 'void __cdecl overload()' hat bereits einen Funktionsrumpf E:\MyProjects\Forum\main.c(285) : warning C4027: Funktion ohne Liste formaler Parameter deklariert Fehler beim Ausführen von cl.exe. main.exe - 1 Fehler, 1 Warnung(en)
-
proggingmania schrieb:
Kann man in C überhaupt Funktionen überladen, wäre mir neu, kenne das nur von C++.
pale dog meint, die Definition zum Linkzeitpunkt zu überschreiben. Überladen ist in der Tat der falsche Begriff.
-
Bashar schrieb:
Um also den Linker-Trick anwenden zu können, müsste man mindestens noch #undef putchar angeben.
würde aber nichts helfen, wenn man z.b. 'printf' umlenken will, das auch putchar aufruft um zeichen auszugeben. es muss schon beim linken passieren.
und ein '#define putchar putchar' gibt's ja wohl nicht...Bashar schrieb:
Überladen ist in der Tat der falsche Begriff.
stimmt, überladen ist, wenn der name gleich bleibt, aber die argumentenliste sich ändert. ich bring' das immer durcheinander...
-
Aber besonders portabel dürfte so etwas auch nicht sein.
Vor allem wirkt so ein "#define putchar(c) ..." auch nur, wenn du die Zielbibliothek neu compilieren kannst (beim Linker bin ich mir auf Anhieb nicht so sicher). Und wenn du den Quelltext vorliegen hast, kannst du ihn vermutlich gleich überarbeiten, damit er beliebige FILE's als Ziel übernehmen kann.
PS: Auch wenn ich dafür bestimmt aus dem Board gejagt werde: In C++ ist sowas eleganter gelöst:
fstream logout("logfile.txt"); stream_buf* oldbuf = cout.rdbuf(); print();//Ausgaben auf Standard-IO (Monitor) //natürlich sollte die print()-Funktion hier auch die <iostream> verwenden ;) cout.rdbuf(logout.rdbuf(); print();//Ausgaben ins File cout.rdbuf(oldbuf);