Ich möchte die stdin und stdout (und vielleicht stderr während Im an ihm) filehandles wieder öffnen, damit zukünftige Aufrufe zu printf () oder putchar () oder puts () in eine Datei und zukünftige Aufrufe zu getc () und solche gehen Wird aus einer Datei kommen. 1) Ich möchte nicht dauerhaft zu verlieren Standard-Eingabe / Ausgabe / Fehler. Vielleicht möchte ich sie später im Programm wiederverwenden. 2) Ich möchte nicht öffnen Sie neue Dateihandles, da diese Dateihandles entweder um eine Menge oder global (shudder) umgangen werden müssen. 3) Ich möchte keine open () oder Gabel () oder andere systemabhängige Funktionen verwenden, wenn ich nicht helfen kann. Also im Grunde, es funktioniert, um dies zu tun: Und, wenn es tut, wie bekomme ich den ursprünglichen Wert von stdin zurück Muss ich es in einer Datei speichern und nur erhalten es später wieder Warum verwenden Sie freopen (). Die C89-Spezifikation hat die Antwort in einem der Endnoten für den Abschnitt über ltstdio. hgt: 116. Die primäre Verwendung der freopen-Funktion besteht darin, die Datei zu ändern, die mit einem Standardtextstrom (stderr. Stdin. Oder stdout) assoziiert ist Identifikatoren müssen nicht modifizierbare l-Werte sein, auf die der von der fopen-Funktion zurückgegebene Wert zugewiesen werden kann. Freopen wird häufig missbraucht, z. B. Stdin freopen (newin, r, stdin). Das ist nicht tragbarer als fclose (stdin) stdin fopen (newin, r). Beide Ausdrücke versuchen, stdin zuzuordnen. Die nicht zuzuordnen ist. Der richtige Weg zur Verwendung von freopen ist, die Zuweisung weglassen: freopen (newin, r, stdin) Klarstellung: Syntaktische Zuordnung zu stdin. Wie in stdin fopen (.) Oder stdin freopen (.). Ist nicht portabel, da stdin darf ein Makro sein. Stdio. h enthält möglicherweise define stdin builtingetstdin (). Und natürlich kannst du das nicht auf die LHS eines Auftrags setzen. ChrisLutz, der richtige Weg, um freopen verwenden ist einfach, wenn (freopen (quotnewinquot, quotrquot, stdin) NULL). --- der Rückgabewert ist nützlich, um anzuzeigen, ob das Öffnen fehlgeschlagen ist, aber Sie sollten es im Allgemeinen nicht zuweisen müssen. Ndash Quuxplusone Dec 19 13 at 18:06 Die os Funktion dup2 () sollte liefern, was Sie brauchen (wenn nicht Hinweise auf genau das, was Sie benötigen). Genauer gesagt können Sie dup2 () den stdin-Dateideskriptor auf einen anderen Dateideskriptor, andere Sachen mit stdin und dann kopieren Sie es zurück, wenn Sie möchten. Die Funktion dup () dupliziert einen geöffneten Dateideskriptor. Insbesondere stellt es eine alternative Schnittstelle zu dem Dienst bereit, der durch die fcntl () - Funktion unter Verwendung des konstanten FDUPFD-Befehlswertes bereitgestellt wird, mit 0 für sein drittes Argument. Der doppelte Dateideskriptor teilt alle Sperren mit dem Original. Bei Erfolg gibt dup () einen neuen Dateideskriptor zurück, der mit dem Original übereinstimmt: Gleiche Datei (oder Pipe) Gleicher Dateizeiger (beide Dateideskriptoren teilen sich einen Dateizeiger) Gleicher Zugriffsmodus (lesen, schreiben oder lesen) / Write) beantwortet Feb 25 09 at 6:22 Die Frage explizit sagt nicht auf systemabhängige Funktionen verwenden, though. Ndash unwind Feb 25 09 at 6:55 Und die Frage explizit sagt, begrenzen die der offenen Streams / Datei-Deskriptoren ndash Tim Post 9830 Feb 25 09 at 15:23 Das spitzt die Nadel auf meinem Round-Peg-Quadrat-Loch-O-Meter , Was versuchst du zu erreichen Denken Sie daran, dass stdin, stdout und stderr Dateideskriptoren 0, 1 und 2 für jeden neu geschaffenen Prozess sind. Freopen () sollte die gleichen fds beibehalten, nur neue Streams zuweisen. Also, ein guter Weg, um sicherzustellen, dass dies tatsächlich tun, was Sie wollen, es zu tun wäre: Ich glaube, das ist das erwartete Verhalten von freopen (), wie Sie sehen können, youre immer noch nur mit drei Dateideskriptoren (und zugehörige Streams) . Dies würde überschreiben jede Shell-Umleitung, da es nichts für die Shell zu umleiten wäre. Allerdings ist es wahrscheinlich zu brechen Pfeifen. Möglicherweise möchten Sie sicher sein, einen Handler für SIGPIPE einzurichten, falls sich Ihr Programm am blockierenden Ende einer Pipe (nicht FIFO, Pipe) befindet. Damit. / Yourprogram --stdout /tmp/stdout. txt --stderr /tmp/stderr. txt sollte einfach mit freopen () ausgeführt werden und die gleichen tatsächlichen Dateideskriptoren beibehalten. Was ich nicht verstehe, ist, warum youd müssen sie wieder einmal ändern sie sicherlich, wenn jemand eine Option bestanden, würden sie wollen, dass es bestehen bleibt, bis das Programm beendet antwortete am 25. Februar um 15:31 Uhr Hallo Tim. Hatte Ärger mit dem Kommentar Eingang in meinem letzten Post. Es doesn39t wie copy39n39paste aus irgendeinem Grund. Wollte auf der Liste der Ausgabe und geben sys Details, aber es wurde gesendet, bevor ich bereit war. Die ersten beiden Anweisungen tun, wie man erwarten würde, aber die letzte ein quotAnd dies sollte auf dem Bildschirm wieder zu tun nicht tun. I39m kompilieren auf XCode clang 500.2.79 unter Mac OS X 10.9.5. Ich habe sogar versucht wieder zu öffnen Stdout bei / dev / tty auch ohne Freude. It39s, als ob einmal stdout neu definiert worden ist, ist es Spiel vorbei. Ndash VectorVictor Dies ist eine modifizierte Version der Tim Posts-Methode, die ich / dev / tty anstelle von / dev / stdout verwendet habe. Ich weiß nicht, warum es funktioniert nicht mit stdout (das ist ein Link zu / proc / self / fd / 1): Mit / dev / tty wird die Ausgabe an das Terminal umgeleitet, von wo aus die App gestartet wurde. Hoffe, diese Info ist nützlich. Freopen löst das einfache Teil. Halten Sie alte stdin herum ist nicht hart, wenn Sie havent gelesenes etwas und wenn youre, das bereit ist, POSIX Systemaufrufe wie dup oder dup2 zu verwenden. Wenn youre begann, daraus zu lesen, sind alle Wetten ausgeschaltet. Vielleicht können Sie uns sagen, den Kontext, in dem dieses Problem auftritt Id ermutigen Sie, sich an Situationen, in denen Sie bereit sind, alte stdin und stdout verlassen und können daher freopen. Ich glaube, ich könnte weg mit dem Verzicht auf die alten stdin / stdout, wenn ich wirklich musste. I39m versuchen, um mein Programm eine Option für das Programm, um Stdin und stdout selbst umleiten, für Leute, die das Programm laufen und don39t kennen ihre Shell sehr gut. Nur für die Hölle. Ndash Chris Lutz Feb 25 09 at 6:40 Meine Studenten haben definitiv Probleme mit I / O-Umleitung, so dass Ihr Ziel klingen wie ein guter. Vielleicht you39d besser mit Befehlszeilenoptionen - i und - o zu nennen Eingabe-und Ausgabedateien ndash Norman Ramsey Feb 25 09 um 6: 43fopen (3) - Linux man Seite fopen, fdopen, freopen - Stream öffnen Funktionen Feature Test Macro Voraussetzungen für glibc (siehe featuretestmacros (7)): fdopen (): POSIXCSOURCE gt 1 XOPENSOURCE POSIXSOURCE Beschreibung Die Funktion fopen () öffnet die Datei, deren Name die Zeichenfolge ist, auf die der Pfad verweist. Der Argumentmodus zeigt auf einen String, der mit einer der folgenden Sequenzen beginnt (ggf. mit zusätzlichen Zeichen, wie nachfolgend beschrieben): r Textdatei zum Lesen öffnen. Der Stream wird am Anfang der Datei positioniert. Offen für Lesen und Schreiben. Der Stream wird am Anfang der Datei positioniert. Truncate Datei auf Null Länge oder erstellen Textdatei zum Schreiben. Der Stream wird am Anfang der Datei positioniert. Offen für Lesen und Schreiben. Die Datei wird erstellt, wenn sie nicht vorhanden ist, andernfalls wird sie abgeschnitten. Der Stream wird am Anfang der Datei positioniert. Offen für Anhängen (Schreiben am Ende der Datei). Die Datei wird erstellt, wenn sie nicht existiert. Der Stream wird am Ende der Datei positioniert. Offen für das Lesen und Anhängen (Schreiben am Ende der Datei). Die Datei wird erstellt, wenn sie nicht existiert. Die Anfangsdateiposition zum Lesen ist am Anfang der Datei, aber die Ausgabe wird immer an das Ende der Datei angefügt. Der Modus-String kann auch den Buchstaben b entweder als ein letztes Zeichen oder als ein Zeichen zwischen den Zeichen in einer der oben beschriebenen Zwei-Zeichen-Zeichenfolgen enthalten. Dies ist ausschließlich für die Kompatibilität mit C89 und hat keine Wirkung, die b wird ignoriert auf allen POSIX-konformen Systemen, einschließlich Linux. (Andere Systeme können Textdateien und Binärdateien unterschiedlich behandeln, und das Hinzufügen von b kann eine gute Idee sein, wenn Sie E / A in einer Binärdatei ausführen und erwarten, dass Ihr Programm in Nicht-UNIX-Umgebungen portiert werden kann.) Siehe HINWEISE unten Details der glibc Erweiterungen für den Modus. Alle erstellten Dateien haben den Modus SIRUSR SIWUSR SIRGRP SIWGRP SIROTH SIWOTH (0666), modifiziert durch den Prozess-umask-Wert (siehe umask (2)). Lesevorgänge und Schreibvorgänge können in Lese - / Schreibströmen in beliebiger Reihenfolge gemischt werden. Beachten Sie, dass ANSI C erfordert, dass eine Dateipositionierungsfunktion zwischen Ausgabe und Eingabe eingreift, es sei denn, eine Eingabeoperation erkennt das Ende der Datei. (Wenn diese Bedingung nicht erfüllt ist, dann wird ein Lesen erlaubt, das Ergebnis von Schreibvorgängen zurückzugeben, die nicht das jüngste sind.) Daher ist es eine gute Praxis (und manchmal auch unter Linux erforderlich), einen fseek (3) oder fgetpos (3 ) - Betrieb zwischen Schreib - und Leseoperationen auf einem solchen Strom. Dieser Vorgang kann ein scheinbares no-op sein (wie bei fseek (. 0L, SEEKCUR), das für seinen synchronisierenden Nebeneffekt aufgerufen wird. Das Öffnen einer Datei im Append-Modus (a als erstes Zeichen des Modus) bewirkt, dass alle nachfolgenden Schreibvorgänge in diesem Stream ausgeführt werden Die Funktion fdopen () verknüpft einen Stream mit dem vorhandenen Dateideskriptor fd. Der Modus des Streams (einer der Werte r, r, w, w, a, A) muss mit dem Modus des Dateideskriptors kompatibel sein. Der Dateipositionsindikator des neuen Streams ist auf diejenige, die zu fd gehört, gesetzt und die Fehler - und End-of-Datei-Indikatoren werden gelöscht. Modus w oder w verursachen keine Verkürzung Das Ergebnis der Anwendung von fdopen () auf ein gemeinsames Speicherobjekt ist undefined Die Funktion freopen () öffnet die Datei, deren Name ist die Zeichenfolge, auf die durch den Pfad hingewiesen wird, und verknüpft den Stream, auf den der Stream zeigt, mit dem es verbunden ist. Der ursprüngliche Stream (falls vorhanden) wird geschlossen. Das Argument mode wird genau wie in der fopen () - Funktion verwendet. Die primäre Verwendung der Funktion freopen () besteht darin, die Datei zu ändern, die mit einem Standardtextstrom (stderr. Stdin. Oder stdout) verknüpft ist. Rückgabewert Nach erfolgreichem Abschluss erhalten fopen (), fdopen () und freopen () einen FILE-Pointer. Andernfalls wird NULL zurückgegeben und errno wird gesetzt, um den Fehler anzuzeigen. Der Modus für fopen (), fdopen () oder freopen () war ungültig. Die Funktionen fopen (), fdopen () und freopen () können ebenfalls fehlschlagen und errno für jeden der für den Routine-malloc (3) angegebenen Fehler setzen. Die fopen () - Funktion kann auch fehlschlagen und errno für einen der Fehler festlegen, die für die Routine offen (2) angegeben werden. Die fdopen () - Funktion kann ebenfalls fehlschlagen und errno für einen der für die Routine fcntl (2) angegebenen Fehler setzen. Die Funktion freopen () kann ebenfalls fehlschlagen und errno für einen der für die Routinen open (2), fclose (3) und fflush (3) angegebenen Fehler setzen. Anpassen Die Funktionen fopen () und freopen () entsprechen C89. Die Funktion fdopen () entspricht POSIX.1-1990. Glibc-Hinweise Die GNU C-Bibliothek ermöglicht die folgenden Erweiterungen für die im Modus angegebene Zeichenfolge. C (seit glibc 2.3.3) Führen Sie keine Löschvorgänge oder nachfolgende Lese - und Schreiboperationen durch. Dieses Flag wird für fdopen () ignoriert. E (seit glibc 2.7) Öffnen Sie die Datei mit dem Flag OCLOEXEC. Siehe open (2) für weitere Informationen. Dieses Flag wird für fdopen () ignoriert. M (seit glibc 2.3) Versuch, mit mmap (2) auf die Datei zuzugreifen, anstelle von I / O-Systemaufrufen (read (2), write (2)). Derzeit wird die Verwendung von mmap (2) nur für eine Datei versucht, die zum Lesen geöffnet ist. X Öffnen Sie die Datei exklusiv (wie das OEXCL-Flag von open (2)). Wenn die Datei bereits vorhanden ist, schlägt fopen () fehl und setzt errno auf EEXIST. Dieses Flag wird für fdopen () ignoriert. Zusätzlich zu den oben genannten Zeichen unterstützen fopen () und freopen () die folgende Syntax im Modus. Der angegebene String wird als der Name eines codierten Zeichensatzes genommen und der Stream als weit ausgerichtet markiert. Danach konvertieren interne Umwandlungsfunktionen E / A zu und von der Zeichensatzkette. Wenn die Syntax der ccs-Zeichenkette nicht angegeben wird, wird die Breitorientierung des Datenstroms durch die erste Dateiverwendung bestimmt. Wenn es sich bei diesem Vorgang um eine Großzeichenoperation handelt, wird der Stream weitorientiert markiert, und Funktionen, die in den codierten Zeichensatz konvertiert werden, werden geladen. Bei der Analyse einzelner Flag-Zeichen im Modus (dh die der ccs-Spezifikation vorangestellten Zeichen) begrenzt die glibc-Implementierung von fopen () und freopen () die Anzahl der im Modus auf 7 untersuchten Zeichen (oder in glibc-Versionen vor 2.14 bis 6) , Das war nicht genug, um mögliche Spezifikationen wie rbcmxe enthalten). Die aktuelle Implementierung von fdopen () analysiert höchstens 5 Zeichen im Modus. Referenziert ByOpens die Datei, deren Name im Parameter Dateiname angegeben ist, und verknüpft sie mit einem Stream, der in zukünftigen Operationen durch den zurückgegebenen FILE-Zeiger identifiziert werden kann. Die Operationen, die auf dem Stream erlaubt sind und wie diese ausgeführt werden, werden durch den Parameter mode definiert. Der zurückgegebene Stream wird standardmäßig vollständig gepuffert, wenn bekannt ist, dass er sich nicht auf ein interaktives Gerät bezieht (siehe setbuf). Der zurückgegebene Zeiger kann aus der Datei durch Aufruf von fclose oder freopen disassoziiert werden. Alle geöffneten Dateien werden bei normaler Programmbeendigung automatisch geschlossen. Die laufende Umgebung unterstützt mindestens FOPENMAX-Dateien, die gleichzeitig geöffnet sind. Parameter Dateiname C-String mit dem Namen der zu öffnenden Datei. Der Wert muss dem Dateinamen der laufenden Umgebung entsprechen und kann einen Pfad enthalten (sofern vom System unterstützt). C-String mit einem Dateizugriffsmodus. Es kann sein: lesen: Datei für Eingabeoperationen öffnen. Die Datei muss vorhanden sein. Schreiben: Leere Datei für Ausgabeoperationen erstellen. Wenn bereits eine Datei mit demselben Namen existiert, wird ihr Inhalt verworfen und die Datei als neue leere Datei behandelt. Append: Datei für die Ausgabe am Ende einer Datei öffnen. Ausgabeoperationen schreiben immer Daten am Ende der Datei und erweitern sie. Neupositionierungen (fseek. Fsetpos rückspulen) werden ignoriert. Die Datei wird erstellt, wenn sie nicht existiert. Lesen / aktualisieren: Öffnen Sie eine Datei für die Aktualisierung (sowohl für die Eingabe und Ausgabe). Die Datei muss vorhanden sein. Write / update: Erstellen Sie eine leere Datei und öffnen Sie sie zum Update (sowohl für die Eingabe als auch für die Ausgabe). Wenn eine Datei mit demselben Namen bereits vorhanden ist, wird ihr Inhalt verworfen und die Datei als neue leere Datei behandelt. Append / update: Öffnen Sie eine Datei für die Aktualisierung (sowohl für die Eingabe als auch für die Ausgabe), wobei alle Ausgabeoperationen Daten am Ende der Datei schreiben. Die Neupositionierungen (fseek. Fsetpos rewind) wirken sich auf die nächsten Eingabeoperationen aus, aber die Ausgabeoperationen verschieben die Position zurück zum Ende der Datei. Die Datei wird erstellt, wenn sie nicht existiert. Bei den obigen Modus-Spezifizierungen ist die Datei als Textdatei geöffnet. Um eine Datei als Binärdatei zu öffnen. Muss ein b-Zeichen in der Moduszeichenfolge enthalten sein. Dieses zusätzliche b-Zeichen kann entweder am Ende des Strings angefügt werden (wodurch die folgenden Verbindungsmodi erzeugt werden: rb, wb, ab, rb, wb, ab) oder zwischen dem Buchstaben und dem Vorzeichen für die gemischten Modi (rb, Wb, ab). Der neue C-Standard (C2011, der nicht Teil von C ist) fügt einen neuen Standard-Subpecifier (x) hinzu, der an beliebige w-Spezifizierer angehängt werden kann (um wx. Wx oder wbx / wbx zu bilden). Dieser subspecifier erzwingt, dass die Funktion fehlschlägt, wenn die Datei existiert, anstatt sie zu überschreiben. Wenn zusätzliche Zeichen der Sequenz folgen, hängt das Verhalten von der Bibliotheksimplementierung ab: Einige Implementierungen können zusätzliche Zeichen ignorieren, so dass beispielsweise ein zusätzliches t (manchmal verwendet, um explizit eine Textdatei anzugeben) akzeptiert wird. Bei einigen Bibliotheksimplementierungen kann das Öffnen oder Erstellen einer Textdatei mit Aktualisierungsmodus den Stream stattdessen als Binärdatei behandeln. Textdateien sind Dateien, die Sequenzen von Textzeilen enthalten. Abhängig von der Umgebung, in der die Anwendung ausgeführt wird, kann eine spezielle Zeichenumwandlung bei Eingabe / Ausgabe-Operationen im Textmodus auftreten, um sie an ein systemspezifisches Textdateiformat anzupassen. Obwohl in einigen Umgebungen keine Konvertierungen auftreten und sowohl Textdateien als auch Binärdateien auf die gleiche Weise behandelt werden, verbessert der geeignete Modus die Portabilität. Für Dateien, die zum Aktualisieren geöffnet sind (solche, die ein Vorzeichen enthalten), auf denen sowohl Eingabe - als auch Ausgabeoperationen erlaubt sind, muss der Stream vor einem Lesevorgang, der einem Schreibvorgang folgt, gespült (fflush) oder neu positioniert (fseek. Der Stream muss vor einem Schreibvorgang, der einem Lesevorgang folgt (wann immer dieser Vorgang nicht das Ende der Datei erreicht hat), neu positioniert (fseek. Fsetpos rewind) werden. Rückgabewert Wenn die Datei erfolgreich geöffnet wurde, gibt die Funktion einen Zeiger auf ein FILE-Objekt zurück, mit dem der Stream bei zukünftigen Operationen identifiziert werden kann. Andernfalls wird ein Nullzeiger zurückgegeben. Bei den meisten Bibliotheksimplementierungen wird die errno-Variable ebenfalls auf einen systemspezifischen Fehlercode bei einem Fehler gesetzt.
No comments:
Post a Comment