Information

2.4: Dateieingabe und -ausgabe - Biologie

2.4: Dateieingabe und -ausgabe - Biologie


We are searching data for your request:

Forums and discussions:
Manuals and reference books:
Data from registers:
Wait the end of the search in all databases.
Upon completion, a link will appear to access the found materials.

Bisher waren alle Daten, mit denen wir gearbeitet haben, in unseren Programmen „hartcodiert“. Im wirklichen Leben suchen wir jedoch nach Daten aus externen Dateien.

Wir können auf Daten zugreifen, die in einer externen Datei (normalerweise einer Textdatei) vorhanden sind, indem wir a Datei-Handle, ein spezieller Datentyp, mit dem wir uns über eine externe Quelle verbinden können. In seiner einfachsten Form funktioniert ein Dateihandle zum Lesen von Daten wie eine Pipe: Das Betriebssystem legt Daten (normalerweise Strings) an einem Ende ab, und wir extrahieren Daten aus dem anderen Ende, normalerweise eine Zeile nach der anderen. Dateihandles zum Schreiben in Dateien verschieben die Daten in die entgegengesetzte Richtung.

Um ein Datei-Handle in Python zu verwenden, müssen wir dem Interpreter mitteilen, dass wir einige Eingabe-/Ausgabefunktionen verwenden möchten, indem wir zuerst den speziellen Befehl eingebenimportierenganz oben in unserem Programm. Dieser Befehl importiert dieioModul und stellt darin vorhandene Zusatzfunktionen zur Verfügung. Diese Funktionen verwenden auch eine Punktsyntax, um das Modul anzugeben, in dem sie vorhanden sind, was der zuvor für Methoden besprochenen Punktsyntax zum Verwechseln ähnlich ist. So verknüpfen Sie ein Datei-Handle namensfhandlemit der Datei „Dateiname.txt", zum Beispiel lautet der Befehlfhandle = io.open("Dateiname.txt", "rU"), wooffen()ist eine Funktion im importiertenioModul. DieRgibt an, dass wir ein schreibgeschütztes Datei-Handle erstellen, und dieUlässt den Interpreter wissen, dass wir eine „universelle“ Interpretation für Zeilenumbrüche wünschen, um das Lesen von Dateien zu ermöglichen, die auf Microsoft Windows-Systemen oder Unix-ähnlichen Systemen erstellt wurden.[1] Der Datei-Handle-Datentyp hat eine Methode namens.Zeile lesen(), die die nächste verfügbare Zeile aus der Pipe als String zurückgibt; so,line = fhandle.readline()extrahiert einen String (Zeile) aus dem Datei-Handle und weist ihn zuLeitung.

Lassen Sie uns eine kleine Datei mit drei Zeilen erstellen, die jeweils eine Gen-ID, eine Registerkarte und einen entsprechenden GC-Inhaltswert enthalten.

Lassen Sie uns nun ein Programm erstellen, das die Daten liest und druckt. Wenn wir mit dem Lesen von Daten aus einer Datei fertig sind, müssen wir die Dateihandles ausführen.nah dran()Methode. Verwenden von.nah dran()bewirkt, dass das Datei-Handle das Betriebssystem benachrichtigt, dass wir mit dem Lesen der Daten aus dem Handle fertig sind. An diesem Punkt steht es dem Betriebssystem frei, die Back-End-„Pipe“ und alle darin enthaltenen Daten zu entfernen.

Wenn die Datei nicht existiert oder vom Programm nicht gelesen werden kann, erhalten Sie eineIOFehlerentweder anzeigenKeine solche Datei oder OrdneroderErlaubnis verweigertmit dem Dateinamen, den Sie zu öffnen versucht haben.[2] Da unsere Datei existiert, können wir den Code erfolgreich ausführen und die Ergebnisse überprüfen:

Hier gibt es einiges zu beachten. Erstens, jedes Mal, wenn wir anrufenfhandle.readline(), gibt das Datei-Handle eine andere Zeichenfolge zurück: die nächste Zeichenfolge, die darauf wartet, aus der Pipe gezogen zu werden. Zweitens sehen wir, dass die Ausgabe unsere drei Zeilen enthält, aber durch Leerzeilen getrennt: Dies liegt daran, dass die Datei bereits „Neuzeilen“-Zeichen enthält. Wir sehen diese Newline-Zeichen nicht, können sie aber selbst darstellen, wenn wir möchten, in einer Zeichenfolge mit dem Steuercode . Ebenso haben Tabulatorzeichen einen Steuercode wieT. Die Datei ist eigentlich eine einzelne serielle Zeichenfolge, und die.Zeile lesen()-Methode fordert das Datei-Handle auf, alles bis einschließlich des nächsten zurückzugeben .

Der Grund für die Leerzeilen in unserer Ausgabe ist letztendlich, dass diedrucken()Funktion, für unsere Bequemlichkeit, hängt a bis zum Ende eines beliebigen Strings, den wir ausgeben (andernfalls würde sich der Großteil unserer Ausgabe in derselben Zeile befinden). Somit wird jede aus der Datei eingelesene Zeile mit zwei Zeichen. Wir werden später lernen, wie man ohne zusätzlichen Zeilenumbruch druckt, wenn wir lernen, Daten in Dateien zu schreiben. Im Moment lösen wir das Problem, indem wir führende und nachgestellte Leerzeichen (Leerzeichen, Tabulatoren und Zeilenumbrüche) entfernen, indem wir einen String bitten, seine auszuführen.Streifen()Methode.

Obwohl wir anrufenimportierenAuch hier dient dies nur der Übersichtlichkeit: Ein Programm muss ein Modul nur einmal importieren (und normalerweise werden diese am oberen Rand des Programms gesammelt). Hier ist die modifizierte Ausgabe:

Wenn du dich abenteuerlustig fühlst (und du solltest!), kannst du es versuchen Methodenverkettung, wobei die Punktsyntax für Methoden angehängt werden kann, solange die vorherige Methode den richtigen Typ zurückgegeben hat.

Um dies mit früheren Konzepten zu verbinden, können wir, nachdem wir jede Zeile extrahiert und den abschließenden Leerraum entfernt haben, verwenden.split(" ")um jede Zeile in eine Liste von Strings aufzuteilen. Von dort können wir verwendenschweben()um das zweite Element von jedem in einen Float-Typ umzuwandeln und den mittleren GC-Inhalt zu berechnen.

Oben druckt der durchschnittliche GC-Gehalt der drei Zeilen als0.523333333. (Weil.Streifen()gibt auch einen String zurück, wir könnten weitere verkettete Methoden haben, wie inline1_list = fhandle.readline().strip().split(" ").)

Da Datei-Handles wie eine Pipe funktionieren, erlauben sie keinen „random access“; wir können das nächste Datenbit aus dem Ende der Pipe holen, aber das war's.[3] Man könnte meinen, dass ein Befehl wieline5 = fhandle[4]würde funktionieren, aber stattdessen würde es einen Fehler erzeugen wieTypeError: '_io.BufferedReader'-Objekt hat kein Attribut '__getitem__'.

Auf der anderen Seite sind Dateihandles wie Listen iterierbar, was bedeutet, dass wir eine for-Schleife verwenden können, um auf jede Zeile der Reihe nach zuzugreifen. Ein einfaches Programm zum Lesen von Zeilen einer Datei und zum Drucken nacheinander (ohne zusätzliche Leerzeilen) könnte so aussehen:

Mögen.Zeile lesen(), mit einer for-Schleife werden Leitungen aus dem Rohr extrahiert. Also, wenn du anrufst.Zeile lesen()zweimal auf einem Datei-Handle, das an eine Datei mit 10 Zeilen angehängt ist, und dann eine for-Schleife auf diesem Datei-Handle ausführen, wird die for-Schleife über die verbleibenden 8 Zeilen iterieren. Dieser Aufruf kann sinnvoll sein, wenn Sie beispielsweise eine Kopfzeile aus einer Texttabelle entfernen möchten, bevor Sie die restlichen Zeilen mit einer Schleife bearbeiten.

Schreiben von Daten

Das Schreiben von Daten in eine Datei funktioniert ähnlich wie das Lesen von Daten: Wir öffnen ein Datei-Handle (das wiederum wie eine Pipe funktioniert) und rufen eine Methode für das Handle namens . auf.schreiben()um Strings darauf zu schreiben. In diesem Fall verwenden Sie statt der"rU"Parameter beim Aufrufenio.open(), wir verwenden"w"um anzuzeigen, dass wir in die Datei schreiben möchten. Seien Sie gewarnt: Wenn Sie ein Datei-Handle auf diese Weise zum Schreiben öffnen, überschreibt es alle vorhandenen Inhalte der Datei. Wenn Sie lieber an die Datei anhängen möchten, können Sie stattdessen verwenden"ein".[4]

nicht so wiedrucken()Funktion, die.schreiben()Methode eines Datei-Handles enthält nicht automatisch ein zusätzliches Newline-Zeichen" ". Wenn Sie also mehrere Zeilen in ein Datei-Handle schreiben möchten, müssen Sie diese selbst hinzufügen. Hier ist ein Beispiel, das die Zahlen druckt0durch9in eine Datei, eine pro Zeile.

Wie oben erwähnt, funktioniert ein zum Schreiben geöffnetes Datei-Handle wie eine Pipe, die vom Betriebssystem eingerichtet wird. Beim Schreiben legen wir jedoch Daten in die Pipe, und das Betriebssystem zieht die Daten auf der anderen Seite heraus und schreibt sie in die Datei auf der Festplatte.

Da das Betriebssystem damit beschäftigt ist, ähnliche Anforderungen für viele Programme auf dem System zu bearbeiten, kommt es möglicherweise nicht dazu, die Daten aus der Pipe zu ziehen und sofort in die Datei auf der Festplatte zu schreiben. Es ist also wichtig, dass wir daran denken, die anzurufen.nah dran()Methode für das Dateihandle, wenn wir mit dem Schreiben von Daten fertig sind; Dies teilt dem Betriebssystem mit, dass alle in der Pipe verbliebenen Informationen ausgespült und auf der Festplatte gespeichert werden sollen und dass die Pipe-Struktur bereinigt werden kann. Wenn unser Programm abstürzt (oder beendet wird), bevor das Handle richtig geschlossen wurde, werden die Daten in der Pipe möglicherweise nie geschrieben.

Berechnung eines Mittelwerts

Lassen Sie uns viele der bisher erlernten Fähigkeiten in die Praxis umsetzen, um den Mittelwert der zu berechnen E Werte aus der Ausgabe von BLAST, die als einfache Texttabelle mit Tabulatoren formatiert ist, die die Spalten trennen. Hier ist die Datei, pz_blastx_yeast_top1.txt, sieht aus wie inweniger -S. Obwohl der Leser uns beim Wort vertrauen muss, enthält die elfte Spalte dieser Datei E Werte wie5e-14,2e-112, und1e-18.

Wenn Sie ein Problem wie dieses lösen, ist es normalerweise eine gute Idee, zuerst in einfachem Englisch (oder Ihrer bevorzugten Nicht-Programmiersprache) die Strategie Sie verwenden möchten, um das Problem zu lösen. Die Strategie hier ist wie folgt: Der Mittelwert einer Reihe von Zahlen wird als ihre Summe dividiert durch deren Anzahl definiert. Wir müssen mindestens zwei wichtige Variablen behalten,eval_sumundSchalter. Nach dem Öffnen der Datei mitio.open(), wir können die Zeilen durchlaufen und jede extrahieren E Wert. (Dies erfordert die Reinigung der Leitung mit.Streifen(), in Stücke teilen mit.split(" "), und schließlich das Umwandeln der E Wert in einen Float anstatt den String zu verwenden.) Für jede Zeile, die wir sehen, können wir den E Wert extrahiert in dieeval_sumvariabel, und wir fügen hinzu1zumSchalterauch variabel. Am Ende können wir einfach berichteneval_sum/counter.

Es hilft oft, diese Strategie in etwas zwischen natürlicher Sprache und Code umzuwandeln, genannt Pseudocode, die besonders bei komplexen Programmen enorm helfen kann, Ihre Gedanken zu ordnen:

import ioopen fhandlecounter = 0sum_eval = 0.0für jede Zeile in fhandlelinestripped = line.strip()Brechen Sie in eine Liste von Strings mit line_list = linestripped.split("	")eval als String ist in line_list bei Index 10 (11. Spalte) Füge float(eval) zu sum_eval hinzu und speichere in sum_evalAdd 1 zum Zählen und Speichern in countmean = sum_eval geteilt durch counterprint("mean is" + mean)

Mit dem skizzierten Pseudocode können wir den eigentlichen Code für unser Programm schreiben. Wenn es ausgeführt wird, druckt es zuverlässigMittelwert ist: 1.37212611293e-08.

Beachten Sie, dass der eigentliche Python-Code (in blast_mean.py) sah dem Pseudocode ziemlich ähnlich – dies ist eines der häufig zitierten Verkaufsargumente für Python. (Aus diesem Grund überspringen wir auch den Pseudocode-Schritt für die meisten Beispiele in diesem Buch, obwohl er beim Programmieren in jeder Sprache immer noch eine wertvolle Technik sein kann.)

Dies mag wie eine Menge Arbeit erscheinen, um einen einfachen Mittelwert zu berechnen, aber es ist eine Folge des Schreibens von Software „von Grund auf“ und wir müssen irgendwo anfangen! Darüber hinaus wird sich der Vorteil des Erlernens dieser Techniken auf lange Sicht auszahlen, wenn es darum geht, neue Probleme zu lösen.

Der Programmierprozess

Obwohl der Prozess des Entwerfens einer Strategie (und eines Pseudocodes) mühsam erscheint, wird er dringend empfohlen. Wenn Sie Ihre Fähigkeiten verbessern, werden Ihre Strategien und Ihr Pseudocode knapper und auf höherem Niveau, aber Sie sollten die Planungsschritte vor dem Codieren niemals überspringen. (Andererseits besteht auch die Gefahr der Überplanung, die jedoch häufiger Teams von Programmierern betrifft, die an großen Projekten arbeiten.)

An dieser Stelle ist noch etwas erwähnenswert: Programme wie die oben genannten werden fast nie vollständig von oben nach unten geschrieben, zumindest nicht ohne erhebliches Debugging! Sie können vergessen, dass das Ergebnis der Aufteilung einer Zeichenfolge eine Liste von Zeichenfolgen ergibt, was zu einem Fehler in einer Zeile wie . führteval_sum = eval_sum + eval_strdaeval_sumist ein Schwimmer, währendeval_strist eine Zeichenfolge. Nachdem Sie diesen Fehler gefunden und behoben haben, finden Sie möglicherweise einen weiteren Fehler, wenn Sie versuchen, mit einer Zeile wie . zu druckenprint("Mittelwert ist: " + Mittelwert), denn auch hier stimmen die Typen nicht überein und können nicht verkettet werden. Nach all dem ist der resultierende Mittelwert vielleicht unerwartet eine große Zahl, wie zum Beispiel131.18, nur um herauszufinden, dass es daran lag, dass du es versehentlich benutzt hasteval_str = line_list[11], vergessen, dass Listenindizes bei beginnen0.

Es gibt zwei Strategien, um lange Ketten von lästigen Fehlern wie diesen und schwerer zu findende (und daher gefährlichere) Fehler zu vermeiden, die zu einer falschen Ausgabe führen, die nicht offensichtlich falsch ist. Die erste Strategie besteht darin, nur wenige Zeilen gleichzeitig zu schreiben und neu hinzugefügte Zeilen mit zu testendrucken()Aussagen, die zeigen, ob sie das tun, was sie sollen. Im obigen Beispiel könnten Sie einige Zeilen schreiben und etwas drucken, um sicherzustellen, dass Sie das Datei-Handle erfolgreich öffnen und daraus lesen können (wenn die Datei groß ist, erstellen Sie eine kleinere Version zum Testen). Schreiben Sie dann eine einfache for-Schleife und drucken Sie etwas aus, um sicherzustellen, dass Sie die Zeilen der Datei erfolgreich durchlaufen und in Listen von Strings aufteilen können. Fahren Sie fort, indem Sie einen Teil des Codes in die for-Schleife ausfüllen, erneut drucken und testen, um sicherzustellen, dass der Code das tut, was Sie denken. Und so weiter durch iterative Entwicklung.

Die zweite Strategie, um gefährlichere Fehler zu vermeiden, die nicht sofort offensichtlich sind, besteht darin, Ihre Programme mit kleinen Dateien zu testen und zu entwickeln, für die Sie die Antwort von Hand (oder einem anderen vertrauenswürdigen Verfahren) berechnen können. Wenn Sie aus Tests wissen, dass Ihr Programm oder auch nur Teile Ihres Programms die beabsichtigte Ausgabe erzeugen, ist die Wahrscheinlichkeit, dass versteckte Fehler durch die Ritzen schlüpfen, viel geringer. Manche Leute produzieren mehrere kleine Eingaben, die die Vielfalt der verschiedenen Eingabesituationen darstellen, führen die Tests durch und vergleichen die Ausgaben automatisiert mit den erwarteten Ergebnissen. Dies wird als „Unit Testing“ bezeichnet, eine gängige Praxis in der professionellen Softwareentwicklung.

Denken Sie schließlich daran, dass jeder Programmierer, unabhängig von seiner Erfahrung, von Zeit zu Zeit frustriert ist! Das ist völlig normal und eine gute Strategie in diesem Fall ist ein kurzer Spaziergang oder sogar eine Pause für den Tag, um am nächsten Tag wieder aufzustehen. Einige finden, dass sie morgens effizient programmieren, andere spät in der Nacht. Was auch immer Sie tun, Vermeiden Sie die Versuchung, durch Versuch und Irrtum zu programmieren, den Code gedankenlos zu optimieren, in der Hoffnung, dass er die gewünschte Ausgabe erzeugt. Selbst wenn Sie auf diese Weise Erfolg haben (was selten vorkommt), produzieren Sie wahrscheinlich Code mit heimtückischen Fehlern, der in wenigen Tagen selbst für Sie selbst unlesbar sein kann.

Übungen

  1. Schreiben Sie ein Python-Programm, um die Standardabweichung der Stichprobe zu berechnen E Werte in der Datei pz_blastx_yeast_top1.txt. Zur Erinnerung, die Standardabweichung der Stichprobe ist definiert als die Quadratwurzel der Summe der quadrierten Differenzen vom Mittelwert geteilt durch die Anzahl der Werte minus 1:

    Um dies zu erreichen, müssen Sie die Daten zweimal durchlaufen: einen wie im Beispiel, um den Mittelwert zu berechnen, und einen anderen, um die Summe der quadrierten Differenzen zu berechnen. Dies bedeutet, dass Sie auf die E Werte doppelt. Anstatt die Datendatei zu schließen und erneut zu öffnen, sollten Sie zunächst eine leere Liste erstellen, an die Sie jede anhängen können E Wert (bei Ihrer ersten Übergabe der Daten) für die spätere Verwendung.

    Um die Quadratwurzel einer Gleitkommazahl zu berechnen, müssen Sie dieMathematikModul per AnrufMathematik importierenganz oben in Ihrem Programm. Dann ist diemath.sqrt()Funktion gibt die Quadratwurzel eines Floats zurück; zum Beispiel,math.sqrt(3.0)wird den Schwimmer zurückgeben1.7320508.

  2. Wenneine Listeist eine Liste, dannb_list = umgekehrt (a_list)schafft ein „listreverseiterator” erlaubt, die Elemente mit einer for-Schleife in umgekehrter Reihenfolge zu durchlaufen. Schreiben Sie mit diesen Informationen ein Programm namensreverse_blast.pydas liest den Inhalt von pz_blastx_yeast_top1.txt und schreibt die Zeilen in umgekehrter Reihenfolge in eine Datei namenspz_blastx_yeast_top1_reversed.txt.
  3. EIN quine (nach dem Logiker und Philosophen W. V. Quine) ist ein nichtleeres Programm, das seinen eigenen Quellcode exakt ausgibt. Verwenden Sie dieioModul- und Datei-Handles zum Schreiben einer Quine namensquine.py. (Quine-Programme dürfen technisch gesehen keine Dateien öffnen. Können Sie ein Programm schreiben, das seinen eigenen Quellcode ausgibt, ohne dieioModul?)


Bisher sind wir auf zwei Arten des Schreibens von Werten gestoßen: Ausdrucksanweisungen und die Funktion print(). (Eine dritte Möglichkeit besteht darin, die Methode write() von Dateiobjekten zu verwenden. Die Standardausgabedatei kann als sys.stdout referenziert werden. Weitere Informationen hierzu finden Sie in der Bibliotheksreferenz.)

Oft möchten Sie mehr Kontrolle über die Formatierung Ihrer Ausgabe haben, als einfach nur durch Leerzeichen getrennte Werte zu drucken. Es gibt mehrere Möglichkeiten, die Ausgabe zu formatieren.

Um formatierte Zeichenfolgenliterale zu verwenden, beginnen Sie eine Zeichenfolge mit f oder F vor dem öffnenden Anführungszeichen oder dreifachen Anführungszeichen. Innerhalb dieses Strings können Sie einen Python-Ausdruck zwischen < und >Zeichen schreiben, der sich auf Variablen oder Literalwerte beziehen kann.

Die Methode str.format() von Strings erfordert mehr manuellen Aufwand. Sie verwenden weiterhin < und >, um zu markieren, wo eine Variable ersetzt wird, und können detaillierte Formatierungsanweisungen bereitstellen, müssen jedoch auch die zu formatierenden Informationen angeben.

Schließlich können Sie das gesamte String-Handling selbst durchführen, indem Sie String-Slicing- und -Verkettungsoperationen verwenden, um ein beliebiges Layout zu erstellen, das Sie sich vorstellen können. Der String-Typ verfügt über einige Methoden, die nützliche Operationen zum Auffüllen von Strings auf eine bestimmte Spaltenbreite ausführen.

Wenn Sie keine ausgefallene Ausgabe benötigen, sondern nur eine schnelle Anzeige einiger Variablen zu Debugging-Zwecken wünschen, können Sie jeden Wert mit den Funktionen repr() oder str() in einen String umwandeln.

Die Funktion str() soll Darstellungen von Werten zurückgeben, die ziemlich gut lesbar sind, während repr() Darstellungen erzeugen soll, die vom Interpreter gelesen werden können (oder einen SyntaxError erzwingen, wenn es keine entsprechende Syntax gibt). Für Objekte, die keine bestimmte Darstellung für den menschlichen Konsum haben, gibt str() denselben Wert wie repr() zurück. Viele Werte, wie Zahlen oder Strukturen wie Listen und Wörterbücher, haben bei beiden Funktionen dieselbe Darstellung. Insbesondere Strings haben zwei unterschiedliche Darstellungen.

Das String-Modul enthält eine Template-Klasse, die eine weitere Möglichkeit bietet, Werte in Strings zu ersetzen, indem Platzhalter wie $x verwendet und durch Werte aus einem Wörterbuch ersetzt werden, aber viel weniger Kontrolle über die Formatierung bietet.

7.1.1. Formatierte String-Literale¶

Mit formatierten String-Literalen (auch kurz als f-Strings bezeichnet) können Sie den Wert von Python-Ausdrücken in einen String einfügen, indem Sie dem String ein f oder F voranstellen und Ausdrücke schreiben als .

Dem Ausdruck kann ein optionaler Formatbezeichner folgen. Dies ermöglicht eine bessere Kontrolle darüber, wie der Wert formatiert wird. Im folgenden Beispiel wird Pi auf drei Stellen nach dem Komma gerundet:

Das Übergeben einer ganzen Zahl nach dem ':' bewirkt, dass dieses Feld eine Mindestanzahl von Zeichen breit ist. Dies ist nützlich, um Spalten auszurichten.

Andere Modifikatoren können verwendet werden, um den Wert zu konvertieren, bevor er formatiert wird. '!a' wendet ascii() an, '!s' wendet str() an und '!r' wendet repr() an:

Eine Referenz zu diesen Formatspezifikationen finden Sie im Referenzhandbuch für die Formatspezifikation Mini-Sprache .

7.1.2. Die Methode String format()¶

Die grundlegende Verwendung der Methode str.format() sieht wie folgt aus:

Die darin enthaltenen Klammern und Zeichen (Formatfelder genannt) werden durch die an die Methode str.format() übergebenen Objekte ersetzt. Eine Zahl in Klammern kann verwendet werden, um auf die Position des an die Methode str.format() übergebenen Objekts zu verweisen.

Wenn in der Methode str.format() Schlüsselwortargumente verwendet werden, wird auf ihre Werte mit dem Namen des Arguments verwiesen.

Positions- und Schlüsselwortargumente können beliebig kombiniert werden:

Wenn Sie einen wirklich langen Formatstring haben, den Sie nicht aufteilen möchten, wäre es schön, wenn Sie die zu formatierenden Variablen nach Namen statt nach Position referenzieren könnten. Dies kann durch einfaches Übergeben des Diktats und Verwendung von eckigen Klammern '[]' erfolgen, um auf die Tasten zuzugreifen.

Dies könnte auch durch Übergabe der Tabelle als Schlüsselwortargumente mit der Notation '**' erfolgen.

Dies ist besonders nützlich in Kombination mit der eingebauten Funktion vars() , die ein Wörterbuch mit allen lokalen Variablen zurückgibt.

Als Beispiel erzeugen die folgenden Zeilen einen sauber ausgerichteten Satz von Spalten, die ganze Zahlen und ihre Quadrate und Würfel enthalten:

Eine vollständige Übersicht über die Zeichenfolgenformatierung mit str.format() finden Sie unter Formatzeichenfolgensyntax .

7.1.3. Manuelle Zeichenfolgenformatierung¶

Hier ist die gleiche Tabelle mit Quadraten und Würfeln, manuell formatiert:

(Beachten Sie, dass das eine Leerzeichen zwischen jeder Spalte durch die Funktionsweise von print() hinzugefügt wurde: Es fügt immer Leerzeichen zwischen seinen Argumenten hinzu.)

Die Methode str.rjust() von String-Objekten richtet einen String in einem Feld einer gegebenen Breite rechtsbündig aus, indem er links mit Leerzeichen aufgefüllt wird. Es gibt ähnliche Methoden str.ljust() und str.center() . Diese Methoden schreiben nichts, sie geben nur einen neuen String zurück. Wenn die Eingabezeichenfolge zu lang ist, wird sie nicht abgeschnitten, sondern unverändert zurückgegeben. Dies wird Ihr Spaltenlayout durcheinander bringen, aber das ist normalerweise besser als die Alternative, die über einen Wert lügen würde. (Wenn Sie wirklich abschneiden möchten, können Sie jederzeit eine Slice-Operation hinzufügen, wie in x.ljust(n)[:n] .)

Es gibt eine andere Methode, str.zfill() , die einen numerischen String links mit Nullen auffüllt. Es versteht Plus- und Minuszeichen:

7.1.4. Alte Zeichenfolgenformatierung¶

Der %-Operator (modulo) kann auch zur Zeichenkettenformatierung verwendet werden. Bei gegebenen 'string' %-Werten werden Instanzen von % in string durch null oder mehr Elemente von Werten ersetzt. Diese Operation wird allgemein als Zeichenfolgeninterpolation bezeichnet. Zum Beispiel:

Weitere Informationen finden Sie im Abschnitt Zeichenfolgenformatierung im printf-Stil.


Hintergrund

Das Aufkommen von Hochdurchsatztechnologien für die parallele Analyse großer Gen- und Proteingruppen hat die Bioinformatik mit vielfältigen analytischen Anforderungen herausgefordert, um die große Menge an produzierten Daten zu nutzen und zu interpretieren [1] Viele kommerzielle und Freeware-Softwarepakete sind verfügbar, um die verschiedenen Phasen zu unterstützen der Generierung und Analyse von Genomik- und Proteomikdaten von der Datenerfassung über die Verarbeitung, Integration und endgültige Dateninterpretation [2]. Die Ergebnisse konvergieren normalerweise in einer Liste von Genen oder Proteinen, von denen beobachtet wurde, dass sie ein gemeinsames Merkmal wie unterschiedliche Regulation, Expressionsmuster und zelluläre Lokalisation aufweisen.

Um die wissenschaftliche Neuheit der erzielten Ergebnisse – z.B. eine Liste von Genen, die bei Leberkrebs unterschiedlich exprimiert werden – eine Reihe öffentlich zugänglicher Text-Mining-Tools wie PubMatrix [3] oder MedMiner [4] können verwendet werden, um die wissenschaftliche Literatur systematisch zu durchsuchen.

PubMatrix ist ein webbasiertes Tool zum textbasierten Mining des NCBI-Literatursuchdienstes PubMed [5], das Assoziationen zwischen einem oder mehreren Gennamen und einer Liste relevanter Forschungsgebiets-Schlüsselwörter wie 'Krebs', 'Leber', ' überexprimiert". Das gemeinsame Vorkommen eines Gennamens mit bestimmten Schlüsselwörtern weist auf eine mögliche Verbindung hin, die weiter erforscht werden kann.

Bis heute sind keine gleichwertigen Softwaretools öffentlich verfügbar, um Forscher bei der Bewertung der Neuheit von Erkenntnissen unter dem Gesichtspunkt des geistigen Eigentums (IP) zu unterstützen, und daher ist im Allgemeinen eine detaillierte Untersuchung vieler Patente zu jedem Gen oder Protein in der Liste erforderlich. Angesichts der großen Anzahl von Patenten, die normalerweise mit Genen und Proteinen in Verbindung gebracht werden, und der Menge an Informationen, die in jedem Patenteintrag enthalten sind, ist dies eine mühsame und zeitaufwändige Tätigkeit, die von erfahrenen Patentexperten durchgeführt werden muss. PatentMatrix zielt darauf ab, einen vorläufigen Patentüberblick zu erleichtern, indem ein PubMatrix-ähnlicher Ansatz auf die proprietäre GENESEQ™-Patentsequenzdatenbank (bereitgestellt von Derwent Thomson Scientific [6] angewendet wird. Der Zugriff auf die Patenteinträge erfolgt über das Sequence Retrieval System (SRS, bereitgestellt von Biowisdom [ 7]) und auf das Vorkommen von benutzerdefinierten Schlüsselwörtern gescreent. Auf diese Weise ist es möglich, Verbindungen zwischen den in Patenten beschriebenen Genen/Proteinen und einem bestimmten Forschungskontext, wie er durch die benutzerdefinierten Schlüsselwörter definiert ist, zu identifizieren. Die Software extrahiert auch aus jeder GENESEQ™-Eintrag die Basisinformationen für eine vorläufige Bewertung des Gen-/Protein-IP-Status Dem Benutzer wird eine „Standard“- und eine „aggregierte“ Ausgabe präsentiert, die eine detaillierte bzw Ergebnisse der Patentanalyse.


2.4: Dateieingabe und -ausgabe - Biologie

Bevor wir mehr über die SMOKE-Verarbeitung beschreiben, müssen wir zunächst die Dateitypen erklären, auf die Sie in dieser Dokumentation stoßen werden. SMOKE verwendet hauptsächlich zwei Arten von Dateiformaten: ASCII-Dateien und I/O-API-Dateien. Darüber hinaus ist das Ausgabedateiformat für das UAM-basierte Luftqualitätsmodell ein Fortran-Binärdateiformat. Kapitel 8, SMOKE-Eingabedateien, Kapitel 9, SMOKE-Zwischendateien, und Kapitel 10, SMOKE-Ausgabedateien beschreiben alle Eingabe-, Zwischen- und Ausgabedateien, einschließlich des Dateiformats für jede einzelne. Eingabedateien sind Dateien, die von mindestens einem SMOKE-Kernprogramm gelesen werden (aufgelistet in Kapitel 6, SMOKE-Kernprogramme), werden aber nicht von einem Kernprogramm geschrieben. Zwischendateien sind Dateien, die von einem Kernprogramm geschrieben und von mindestens einem anderen Kernprogramm gelesen werden. Ausgabedateien sind Dateien, die von einem SMOKE-Kernprogramm ausgegeben, aber von keinem dieser Dateien gelesen werden. Diese Dateien umfassen Berichte, Protokolldateien und die modellbereiten Dateien, die in ein Luftqualitätsmodell eingegeben werden können. (Ausnahme: eine Zwischendatei [von einem Kernprogramm verwendet] ist auch eine Ausgabedatei [von einem AQM verwendet]: die STACK_GROUPS-Datei, beschrieben in Abschnitt 9.3.2, “ STACK_GROUPS ”.) In diesem Abschnitt werden wir beschreiben die ASCII- und I/O-API-Dateien weiter und geben dann Informationen über die beiden Ansätze zum Formatieren der von SMOKE erzeugten modellbereiten Ausgabedateien (den CMAQ/Models-3-Ansatz und den UAM-basierten Ansatz).

Die Eingabedateien von SMOKE sind hauptsächlich ASCII-Dateien, obwohl einige E/A-API-Dateien verwendet werden. Die Zwischendateien in SMOKE sind hauptsächlich E/A-API-Dateien, obwohl es auch mehrere wichtige ACSII-Dateien gibt. Die Ausgabedateien von SMOKE sind hauptsächlich E/A-API-Dateien und Fortran-Binärdateien für modellfertige Emissionsdateien und ASCII-Dateien für Berichte und Protokolle.

2.5.1. ASCII-Dateien

ASCII-Dateien sind einfach die Textdateien, mit denen die meisten Computerbenutzer vertraut sind. Die von SMOKE eingegebenen ASCII-Dateien liegen in zwei Strukturen vor: spaltenspezifisch und listengerichtet .

2.5.1.1. Spaltenspezifische ASCII-Dateien

In spaltenspezifischen Dateien müssen die Felder in den Dateien in bestimmten Spalten der Datei erscheinen. Jedes Zeichen in einer Zeile steht für eine einzelne Spalte. Die folgenden Zeilen stellen eine spaltenspezifische ASCII-Datendatei dar:

Die Buchstaben TEST befinden sich in den Spalten 1 bis 4 der Datei und die Zahlen 1, 2 und 3 befinden sich in den Spalten 6, 8 bzw. 10:

2.5.1.2. Listengerichtete ASCII-Dateien

Bei listengerichteten Dateien ist die genaue Positionierung der Felder in einer Zeile nicht wichtig, aber die Reihenfolge der Felder in dieser Zeile ist entscheidend. Die Felder müssen durch Sonderzeichen, die in SMOKE als Trennzeichen bezeichnet werden, abgegrenzt (getrennt) werden, gültige Trennzeichen sind Leerzeichen , Kommas , oder Semikolons . Wenn ein bestimmtes Feld eines dieser Trennzeichen enthält, muss dieses Feld in der Eingabedatei in einfache oder doppelte Anführungszeichen eingeschlossen werden.


2.4: Dateieingabe und -ausgabe - Biologie

Foder aus irgendeinem unergründlichen Grund hat es Java nie leicht gemacht, vom Benutzer eines Programms eingegebene Daten zu lesen. Sie haben bereits gesehen, dass die Ausgabe dem Benutzer mit der Subroutine System.out.print angezeigt werden kann. Diese Subroutine ist Teil eines vordefinierten Objekts namens System.out . Der Zweck dieses Objekts besteht genau darin, dem Benutzer eine Ausgabe anzuzeigen. Es gibt ein entsprechendes Objekt namens System.in, das zum Lesen von Dateneingaben durch den Benutzer existiert, aber es bietet nur sehr primitive Eingabemöglichkeiten und erfordert einige fortgeschrittene Java-Programmierkenntnisse, um es effektiv zu verwenden.

Java 5.0 macht die Eingabe mit einer neuen Scanner-Klasse endlich etwas einfacher. Es erfordert jedoch einige Kenntnisse in objektorientierter Programmierung, um diese Klasse zu verwenden, daher ist sie für die Verwendung hier am Anfang dieses Kurses nicht geeignet. (Außerdem macht Scanner meiner Meinung nach immer noch nicht alles richtig.)

Es gibt eine Entschuldigung für dieses mangelnde Interesse an der Eingabe, da Java hauptsächlich dazu gedacht ist, Programme für grafische Benutzeroberflächen zu schreiben, und diese Programme haben ihren eigenen Eingabe-/Ausgabestil, der ist in Java implementiert. Für die Eingabe/Ausgabe in altmodischen Nicht-GUI-Programmen ist jedoch eine grundlegende Unterstützung erforderlich. Glücklicherweise ist es möglich, erweitern Java, indem Sie neue Klassen erstellen, die Unterroutinen bereitstellen, die im Standardteil der Sprache nicht verfügbar sind. Sobald eine neue Klasse verfügbar ist, können die darin enthaltenen Unterprogramme genauso verwendet werden wie eingebaute Routinen.

In diesem Sinne habe ich eine Klasse namens TextIO geschrieben, die Subroutinen zum Lesen von Werten definiert, die vom Benutzer eines Nicht-GUI-Programms eingegeben werden. Die Unterroutinen in dieser Klasse ermöglichen es, Eingaben vom Standardeingabeobjekt System.in zu erhalten, ohne die erweiterten Aspekte von Java zu kennen, die für die Verwendung von Scanner oder die direkte Verwendung von System.in erforderlich sind. TextIO enthält auch eine Reihe von Ausgabeunterprogrammen. Die Ausgabe-Subroutinen ähneln denen in System.out , bieten jedoch einige zusätzliche Funktionen. Sie können jeden beliebigen Satz von Ausgabe-Subroutinen verwenden, und Sie können sie sogar im selben Programm mischen.

Um die TextIO-Klasse verwenden zu können, müssen Sie sicherstellen, dass die Klasse für Ihr Programm verfügbar ist. Was dies bedeutet, hängt von der verwendeten Java-Programmierumgebung ab. Im Allgemeinen müssen Sie nur die Quellcodedatei TextIO.java in dasselbe Verzeichnis einfügen, das Ihr Hauptprogramm enthält. Weitere Informationen zur Verwendung von TextIO finden Sie in Abschnitt 2.6.

2.4.1 Ein erstes Beispiel für die Texteingabe

Die Eingaberoutinen in der TextIO-Klasse sind statische Memberfunktionen. (Statische Memberfunktionen wurden im vorherigen Abschnitt eingeführt.) Nehmen wir an, Ihr Programm soll eine vom Benutzer eingegebene Ganzzahl lesen. Die TextIO-Klasse enthält eine statische Memberfunktion namens getlnInt, die Sie zu diesem Zweck verwenden können. Da diese Funktion in der TextIO-Klasse enthalten ist, müssen Sie sie in Ihrem Programm als TextIO.getlnInt bezeichnen. Die Funktion hat keine Parameter, daher hat ein vollständiger Aufruf der Funktion die Form " TextIO.getlnInt() ". Dieser Funktionsaufruf stellt den vom Benutzer eingegebenen int-Wert dar, und Sie müssen etwas mit dem zurückgegebenen Wert tun, z. B. einer Variablen zuweisen. Wenn userInput beispielsweise eine Variable vom Typ int ist (erstellt mit einer Deklarationsanweisung " int userInput "), können Sie die Zuweisungsanweisung verwenden

Wenn der Computer diese Anweisung ausführt, wartet er, bis der Benutzer einen ganzzahligen Wert eingibt. Der eingegebene Wert wird von der Funktion zurückgegeben und in der Variablen userInput gespeichert. Hier ist ein vollständiges Programm, das TextIO.getlnInt verwendet, um eine vom Benutzer eingegebene Zahl zu lesen und dann das Quadrat der vom Benutzer eingegebenen Zahl auszugeben:

Wenn Sie dieses Programm ausführen, zeigt es die Meldung "Bitte geben Sie eine Zahl ein:" an und hält an, bis Sie eine Antwort eingeben, einschließlich eines Wagenrücklaufs nach der Zahl. Hier ist ein Applet, das das Programm simuliert. (Notiz: Wenn das Applet nicht auf Ihre Eingabe reagiert, müssen Sie es möglicherweise anklicken, um es zu aktivieren. In einigen Browsern müssen Sie möglicherweise auch den Mauszeiger im Applet belassen, damit es Ihre Eingabe erkennt.)

2.4.2 Textausgabe

Die TextIO-Klasse enthält die statischen Member-Unterroutinen TextIO.put und TextIO.putln, die auf die gleiche Weise wie System.out.print und System.out.println verwendet werden können. Obwohl dies in diesem Fall keinen besonderen Vorteil bringt, könnten Sie beispielsweise die beiden Zeilen ersetzen

In den nächsten Kapiteln werde ich in allen meinen Beispielen TextIO für die Eingabe verwenden, und ich werde es oft für die Ausgabe verwenden. Beachten Sie, dass TextIO nur in einem Programm verwendet werden kann, wenn es für dieses Programm verfügbar ist. Sie ist nicht wie die Systemklasse in Java integriert.

Schauen wir uns die eingebauten Ausgabe-Subroutinen System.out.print und System.out.println etwas genauer an. Jede dieser Subroutinen kann mit einem Parameter verwendet werden, wobei der Parameter ein Wert eines der primitiven Typen byte , short , int , long , float , double , char oder boolean sein kann. Der Parameter kann auch ein String , ein Wert eines Enum-Typs oder ein beliebiges Objekt sein. Das heißt, Sie können " System.out.print(x) " oder " System.out.println(x) " sagen, wobei x ein beliebiger Ausdruck ist, dessen Wert einen beliebigen Typ hat. Der Ausdruck kann eine Konstante, eine Variable oder sogar etwas Komplizierteres wie 2*Entfernung*Zeit sein. Tatsächlich enthält die System-Klasse nun mehrere verschiedene Unterroutinen, um verschiedene Parametertypen zu handhaben. Es gibt eine System.out.print zum Drucken von Werten vom Typ double , eine für Werte vom Typ int , eine andere für Werte, die Objekte sind, und so weiter. Diese Subroutinen können den gleichen Namen haben, da der Computer erkennen kann, welche Sie in einer bestimmten Subroutinenaufrufanweisung meinen, abhängig vom Typ des Parameters, den Sie angeben. Mehrere Unterprogramme gleichen Namens zu haben, die sich in den Typen ihrer Parameter unterscheiden, wird als Überladen bezeichnet. Viele Programmiersprachen erlauben kein Überladen, aber es ist in Java-Programmen üblich.

Der Unterschied zwischen System.out.print und System.out.println besteht darin, dass die println-Version einen Wagenrücklauf ausgibt, nachdem sie den angegebenen Parameterwert ausgegeben hat. Es gibt eine Version von System.out.println, die keine Parameter hat. Diese Version gibt einfach einen Wagenrücklauf aus und sonst nichts. Eine Unterprogrammaufrufanweisung für diese Version des Programms sieht wie " System.out.println() " mit leeren Klammern aus. Beachten Sie, dass " System.out.println(x) " genau äquivalent zu " System.out.print(x) System.out.println() " ist, der Wagenrücklauf kommt nach der Wert von x. (Es gibt keine Version von System.out.print ohne Parameter. Verstehst du warum?)

Wie oben erwähnt, können die TextIO-Unterroutinen TextIO.put und TextIO.putln als Ersatz für System.out.print und System.out.println verwendet werden. Die TextIO-Funktionen funktionieren genauso wie die Systemfunktionen, außer dass, wie wir weiter unten sehen werden, TextIO auch zum Schreiben auf andere Ziele verwendet werden kann.

2.4.3 TextIO-Eingangsfunktionen

Die TextIO -Klasse ist bei der Ausgabe etwas vielseitiger als System.out . Es ist jedoch ein Input, für den wir ihn wirklich brauchen.

Bei TextIO erfolgt die Eingabe über Funktionen. TextIO.getlnInt() zum Beispiel, das oben beschrieben wurde, veranlasst den Benutzer, einen Wert vom Typ int einzugeben und gibt diesen Eingabewert zurück, damit Sie ihn in Ihrem Programm verwenden können. TextIO enthält mehrere Funktionen zum Lesen verschiedener Arten von Eingabewerten. Hier sind Beispiele für diejenigen, die Sie am wahrscheinlichsten verwenden werden:

Damit diese Anweisungen zulässig sind, müssen die Variablen auf der linken Seite jeder Zuweisungsanweisung bereits deklariert sein und vom gleichen Typ sein wie der, der von der Funktion auf der rechten Seite zurückgegeben wird. Beachten Sie, dass diese Funktionen keine Parameter haben. Die zurückgegebenen Werte stammen von außerhalb des Programms und werden vom Benutzer während der Ausführung des Programms eingegeben. Um diese Daten zu "erfassen", damit Sie sie in Ihrem Programm verwenden können, müssen Sie den Rückgabewert der Funktion einer Variablen zuweisen. Sie können dann auf den Eingabewert des Benutzers verweisen, indem Sie den Namen der Variablen verwenden.

Wenn Sie eine dieser Funktionen aufrufen, wird garantiert, dass sie einen zulässigen Wert des richtigen Typs zurückgibt. Wenn der Benutzer einen unzulässigen Wert als Eingabe eingibt – zum Beispiel wenn Sie nach einem int fragen und der Benutzer ein nicht numerisches Zeichen oder eine Zahl eingibt, die außerhalb des zulässigen Wertebereichs liegt, der in einer Variablen gespeichert werden kann vom Typ int -- dann fordert der Computer den Benutzer auf, den Wert erneut einzugeben, und Ihr Programm sieht nie den ersten ungültigen Wert, den der Benutzer eingegeben hat. Für TextIO.getlnBoolean() darf der Benutzer Folgendes eingeben: true, false, t, f, yes, no, y, n, 1 oder 0. Außerdem kann er entweder Groß- oder Kleinbuchstaben verwenden Briefe. In jedem Fall wird die Eingabe des Benutzers als wahr/falsch-Wert interpretiert. Es ist praktisch, TextIO.getlnBoolean() zu verwenden, um die Antwort des Benutzers auf eine Ja/Nein-Frage zu lesen.

Sie werden feststellen, dass es zwei Eingabefunktionen gibt, die Strings zurückgeben. Die erste, getlnWord() , gibt einen String zurück, der nur aus nicht leeren Zeichen besteht. Wenn es aufgerufen wird, überspringt es alle vom Benutzer eingegebenen Leerzeichen und Zeilenumbrüche. Dann liest es nicht-leere Zeichen, bis es zum nächsten Leerzeichen oder Wagenrücklauf kommt. Es gibt einen String zurück, der aus allen nicht leeren Zeichen besteht, die es gelesen hat. Die zweite Eingabefunktion getln() gibt einfach einen String zurück, der aus allen vom Benutzer eingegebenen Zeichen einschließlich Leerzeichen bis zum nächsten Wagenrücklauf besteht. Es erhält eine ganze Zeile Eingabetext. Der Wagenrücklauf selbst wird nicht als Teil der Eingabezeichenfolge zurückgegeben, sondern vom Computer gelesen und verworfen. Beachten Sie, dass der von dieser Funktion zurückgegebene String möglicherweise der leere String "" ist, der überhaupt keine Zeichen enthält. Sie erhalten diesen Rückgabewert, wenn der Benutzer einfach die Eingabetaste drückt, ohne zuerst etwas anderes einzugeben.

Alle anderen aufgeführten Eingabefunktionen -- getlnInt() , getlnDouble() , getlnBoolean() und getlnChar() -- verhalten sich wie getWord(), indem sie alle Leerzeichen und Zeilenumbrüche in der Eingabe überspringen, bevor ein Wert gelesen wird.

Wenn der Benutzer außerdem zusätzliche Zeichen in die Zeile nach dem Eingabewert eingibt, alle zusätzlichen Zeichen werden verworfen, zusammen mit dem Wagenrücklauf am Ende der Zeile. Wenn das Programm eine andere Eingabefunktion ausführt, muss der Benutzer eine weitere Eingabezeile eingeben. Es klingt vielleicht nicht nach einer guten Idee, die Eingaben des Benutzers zu verwerfen, aber es stellt sich in den meisten Programmen als die sicherste Methode heraus.Manchmal möchten Sie jedoch mehr als einen Wert aus derselben Eingabezeile lesen. TextIO bietet dazu folgende alternative Eingabefunktionen:

Die Namen dieser Funktionen beginnen mit "get" statt mit "getln". "Getln" ist die Abkürzung für "get line" und soll Sie daran erinnern, dass die Funktionen, deren Namen mit "getln" beginnen, eine ganze Datenzeile erhalten. Eine Funktion ohne "ln" liest einen Eingabewert auf die gleiche Weise, speichert dann aber den Rest der Eingabezeile in einem Teil des internen Speichers, der als Eingabepuffer bezeichnet wird. Wenn der Computer das nächste Mal einen Eingabewert lesen möchte, sucht er im Eingabepuffer, bevor er den Benutzer zur Eingabe auffordert. Dadurch kann der Computer mehrere Werte aus einer Zeile der Benutzereingabe lesen. Genau genommen liest der Computer tatsächlich nur aus dem Eingabepuffer. Wenn das Programm zum ersten Mal versucht, Eingaben vom Benutzer zu lesen, wartet der Computer, während der Benutzer eine ganze Eingabezeile eingibt. TextIO speichert diese Zeile im Eingabepuffer, bis die Daten in der Zeile gelesen oder verworfen wurden (durch eine der "getln"-Funktionen). Der Benutzer kann nur tippen, wenn der Puffer leer ist.

Offensichtlich ist die Semantik der Eingabe viel komplizierter als die Semantik der Ausgabe! Glücklicherweise ist es für die meisten Anwendungen in der Praxis ziemlich einfach. Sie müssen nur den Details folgen, wenn Sie etwas Ausgefallenes machen möchten. Insbesondere ich stark empfehlen Ihnen, die "getln"-Versionen der Eingaberoutinen anstelle der "get"-Versionen zu verwenden, es sei denn, Sie möchten wirklich mehrere Elemente aus derselben Eingabezeile lesen, gerade weil die Semantik der "getln"-Versionen viel einfacher ist .

Beachten Sie übrigens, dass die TextIO-Eingabefunktionen zwar Leerzeichen und Zeilenumbrüche überspringen, während sie nach Eingaben suchen, aber nicht Überspringen Sie andere Zeichen. Wenn Sie beispielsweise versuchen, zwei int s zu lesen und der Benutzer "2,3" eingibt, liest der Computer die erste Zahl richtig, aber wenn er versucht, die zweite Zahl zu lesen, wird das Komma angezeigt. Es wird dies als Fehler betrachten und den Benutzer zwingen, die Nummer erneut einzugeben. Wenn Sie mehrere Zahlen aus einer Zeile eingeben möchten, sollten Sie sicherstellen, dass der Benutzer sie mit Leerzeichen und nicht mit Kommas trennt. Wenn Sie alternativ ein Komma zwischen den Zahlen benötigen, verwenden Sie getChar(), um das Komma zu lesen, bevor Sie die zweite Zahl lesen.

Es gibt eine weitere Zeicheneingabefunktion, TextIO.getAnyChar() , die keine Leerzeichen oder Zeilenumbrüche überspringt. Es liest einfach das nächste vom Benutzer eingegebene Zeichen und gibt es zurück, auch wenn es ein Leerzeichen oder ein Wagenrücklauf ist. Wenn der Benutzer einen Wagenrücklauf eingegeben hat, ist das von getAnyChar() zurückgegebene Zeichen das spezielle Zeilenvorschubzeichen ' '. Es gibt auch eine Funktion, TextIO.peek() , mit der Sie das nächste Zeichen in der Eingabe vorausschauen können, ohne es tatsächlich zu lesen. Nachdem Sie sich das nächste Zeichen angesehen haben, ist es immer noch vorhanden, wenn Sie das nächste Element von der Eingabe lesen. Auf diese Weise können Sie nach vorne schauen und sehen, was in der Eingabe auftaucht, sodass Sie je nach Inhalt unterschiedliche Aktionen ausführen können.

Die TextIO-Klasse stellt eine Reihe weiterer Funktionen bereit. Um mehr darüber zu erfahren, können Sie sich die Kommentare in der Quellcodedatei TextIO.java ansehen.

(Sie fragen sich vielleicht, warum es nur zwei Ausgaberoutinen gibt, print und println , die Datenwerte jeden Typs ausgeben können, während es für jeden Datentyp eine separate Eingaberoutine gibt. Wie oben erwähnt, gibt es in Wirklichkeit viele print und println Routinen, eine für jeden Datentyp. Der Computer kann sie anhand des von Ihnen angegebenen Parametertyps unterscheiden. Die Eingaberoutinen haben jedoch keine Parameter, sodass die verschiedenen Eingaberoutinen nur durch unterschiedliche Namen unterschieden werden können. )

Mit TextIO für Ein- und Ausgabe können wir nun das Programm aus Abschnitt 2.2 zur Berechnung des Wertes einer Investition verbessern. Wir können den Benutzer den Anfangswert der Investition und den Zinssatz eingeben lassen. Das Ergebnis ist ein viel nützlicheres Programm – zum einen ist es sinnvoll, es mehr als einmal auszuführen!

Probieren Sie hier ein gleichwertiges Applet aus. (Wenn das Applet nicht auf Ihre Eingabe reagiert, müssen Sie es möglicherweise anklicken, um es zu aktivieren.)

Übrigens verwenden die Applets auf dieser Seite TextIO selbst nicht. Die TextIO-Klasse dient nur zur Verwendung in Programmen, nicht in Applets. Für Applets habe ich eine separate Klasse geschrieben, die ähnliche Eingabe-/Ausgabemöglichkeiten in einem Programm mit grafischer Benutzeroberfläche bietet. Denken Sie daran, dass die Applets nur Simulationen der Programme.

2.4.4 Formatierte Ausgabe

Wenn Sie das obige Interest2-Beispiel ausgeführt haben, ist Ihnen vielleicht aufgefallen, dass die Antwort nicht immer in dem Format geschrieben ist, das normalerweise für Dollarbeträge verwendet wird. Im Allgemeinen werden Dollarbeträge mit zwei Stellen nach dem Komma geschrieben. Aber die Ausgabe des Programms kann eine Zahl wie 1050.0 oder 43.575 sein. Es wäre besser, wenn diese Zahlen als 1050,00 und 43,58 gedruckt würden.

Java 5.0 hat eine formatierte Ausgabefunktion eingeführt, die es viel einfacher macht als früher, das Format von Ausgabezahlen zu steuern. Es stehen viele Formatierungsoptionen zur Verfügung. Ich werde hier nur einige der einfachsten und am häufigsten verwendeten Möglichkeiten behandeln.

Sie können die Funktion System.out.printf verwenden, um eine formatierte Ausgabe zu erzeugen. (Der Name "printf", der für "print formatted" steht, wird von den Programmiersprachen C und C++ übernommen, die immer eine ähnliche Formatierungsfähigkeit haben). System.out.printf benötigt zwei oder mehr Parameter. Der erste Parameter ist ein String, der das Format der Ausgabe angibt. Dieser Parameter wird als Formatstring bezeichnet. Die restlichen Parameter geben die auszugebenden Werte an. Hier ist eine Anweisung, die eine Zahl im richtigen Format für einen Dollarbetrag ausgibt, wobei Betrag eine Variable vom Typ double ist:

TextIO kann auch formatierte Ausgaben durchführen. Die Funktion TextIO.putf hat die gleiche Funktionalität wie System.out.printf . Mit TextIO wäre das obige Beispiel: TextIO.printf("%1.2",amount) und Sie könnten TextIO.putln("%1.2f",principal) anstelle von TextIO.putln(principal) im Interest2-Programm sagen, um zu erhalten die Ausgabe im richtigen Format.

Das Ausgabeformat eines Werts wird durch einen Formatbezeichner angegeben. Der Formatstring (in den einfachen Fällen, die ich hier beschreibe) enthält einen Formatbezeichner für jeden der auszugebenden Werte. Einige typische Formatbezeichner sind %d , %12d , %10s , %1.2f , %15.8e und %1.8g . Jeder Formatbezeichner beginnt mit einem Prozentzeichen ( % ) und endet mit einem Buchstaben, möglicherweise mit einigen zusätzlichen Formatierungsinformationen dazwischen. Der Buchstabe gibt die Art der Ausgabe an, die produziert werden soll. In %d und %12d gibt das "d" beispielsweise an, dass eine ganze Zahl geschrieben werden soll. Die "12" in %12d gibt die Mindestanzahl an Leerzeichen an, die für die Ausgabe verwendet werden sollen. Wenn die ausgegebene Ganzzahl weniger als 12 Leerzeichen benötigt, werden zusätzliche Leerzeichen vor der Ganzzahl hinzugefügt, um die Summe auf 12 zu erhöhen. Wir sagen, dass die Ausgabe "rechtsbündig in einem Feld der Länge 12" erfolgt. Der Wert wird nicht in 12 Leerzeichen gezwungen, wenn der Wert mehr als 12 Stellen hat, werden alle Stellen ohne zusätzliche Leerzeichen gedruckt. Der Bezeichner %d bedeutet dasselbe wie %1d, dh eine ganze Zahl, die mit so vielen Leerzeichen wie nötig gedruckt wird. (Das „d“ steht übrigens für „dezimale“ (Basis-10) Zahlen. Mit einem „x“ können Sie einen ganzzahligen Wert in hexadezimaler Form ausgeben.)

Der Buchstabe "s" am Ende eines Formatbezeichners kann mit jedem beliebigen Werttyp verwendet werden. Dies bedeutet, dass der Wert in seinem Standardformat ausgegeben werden sollte, genau wie bei einer unformatierten Ausgabe. Um die (Mindest-)Anzahl der Zeichen anzugeben, kann eine Zahl wie beispielsweise die "10" in %10s hinzugefügt werden. Das "s" steht für "string", was bedeutet, dass der Wert wie üblich in einen String-Wert umgewandelt wird.

Noch komplizierter sind die Formatbezeichner für Werte vom Typ double. Ein "f" wie in %1.2f wird verwendet, um eine Zahl in "Floating-Point"-Form, also mit Nachkommastellen, auszugeben. In %1.2f gibt die "2" die Anzahl der Stellen nach dem Dezimalpunkt an. Die "1" gibt die (Mindest-)Anzahl der auszugebenden Zeichen an, was im Endeffekt bedeutet, dass nur so viele Zeichen wie nötig verwendet werden sollten. Ebenso würde %12.3f ein Gleitkommaformat mit 3 Stellen nach dem Komma angeben, rechtsbündig in einem Feld der Länge 12.

Sehr große und sehr kleine Zahlen sollten im Exponentialformat geschrieben werden, z. B. 6.00221415e23, was "6.00221415 mal 10 hoch 23" darstellt. Ein Formatbezeichner wie %15.8e gibt eine Ausgabe in Exponentialform an, wobei die "8" angibt, wie viele Stellen nach dem Komma verwendet werden sollen. Wenn Sie "g" anstelle von "e" verwenden, erfolgt die Ausgabe bei kleinen Werten in Gleitkommaform und bei großen Werten in Exponentialform. In %1.8g gibt die 8 die Gesamtzahl der Ziffern in der Antwort an, einschließlich der Ziffern vor dem Komma und der Ziffern nach dem Komma.

Zusätzlich zu Formatbezeichnern kann die Formatzeichenfolge in einer printf-Anweisung andere Zeichen enthalten. Diese zusätzlichen Zeichen werden nur in die Ausgabe kopiert. Dies kann eine bequeme Möglichkeit sein, Werte in die Mitte einer Ausgabezeichenfolge einzufügen. Wenn x und y beispielsweise Variablen vom Typ int sind, könnten Sie sagen:

Wenn diese Anweisung ausgeführt wird, wird der Wert von x für den ersten %d in der Zeichenfolge, der Wert von y für den zweiten %d und der Wert des Ausdrucks x*y für den dritten ersetzt, sodass die Ausgabe etwas wäre wie "Das Produkt von 17 und 42 ist 714" (Anführungszeichen nicht in der Ausgabe enthalten!).

2.4.5 Einführung in die Datei-I/O

System.out sendet seine Ausgabe an das als "Standardausgabe" bekannte Ausgabeziel. Die Standardausgabe ist jedoch nur ein mögliches Ausgabeziel. Beispielsweise können Daten in eine Datei geschrieben werden, die auf der Festplatte des Benutzers gespeichert ist. Dies hat natürlich den Vorteil, dass die Daten auch nach Programmende in der Datei gespeichert werden und der Benutzer die Datei ausdrucken, per E-Mail versenden, mit einem anderen Programm bearbeiten und so weiter bearbeiten kann.

TextIO kann Daten in Dateien schreiben und Daten aus Dateien lesen. Wenn Sie die Ausgabe mit der Methode put , putln oder putf in TextIO schreiben, wird die Ausgabe an das aktuelle Ausgabeziel gesendet. Standardmäßig ist das aktuelle Ausgabeziel die Standardausgabe. TextIO verfügt jedoch über einige Unterprogramme, mit denen das aktuelle Ausgabeziel geändert werden kann. Um beispielsweise in eine Datei mit dem Namen "result.txt" zu schreiben, verwenden Sie die Anweisung:

Nachdem diese Anweisung ausgeführt wurde, wird jede Ausgabe von TextIO-Ausgabeanweisungen an die Datei mit dem Namen "result.txt" statt an die Standardausgabe gesendet. Die Datei sollte in demselben Verzeichnis erstellt werden, das das Programm enthält. Beachten Sie, dass, wenn bereits eine Datei mit demselben Namen existiert, ihr vorheriger Inhalt gelöscht wird! In vielen Fällen möchten Sie den Benutzer die Datei auswählen lassen, die für die Ausgabe verwendet wird. Die Aussage

öffnet einen typischen Dateiauswahldialog einer grafischen Benutzeroberfläche, in dem der Benutzer die Ausgabedatei angeben kann. Wenn Sie zum Senden der Ausgabe an die Standardausgabe zurückkehren möchten, können Sie sagen:

Sie können auch die Eingangsquelle für die verschiedenen "Get"-Funktionen von TextIO angeben. Die Standardeingabequelle ist die Standardeingabe. Sie können stattdessen die Anweisung TextIO.readFile("data.txt") verwenden, um aus einer Datei namens "data.txt" zu lesen, oder Sie können den Benutzer die Eingabedatei auswählen lassen, indem Sie TextIO.readUserSelectedFile() sagen, und Sie können gehen zurück zum Lesen von Standardeingaben mit TextIO.readStandardInput() .

Wenn Ihr Programm von der Standardeingabe liest, hat der Benutzer die Möglichkeit, Fehler in der Eingabe zu korrigieren. Dies ist nicht möglich, wenn das Programm aus einer Datei liest. Wenn beim Versuch, aus einer Datei zu lesen, unzulässige Daten gefunden werden, tritt ein Fehler auf, der das Programm zum Absturz bringt. (Später werden wir sehen, dass es möglich ist, solche Fehler zu "fangen" und zu beheben.) Fehler können auch, wenn auch seltener, beim Schreiben in Dateien auftreten.

Ein vollständiges Verständnis der Dateieingabe/-ausgabe in Java erfordert Kenntnisse in der objektorientierten Programmierung. Wir werden später in Kapitel 11 auf das Thema zurückkommen. Die Datei-I/O-Fähigkeiten in TextIO sind im Vergleich dazu eher primitiv. Dennoch reichen sie für viele Anwendungen aus und ermöglichen es Ihnen, früher oder später erste Erfahrungen mit Dateien zu sammeln.


4.3.1.5. Ausgabe¶

Dieser Abschnitt der primären FAST-Eingabedatei befasst sich mit dem, was von einer FAST-Simulation ausgegeben werden kann, mit Ausnahme der Linearisierungs- und Visualisierungsausgabe, die in den folgenden Abschnitten enthalten sind.

Zusammenfassungsdaten in „<RootName>.sum“ drucken [T/F]

Bei Einstellung auf „True“ generiert FAST eine Datei mit dem Namen „<RootName>.sum“. Diese Zusammenfassungsdatei enthält die Versionsnummer aller verwendeten Module, die Zeitschritte für jedes Modul und Informationen über die Kanäle, die in die Time-Marching-Ausgabedatei(en) geschrieben werden. Wenn SumPrint „False“ ist, wird keine Zusammenfassungsdatei generiert.

Zeit zwischen Bildschirmstatusmeldungen [s]

Während einer FAST-Simulation gibt das Programm eine Meldung wie diese aus: SttsTime legt fest, wie oft diese Meldung aktualisiert wird. Wenn SttsTime beispielsweise 2 Sekunden beträgt, wird diese Nachricht alle 2 Sekunden der simulierten Zeit aktualisiert.

Zeitspanne zwischen dem Erstellen von Checkpoint-Dateien für einen möglichen Neustart [s]

Diese Eingabe bestimmt, wie oft Prüfpunktdateien geschrieben werden sollen. Checkpoint-Dateien werden für die Neustartfähigkeit verwendet. Wir empfehlen, dass bei kurzen Simulationen ChkptTime größer als die Simulationszeit TMax ist. Weitere Informationen zu Prüfpunktdateien und der Neustartfähigkeit in FAST finden Sie in den Abschnitten „Prüfpunktdateien (Neustartfähigkeit)“ und „Neustart: Starten von FAST aus einer Prüfpunktdatei“ in diesem Dokument. ChkptTime wird in der FAST-Simulink-Schnittstelle ignoriert und muss bei Verwendung der FAST-OrcaFlex-Schnittstelle (CompMooring = 4) größer als TMax sein.

Zeitschritt für Tabellenausgabe [s]

Dies ist der Zeitschritt der Daten in den tabellarischen (Time-Marching) Ausgabedateien. DT_Out muss ein ganzzahliges Vielfaches von DT sein. Alternativ kann DT_Out als String „default“ eingegeben werden, wodurch DT_Out = DT gesetzt wird.

Zeit bis zum Beginn der Tabellenausgabe [s]

Dies ist der Zeitschritt, der erreicht werden muss, bevor FAST mit dem Schreiben von Daten in die tabellarischen (Zeitverlaufs-)Ausgabedateien beginnt. Beachten Sie, dass die Ausgabedateien möglicherweise nicht tatsächlich bei TStart Sekunden beginnen, wenn TStart kein ganzzahliges Vielfaches von DT_Out ist.

Format für Tabellenausgabe [1, 2 oder 3]

Tab-Trennzeichen in tabellarischer Textausgabedatei verwenden? [T/F]

Wenn OutFileFmt = 1 oder 3 ist, werden Tabs zwischen den Spalten in der tabellarischen Textausgabedatei (Zeitverlauf) gesetzt, wenn TabDelim auf „True“ gesetzt wird. Andernfalls trennen Leerzeichen die Spalten in der tabellarischen Textausgabedatei. Wenn OutFileFmt = 2, hat TabDelim keine Wirkung.

Format, das für die tabellarische Textausgabe verwendet wird, mit Ausnahme des Zeitkanals [-]

Wenn OutFileFmt = 1 oder 3 ist, verwendet FAST OutFmt, um die in der Texttabellenausgabedatei gedruckten Kanäle zu formatieren. OutFmt sollte ein Feld mit einer Länge von 10 Zeichen ergeben (Kanal-Header sind 10 Zeichen lang, und die NWTC-Nachbearbeitungssoftware nimmt manchmal 10 Zeichen an). Der Zeitkanal wird im Format „F10.4“ gedruckt. Wir geben OutFmt normalerweise als „ES10.3E2“ an. Wenn OutFileFmt = 2, hat OutFmt keine Wirkung.

(*) Dies gibt an, welcher Typ von tabellarischen Ausgabedateien (im Zeitverlauf) erzeugt wird. Wenn OutFileFmt 1 ist, wird nur eine Textdatei geschrieben. Wenn OutFileFmt 2 ist, wird nur eine Binärdatei geschrieben. Wenn OutFileFmt 3 ist, werden sowohl Text- als auch Binärdateien geschrieben. Textdateien schreiben bei jedem Ausgabezeitschritt eine Zeile in die Datei. Dies kann die Simulation verlangsamen, kann aber für das Debugging nützlich sein, insbesondere wenn eine Simulation nicht vollständig ausgeführt wird oder wenn Sie einige Ergebnisse anzeigen möchten, bevor die gesamte Simulation abgeschlossen ist. Binärdateien werden am Ende der Simulation vollständig geschrieben. Wenn für eine lange Simulation viele Ausgabekanäle angefordert werden, kann dies einen mäßigen Speicherplatz beanspruchen. Sie laufen jedoch tendenziell schneller und die resultierenden Dateien benötigen viel weniger Speicherplatz. Die Binärdateien enthalten genauere Ausgabedaten als Textdateien, die durch den gewählten Ausgabeformatbezeichner eingeschränkt sind – siehe OutFmt unten. Wir empfehlen Ihnen, Textdateien für das Debugging und Binärdateien für die Produktionsarbeit zu verwenden. Ein MATLAB-Skript zum Lesen von FAST-Binärausgabedateien ist im OpenFAST Matlab Toolbox-Repository enthalten. Python-Code zum Lesen von FAST-Ausgabedateien wird mit OpenFAST im fast_io-Modul des Regressionstest-Frameworks verteilt. Auch die NREL-Postprozessoren Crunch und MCrunch können diese Binärdateien lesen.


2.2. Modellierungsstile¶

In Verilog kann das Modell auf vier Arten entworfen werden, wie in diesem Abschnitt gezeigt. Der Zwei-Bit-Komparator ist mit unterschiedlichen Stilen entworfen, die den Ausgang „1“ erzeugen, wenn die Zahlen gleich sind, andernfalls wird der Ausgang auf „0“ gesetzt.

2.2.1. Kontinuierliche Zuweisungsanweisungen¶

Bei diesem Modellierungsstil wird die Beziehung zwischen Eingang und Ausgang über Signalzuordnungen definiert. Zu diesem Zweck wird das Schlüsselwort „assign“ verwendet. Mit anderen Worten, wir definieren die Struktur des Designs nicht explizit, sondern definieren nur die Beziehungen zwischen den Signalen und die Struktur wird implizit während des Syntheseprozesses erstellt.

Erläuterung Auflistung 2.1:

Listing 2.1 ist das Beispiel für das Design von 'Continuous Assignment Statements', bei dem die Beziehung zwischen Inputs und Outputs in Zeile 8 angegeben ist für Kommentare verwendet (Zeile 1). Das von Listing 2.1 generierte ‚and-Gate (d. h. RTL-Ansicht)‘ ist in Abb. 2.1 dargestellt.

Notiz

Um die RTL-Ansicht des Designs anzuzeigen, gehen Sie zu Tools–>Netlist Viewers–>RTL viewer

Beachten Sie, dass in den Zeilen 4 und 5 das Schlüsselwort „wire“ verwendet wird, das dem „Datentyp“ entspricht. Für kontinuierliche Zuweisungsanweisungen wird das Schlüsselwort ‚wire‘ verwendet, während das Schlüsselwort ‚reg‘ für prozedurale Zuweisungsanweisungen verwendet wird. Außerdem können Eingabeports nicht als „reg“ definiert werden. Beachten Sie, dass diese Schlüsselwörter nicht austauschbar sind und die Unterschiede zwischen diesen „Datentypen“ in Abschnitt 2.2.4 erörtert werden. Außerdem können mehr Betreiber, z.B. „and“, „not“ und „nand“ usw. werden in Kapitel 3 behandelt.

Listing 2.1 kann als Listing 2.2 geschrieben werden, wobei die Moduldefinition nur die Namen der Ports enthält (Zeile 3) und die Porttypen außerhalb des Moduls definiert werden (Zeile 5-6).

2.2.2. Komparatoren mit kontinuierlichen Zuweisungsanweisungen¶

In diesem Abschnitt werden zwei weitere Beispiele für kontinuierliche Zuweisungsanweisungen gezeigt, d.h.„1 Bit“- und „2 Bit“-Komparatoren, die verwendet werden, um die Unterschiede zwischen verschiedenen Modellierungsstilen im Tutorial zu demonstrieren. Abb. 2.2 und Abb. 2.3 zeigen die Wahrheitstabellen von „1 Bit“- und „2 Bit“-Komparatoren. Wie der Name schon sagt, vergleicht der Komparator die beiden Werte und setzt den Ausgang „eq“ auf 1, wenn beide Eingangswerte gleich sind, andernfalls wird „eq“ auf Null gesetzt. Die entsprechenden booleschen Ausdrücke sind unten gezeigt,

Die beiden obigen Ausdrücke sind mit verilog in Listing 2.3 und Listing 2.4 implementiert, die weiter unten erklärt werden.

Erläuterung Auflistung 2.3:

Listing 2.3 implementiert den 1-Bit-Komparator basierend auf (2.1). In Zeile 8 sind zwei Zwischensignale definiert. Diese beiden Signale (s0 und s1) sind definiert, um die Werte von x’y’ bzw. xy zu speichern. In den Zeilen 10 und 11 werden diesen Signalen Werte zugewiesen. In Verilog werden die Operationen „not“ und „or“ mit „

’ und ‘|’ Zeichen wie in Zeile 10 bzw. 12 gezeigt. Schließlich führt (2.1) eine „oder“-Operation an diesen beiden Signalen durch, was in Zeile 12 erfolgt. Wenn wir diesen Code mit der „Quartus-Software“ kompilieren, implementiert er den Code in das Hardware-Design, wie in Abb. 2.4 gezeigt.

Der Erstellungsprozess zur Erstellung des Entwurfs ist in Anlage 17 dargestellt. Außerdem können wir die Input-Output-Beziehungen dieses Designs mit Modelsim überprüfen, was auch in Anhang 17 kurz diskutiert wird.

Beachten Sie, dass die Anweisungen in „Kontinuierliche Zuweisungsanweisungen“ und „Strukturmodellierung“ (beschrieben in Abschnitt 2.2.3 ) die gleichzeitigen Anweisungen sind, d. h. diese Anweisungen werden parallel ausgeführt. Mit anderen Worten, die Reihenfolge der Anweisungen beeinflusst das Verhalten der Schaltung nicht, z. vertauschen wir die Zeilen 10, 11 und 12 in Listing 2.3 , erhalten wir wieder die Abb. 2.4 als Implementierung.

Auf der anderen Seite werden Anweisungen in „Prozedurale Zuweisungsanweisungen“ (beschrieben in Abschnitt 2.2.4 ) sequentiell ausgeführt und jede Änderung in der Reihenfolge der Anweisungen ändert das Verhalten der Schaltung.

Erläuterung :numref: Abb. 2.4

Abb. 2.4 wird von der Quartus-Software gemäß dem in Listing 2.3 gezeigten Verilog-Code generiert. Hier ist s0 das ‚und‘-Gatter mit invertierten Eingängen x und y, die nach Zeile 10 in Listing 2.3 erzeugt werden. In ähnlicher Weise wird s1 ‚and‘-Gatter gemäß Zeile 11 erzeugt. Schließlich wird die Ausgabe dieser beiden Gatter an das ‚oder‘-Gatter (als ‚eq‘ bezeichnet) angelegt, das in Zeile 12 von Listing 2.3 definiert ist.

Erläuterung Auflistung 2.4

Diese Auflistung implementiert die Gleichung (2.2). Hier verwenden wir eine Zwei-Bit-Eingabe, daher wird 'wire[1:0]' in Zeile 4 verwendet. '1:0' setzt die 1 als MSB (höchstwertiges Bit) und 0 als LSB (niedrigstwertiges Bit), dh die a[1] und b[1] sind das MSB, während a[0] und b[0] das LSB sind. Da wir vier Signale speichern müssen (Zeile 10-13), ist ‚s‘ in Zeile 8 als 4-Bit-Vektor definiert. Der Rest ist wie in Listing 2.3. Die Implementierung dieses Listings ist in Abb. 2.5 dargestellt.

2.2.3. Strukturmodellierung¶

Im vorherigen Abschnitt haben wir den 2-Bit-Komparator basierend auf Gleichung (2.2) entworfen. Außerdem können wir den 2-Bit-Komparator auch mit 1-Bit-Komparator entwerfen, mit den folgenden Schritten:

  • Vergleichen Sie zuerst jedes Bit von 2-Bit-Zahlen unter Verwendung des 1-Bit-Komparators, d. h. vergleichen Sie a[0] mit b[0] und a[1] mit b[1] unter Verwendung des 1-Bit-Komparators (wie in Abb. 2.3 gezeigt).
  • Wenn beide Werte gleich sind, dann setzen Sie den Ausgang ‚eq‘ auf 1, andernfalls setzen Sie ihn auf Null.

Diese Methode ist als „strukturelle“ Modellierung bekannt, bei der wir die vordefinierten Designs verwenden, um die neuen Designs zu erstellen (anstatt den „booleschen“ Ausdruck zu implementieren). Diese Methode ist sehr nützlich, da die meisten großen Systeme aus verschiedenen kleinen Designeinheiten bestehen. Außerdem ist es einfach, die verschiedenen kleinen Einheiten anstelle eines großen Systems zu erstellen, zu simulieren und zu überprüfen. Listing 2.5 ist das Beispiel für strukturelle Designs, bei denen ein 1-Bit-Komparator verwendet wird, um einen 2-Bit-Komparator zu erstellen.

Erläuterung Auflistung 2.5

In dieser Auflistung definieren die Zeilen 4-5 die beiden Eingangsports mit einer Größe von 2 Bit und einen 1-Bit-Ausgangsport. Dann werden zwei Signale definiert (Zeile 8), um die Ausgaben von zwei 1-Bit-Komparatoren zu speichern, wie unten diskutiert.

‚eq_bit0‘ und ‚eq_bit1‘ in den Zeilen 10 und 11 sind die Namen der beiden 1-Bit-Komparatoren, die in diesem Design verwendet werden. Wir können diese Namen im resultierenden Design sehen, das in Listing 2.5 gezeigt wird.

Als nächstes ist ‚comparator1Bit‘ in den Zeilen 10 und 11 der Name des 1-Bit-Komparators (definiert in Listing 2.3 ). Mit dieser Deklaration, d. h. komparator1bit, nennen wir das Design des 1-Bit-Komparators als aktuelles Design.

Dann werden Mapping-Anweisungen, z.B. .x(a[0]) in den Zeilen 10 und 11, weisen die Werte dem Eingangs- und Ausgangsport des 1-Bit-Komparators zu. Zum Beispiel werden in Zeile 10 den Eingangsports des 1-Bit-Komparators, dh x und y, die Werte von a[0] bzw. b[0] von diesem Entwurf zugewiesen, und der Ausgang y des 1-Bit-Komparators wird im Signal s0. Wenn in Zeile 13 die Signale s0 und s1 1 sind, wird 'eq' mit 'and'-Gatter auf 1 gesetzt, andernfalls wird es auf 0 gesetzt .

Erläuterung Abb. 2.6

In dieser Abbildung sind a[1..0] und b[1..0] die Eingangsbits, während „eq“ das Ausgangsbit ist. Dicke Linien nach a[1..0] und b[1..0] zeigen, dass mehr als 1 Bit vorhanden sind, z.B. in diesem Fall haben diese Zeilen zwei Bits. Diese dicken Linien werden in dünne Linien geändert, bevor sie zu den Komparatoren gehen, was anzeigt, dass nur 1 Bit als Eingabe an den Komparator gesendet wird.

In ‚comparator1Bit: eq_bit0‘ ist ‚comparator1Bit‘ der Name des Moduls, das für den 1-Bit-Komparator ( Listing 2.3 ) definiert ist, während ‚eq_bit0‘ der Name dieses Moduls ist, das in Zeile 10 von Listing 2.5 definiert ist. Schließlich werden die Ausgänge von zwei 1-Bit-Komparatoren gemäß Zeile 13 in Listing 2.5 an das ‚und‘-Gatter gesendet.

Daher können wir aus dieser Figur sehen, dass der 2-Bit-Komparator unter Verwendung von zwei 1-Bit-Komparatoren entworfen werden kann.

2.2.4. Prozedurale Zuweisungsanweisungen¶

In prozeduralen Zuweisungsanweisungen wird das Schlüsselwort ‚always‘ verwendet und alle Anweisungen innerhalb der Always-Anweisung werden nacheinander ausgeführt. Innerhalb des Prozessblocks können verschiedene Bedingungs- und Schleifenanweisungen verwendet werden, wie in Listing 2.6 gezeigt. Außerdem sind Always-Blöcke gleichzeitige Blöcke, d. h. wenn das Design mehrere Always-Blöcke enthält (siehe Listing 2.7 ), werden alle Always-Blöcke parallel ausgeführt.

Erläuterung Auflistung 2.6:

Der „always“-Block wird in Zeile 8 deklariert, die in Zeile 9 bzw. 14 beginnt und endet. Daher werden alle Anweisungen zwischen Zeile 9 bis 14 sequentiell ausgeführt und Quartus Software generiert das Design basierend auf den Sequenzen der Anweisungen. Jegliche Änderungen in den Sequenzen führen zu einem anderen Design.

Beachten Sie, dass der Ausgabeport ‚eq‘ als . deklariert ist reg in Zeile 5. Wenn wir dem Signal innerhalb des ‚always‘-Blocks einen Wert zuweisen, muss dieses Signal als ‚reg‘ deklariert werden, z. Der Wert von ‚eq‘ wird in Zeile 11 und 13 zugewiesen, die sich im ‚always‘-Block befinden, daher wird ‚eq‘ als reg deklariert.

Das Schlüsselwort ‚always‘ nimmt in Zeile 8 zwei Argumente an (bekannt als ‚Sensitivitätsliste‘), was angibt, dass der Prozessblock genau dann ausgeführt wird, wenn sich in ‚a‘ und ‚b‘ Änderungen ergeben. ‘@’ wird nach ‘always’ verwendet, um die Sensitivitätsliste zu definieren. In Zeile 10-13 wird die 'if'-Anweisung deklariert, die den Wert von 'eq' auf 1 setzt, wenn beide Bits gleich sind (Zeile 10-11), ansonsten wird 'eq' auf 0 gesetzt (Zeile 12-13 ). Abb. 2.7 zeigt das von der Quartus Software generierte Design für dieses Listing. ‘==’ in Zeile 10 ist einer der Bedingungsoperatoren, während && der logische Operator ist, die in Kapitel 3 ausführlich behandelt werden.


Abschnitt 33. Befehlscodes EFTNT, EFTAD und EFTOF für den elektronischen Geldtransfer

Manuelle Übertragung

Zweck

(1) Dies überträgt den überarbeiteten IRM 2.4.33, IDRS-Terminaleingabe, Befehlscodes EFTNT, EFTAD und EFTOF für den elektronischen Geldtransfer.

Wesentliche Änderungen

(1) Der Befehlscode EFTNT erfordert nun die zweimalige Eingabe der Bankleitzahl und der Bankkontonummer auf dem Eingabebildschirm. Wenn die beiden Felder nicht gleich sind, wird ein Fehler zurückgegeben.

Auswirkung auf andere Dokumente

Publikum

Datum des Inkrafttretens

Terence V. Milholland
Chief Technology Officer

Allgemeine Informationen zu EFT-Befehlscodes

Dieser Abschnitt enthält Anweisungen für den Zugriff und die Verwendung der Befehlscodes (CC) EFTNT, EFTAD und EFTOF. Diese Befehlscodes werden vom Einzugspersonal in den Campussen verwendet, um elektronische Überweisungen (EFT) für Lastschrift-Ratenzahlungsvereinbarungen (DDIA) einzurichten, zu überprüfen, zu aktualisieren oder zu überspringen.

Befehlscode EFTNT

Der Befehlscode EFTNT wird zum Eingeben neuer DDIA EFT-Bankinformationen verwendet. ODER KORRIGIEREN bestehender Bankinformationen.

Befehlscode EFTNT mit einem leeren Definierer

Auf den Befehlscode EFTNT sollte nur mit dem Befehlscode IAGRE, IAORG oder IAREV zugegriffen werden. Dies ist die Voraussetzung für den Zugriff auf den Command Code EFTNT zur Eingabe neuer oder Änderung bestehender Bankinformationen. Anlage 2.4.33–3. Befehlscode EFTNT mit Definierer F ist die Voraussetzung für die Eingabe des Befehlscodes EFTNT mit leerem Definierer.

Terminalausgabeantworten für EFTNT:

"ANFORDERUNG ABGESCHLOSSEN", angezeigt auf Bildschirmzeile 24, zeigt an, dass keine Fehlerbedingungen beim Akzeptieren der Bankinformationseingabe von CC IAORG, IAPND oder IAREV aufgetreten sind.

"BITTE KORRIGIEREN SIE UNGÜLTIGE DATEN", das auf der Bildschirmzeile 24 angezeigt wird, zeigt an, dass ein Eingabefeld nicht richtig formatiert ist oder einen falschen Wert enthält. Das ungültige Feld wird mit einem Sternchen (*) gekennzeichnet.

"KONTO ÜBERTRAGENES AKTUALISIERUNG NICHT ERLAUBT", das auf Bildschirmzeile 24 angezeigt wird, zeigt an, dass das Konto an ein anderes Service-Center übertragen wurde.

"ZAHLUNG VORHANDEN AUF ZAHLUNGSKONTROLLE - CHECK CC EFTAD", die auf Bildschirmzeile 24 angezeigt wird, zeigt an, dass heute eine Zahlungsanforderung zu extrahieren ist. Eine Vorabnotiz kann nicht bearbeitet werden, wenn eine Zahlungsaufforderung vorliegt.

Befehlscode EFTNT mit Definierer F

Der Befehlscode EFTNT mit F-Definierer wird nur verwendet, um vorhandene Bankinformationen zu aktualisieren oder zu korrigieren. Um diesen Befehlscode zu verwenden, muss er nach dem Zugriff auf IAGRE, IAORG oder IAREV eingegeben werden (Siehe IRM 2.4.30) . Dies sind die Voraussetzung für die Verwendung von EFTNT mit dem Definierer F. Anlage 2.4.33–1

Siehe Anlage 2.4.33-2 für das Bankinformationsformat

Terminalausgabeantworten für EFTNT mit Definierer F:

"ANFORDERUNG VERWEIGERT/UNSACHGEMÄSSE INITIALISIERUNG", angezeigt auf Bildschirmzeile 24, zeigt an, dass CC EFTNT mit dem Definierer F nicht von CC IAGRE, IAORG oder IAREV vorangegangen ist.

"KONTO NICHT EFT-INSTALLATIONSSTATUS", das auf Bildschirmzeile 24 angezeigt wird, zeigt an, dass die vorangehende CC IAGRE-, IAORG- oder IAREV-Eingabe den EFT-Indikator nicht enthielt.

"ANFORDERUNG ABGESCHLOSSEN", angezeigt auf Bildschirmzeile 24, zeigt an, dass keine Fehlerbedingungen beim Akzeptieren der Bankinformationseingabe von CC IAORG, IAPND oder IAREV aufgetreten sind.

"BITTE KORRIGIEREN SIE UNGÜLTIGE DATEN", das auf der Bildschirmzeile 24 angezeigt wird, zeigt an, dass ein Eingabefeld nicht richtig formatiert ist oder einen falschen Wert enthält. Das ungültige Feld wird mit einem Sternchen (*) gekennzeichnet.

Befehlscode EFTAD

Dieser Befehlscode mit leerem Definierer wird verwendet, um Bankinformationen und Zahlungsdaten für eine angegebene TIN zu erhalten. Anlage 2.4.33–4.

Terminalausgangsantworten für CC EFTAD

Siehe Anlage 2.4.33–5 für Bankinformationen und Zahlungsdatenformat.

"INVALID TIN", angezeigt auf Bildschirmzeile 24, zeigt an, dass die eingegebene TIN nicht richtig formatiert ist oder einen ungültigen Wert enthält.

"KONTO NICHT IN DATEI", angezeigt auf Bildschirmzeile 24, zeigt an, dass die eingegebene TIN in der EFT-Datei nicht vorhanden ist.

"ZAHLUNG VON ACH BANK ABGELEHNT" , die in Bildschirmzeile 9 angezeigt wird, zeigt an, dass die EFT-Anforderung von der Bank bearbeitet und wegen Nichtzahlung zurückgegeben wurde.

Befehlscode EFTAD mit Definierer D

Dieser Befehlscode mit dem Definierer D und einem gültigen zweistelligen Service Center Code (07,08,09,17,18,19,28,29,49 und 89) werden verwendet, um Einzahlungsinformationen und Zahlungsdaten für ein bestimmtes Einzahlungsdatum zu erhalten. Ausstellung 2.4.33–6.

Antworten der Terminalausgabe:

Siehe Anlage 2.4.33–7 für Einzahlungsinformationen und das Zahlungsdatenformat.

"INVALID DATE", das auf Bildschirmzeile 24 angezeigt wird, zeigt an, dass das Eingabedatum nicht richtig formatiert ist oder einen ungültigen Wert enthält.

"KEINE DATEN VERFÜGBAR FÜR ALN XX", die auf Bildschirmzeile 24 angezeigt wird, zeigt an, dass das angeforderte Datum für das bestimmte ALN kein tatsächliches Einzahlungsdatum (Wochenende oder Feiertag) ist oder das angeforderte Datum noch nicht verarbeitet wurde.

SIE MÜSSEN EINEN GÜLTIGEN CAMPUSCODE EINGEBEN, der auf Bildschirmzeile 24 angezeigt wird, zeigt an, dass ein gültiger zweistelliger Campuscode eingegeben werden muss, um die Einzahlungsdaten für diesen Campus anzuzeigen

Befehlscode EFTAD mit Definierer Z

Dieser Befehlscode mit dem Definierer Z mit einem gültigen zweistelligen Service Center Code (07,08,09,17,18,19,28,29,49 und 89) wird verwendet, um Einzahlungstermine zu erhalten, die 10 Tage vor und 5 Tage liegen nach dem aktuellen Datum in der elektronischen Geldtransferdatei. Ausstellung 2.4.33–8.

Antworten der Terminalausgabe:

Siehe Anlage 2.4.33–9 für das Format der Hinterlegungsdaten.

"KEINE DATEN VERFÜGBAR FÜR ALN XX", die auf Bildschirmzeile 24 angezeigt wird, zeigt an, dass keine Einzahlungsdaten auf der EFTF vorhanden sind.

"NOT SENT" auf dem Bildschirm zeigt an, dass das Hinterlegungsdatum auf der EFTF vorhanden ist, aber noch nicht zur Übermittlung an die Clearinghausbank extrahiert wurde.

"SENT TO BANK" , angezeigt auf dem Bildschirm, zeigt an, dass das Hinterlegungsdatum auf der EFTF vorhanden ist und mit diesem Hinterlegungsdatum verbundene Vornoten und Zahlungsaufforderungen extrahiert wurden, um sie an die Clearinghausbank zu senden.

SIE MÜSSEN EINEN GÜLTIGEN CAMPUS-CODE EINGEBEN, der auf Bildschirmzeile 24 angezeigt wird, zeigt an, dass ein gültiger zweistelliger Campus-Code eingegeben werden muss, um den angeforderten Bereich der Einzahlungsdaten für diesen Campus anzuzeigen

UNGÜLTIGE DEFINER

Die Terminalausgabeantwort "INVALID DEFINER", die auf Bildschirmzeile 24 angezeigt wird, zeigt an, dass der Definierer nicht leer war, "D" oder "Z".

Befehlscode EFTOF

Dieser Befehlscode wird verwendet, um eine elektronische Überweisungsanforderung an die Bank für eine bestimmte TIN und ein bestimmtes Ratendatum zu stoppen. Diese Anforderung wird nur verwendet, wenn die EFT-Datei aktualisiert wurde, um das eingegebene Ratenzahlungsdatum aufzunehmen. Außerdem muss die Anfrage der Übermittlung der EFT-Zahlungsanfrage an die Clearing House Bank vorausgehen. Ausstellung 2.4.33–10.

Antworten der Terminalausgaben: Anlage 2.4.33–11.

"REQUEST COMPLETED" in Bildschirmzeile 13 zeigt an, dass die EFT-Zahlungsstoppanforderung verarbeitet wurde.

"INVALID TIN" in Bildschirmzeile 13 zeigt an, dass die Eingabe-TIN nicht richtig formatiert ist oder einen ungültigen Wert enthält.

"UNGÜLTIGES DATUM", das auf Bildschirmzeile 13 angezeigt wird, zeigt an, dass das Anforderungsdatum nicht richtig formatiert ist oder einen ungültigen Wert enthält.

"EFT-DATEN NICHT VERFÜGBAR", angezeigt auf Bildschirmzeile 13 zeigt an, dass die eingegebene TIN in der EFT-Datei nicht vorhanden ist.

"FALSCHES ZAHLUNGSDATUM", das in Bildschirmzeile 13 angezeigt wird, zeigt an, dass das angeforderte Datum kein korrektes Zahlungsdatum für die eingegebene TIN ist oder dass die EFT-Datei nicht aktualisiert wurde, um das angeforderte Datum aufzunehmen.

"ZAHLUNGSANFORDERUNG AN BANK GESENDET", die auf Bildschirmzeile 13 angezeigt wird, zeigt an, dass die EFT-Anforderung zur Verarbeitung an die Bank generiert wurde.

"ZAHLUNGSANFRAGE VON BANK ABGELEHNT" , die in Bildschirmzeile 13 angezeigt wird, zeigt an, dass die EFT-Anforderung von der Bank bearbeitet und wegen Nichtzahlung zurückgesendet wurde.

"ZAHLUNGSANFRAGE VORHER UNTERDRÜCKT" , angezeigt auf Bildschirmzeile 13 zeigt an, dass CC EFTOF zuvor für die eingegebene TIN und das Zahlungsdatum eingegeben wurde.

"ACCOUNT TRANSFERRED UPDATE NICHT ERLAUBT" , angezeigt in Bildschirmzeile 13 zeigt an, dass das Konto an ein anderes Service Center übertragen wurde.

"INVALID DEFINER", das in Bildschirmzeile 13 angezeigt wird, zeigt an, dass der Definierer nicht leer war.

"ZAHLUNGSANFORDERUNG ABGELEHNT VORANMERKUNGSINFO", die auf Bildschirmzeile 13 angezeigt wird, zeigt an, dass die Vornotiz von der Bank zurückgewiesen wurde.

SIE MÜSSEN EINEN GÜLTIGEN CAMPUS-CODE EINGEBEN, der auf Bildschirmzeile 24 angezeigt wird, zeigt an, dass ein gültiger zweistelliger Campus-Code, in dem sich das Konto befindet, eingegeben werden muss. (07,08,09,17,18,19,28,29,49 und 89)


Verfügbarmachen von Filtern als HTTP-Dienst

Filter können verwendet werden, um Inhalte zu verarbeiten, die vom Client stammen, zusätzlich zur Verarbeitung von Inhalten, die vom Server stammen, indem das Modul mod_reflector verwendet wird.

mod_reflector akzeptiert POST-Anfragen von Clients und spiegelt den Inhalt der innerhalb der POST-Anforderung empfangenen Inhaltsanforderung in der Antwort wieder, wobei er auf dem Weg zurück zum Client den Ausgabefilterstapel passiert.

Diese Technik kann als Alternative zu einem Webdienst verwendet werden, der innerhalb eines Anwendungsserverstapels ausgeführt wird, bei dem ein Ausgabefilter die erforderliche Transformation des Anforderungstexts bereitstellt. Beispielsweise kann das Modul mod_deflate verwendet werden, um einen allgemeinen Komprimierungsdienst bereitzustellen, oder ein Bildtransformationsfilter könnte in einen Bildtransformationsdienst umgewandelt werden.


Grundlegende Eingabe/Ausgabe

Die Beispielprogramme der vorherigen Abschnitte boten wenig oder gar keine Interaktion mit dem Benutzer. Sie druckten einfach einfache Werte auf dem Bildschirm aus, aber die Standardbibliothek bietet viele zusätzliche Möglichkeiten, mit dem Benutzer über ihre Eingabe-/Ausgabefunktionen zu interagieren. In diesem Abschnitt werden einige der nützlichsten kurz vorgestellt.

C++ verwendet eine praktische Abstraktion namens strömt um Eingabe- und Ausgabeoperationen in sequentiellen Medien wie dem Bildschirm, der Tastatur oder einer Datei durchzuführen. A ist eine Entität, in die ein Programm Zeichen entweder einfügen oder daraus extrahieren kann. Es ist nicht erforderlich, Details zu den dem Stream zugeordneten Medien oder seinen internen Spezifikationen zu kennen. Alles, was wir wissen müssen, ist, dass Streams eine Quelle/ein Ziel von Zeichen sind und dass diese Zeichen sequentiell (d. h. nacheinander) bereitgestellt/angenommen werden.

Die Standardbibliothek definiert eine Handvoll Stream-Objekte, die verwendet werden können, um auf die Standardquellen und -ziele von Zeichen zuzugreifen, die von der Umgebung, in der das Programm ausgeführt wird, angesehen werden:

StromBezeichnung
cin Standardeingabestream
cout Standardausgabestrom
cerr Standardfehler (Ausgabe) Stream
verstopfen Standard-Logging-(Ausgabe-)Stream

Wir werden nur cout und cin (die Standard-Ausgabe- und Eingabe-Streams) genauer sehen. cerr und clog sind ebenfalls Ausgabe-Streams, also funktionieren sie im Wesentlichen wie cout , mit dem einzigen Unterschied, dass sie Streams für bestimmte Zwecke identifizieren: Fehlermeldungen und Protokollierung, die in vielen Fällen in den meisten Umgebungskonfigurationen tatsächlich genau dasselbe tun: Sie drucken auf dem Bildschirm, obwohl sie auch einzeln umgeleitet werden können.

Standardausgabe (cout)

In den meisten Programmumgebungen ist die Standardausgabe standardmäßig der Bildschirm, und das für den Zugriff definierte C++-Stream-Objekt ist cout .

Für formatierte Ausgabeoperationen wird cout zusammen mit dem . verwendet Einfügeoperator, die als << geschrieben wird (d. h. zwei "kleiner als"-Zeichen).

Der <<-Operator fügt die ihm folgenden Daten in den davor liegenden Stream ein. In den obigen Beispielen wurden die Literalzeichenfolge Ausgabesatz , die Zahl 120 und der Wert der Variablen x in den Standardausgabestrom cout eingefügt. Beachten Sie, dass der Satz in der ersten Anweisung in doppelte Anführungszeichen ( " ) eingeschlossen ist, da es sich um ein String-Literal handelt, während in der letzten x dies nicht der Fall ist. Die doppelten Anführungszeichen machen den Unterschied, wenn der Text zwischen ihnen eingeschlossen ist text wird buchstäblich ausgegeben, wenn dies nicht der Fall ist, wird der Text als Bezeichner einer Variablen interpretiert und stattdessen ihr Wert ausgegeben.Zum Beispiel haben diese beiden Sätze sehr unterschiedliche Ergebnisse:

Mehrere Einfügevorgänge (<<) können in einer einzigen Anweisung verkettet werden:

Diese letzte Anweisung würde den Text ausgeben. Dies ist eine einzelne C++-Anweisung. Das Verketten von Einfügungen ist besonders nützlich, um Literale und Variablen in einer einzigen Anweisung zu mischen:

Angenommen, die Altersvariable enthält den Wert 24 und die Postleitzahl-Variable 90064, dann wäre die Ausgabe der vorherigen Anweisung:

Ich bin 24 Jahre alt und meine Postleitzahl ist 90064
cout fügt nicht automatisch Zeilenumbrüche am Ende hinzu, es sei denn, Sie werden dazu aufgefordert. Nehmen Sie zum Beispiel die folgenden zwei Anweisungen, die in cout eingefügt werden:
cout << "Dies ist ein Satz."
cout << "Das ist ein anderer Satz."

Die Ausgabe erfolgt in einer einzigen Zeile ohne Zeilenumbrüche dazwischen. Etwas wie:

Dies ist ein Satz. Dies ist ein anderer Satz.
Um einen Zeilenumbruch einzufügen, muss ein Zeilenumbruch genau an der Stelle eingefügt werden, an der der Zeilenumbruch erfolgen soll. In C++ kann ein Zeilenumbruchzeichen als angegeben werden (d. h. ein umgekehrter Schrägstrich gefolgt von einem kleinen n ). Zum Beispiel:

Dies erzeugt die folgende Ausgabe:

Erster Satz.
Zweiter Satz.
Dritter Satz.

Alternativ kann der Endl-Manipulator auch zum Brechen von Linien verwendet werden. Zum Beispiel:

Erster Satz.
Zweiter Satz.

Der Endl-Manipulator erzeugt ein Newline-Zeichen, genau wie das Einfügen von ' ', hat aber auch ein zusätzliches Verhalten: Der Puffer des Streams (falls vorhanden) wird geleert, was bedeutet, dass die Ausgabe physisch auf das Gerät geschrieben werden muss , wenn es nicht schon war. Dies betrifft hauptsächlich voll gepuffert Bäche, und cout ist (im Allgemeinen) nicht a voll gepuffert Strom. Dennoch ist es im Allgemeinen eine gute Idee, endl nur dann zu verwenden, wenn das Leeren des Streams eine Funktion wäre, und ' ', wenn dies nicht der Fall wäre. Bedenken Sie, dass ein Spülvorgang mit einem gewissen Aufwand verbunden ist und bei manchen Geräten zu einer Verzögerung führen kann.

Standardeingang (cin)

In den meisten Programmumgebungen ist die Standardeingabe standardmäßig die Tastatur, und das für den Zugriff definierte C++-Stream-Objekt ist cin .

Für formatierte Eingabeoperationen wird cin zusammen mit dem Extraktionsoperator verwendet, der als >> geschrieben wird (d. h. zwei "größer als"-Zeichen). Auf diesen Operator folgt dann die Variable, in der die extrahierten Daten gespeichert sind. Zum Beispiel:

Die erste Anweisung deklariert eine Variable vom Typ int namens age , und die zweite extrahiert aus cin einen darin zu speichernden Wert. Diese Operation lässt das Programm im Allgemeinen auf Eingaben von cin warten, das bedeutet, dass das Programm darauf wartet, dass der Benutzer eine Sequenz mit der Tastatur eingibt. Beachten Sie in diesem Fall, dass die über die Tastatur eingegebenen Zeichen nur dann an das Programm übertragen werden, wenn die Taste ENTER (oder RETURN ) gedrückt wird. Sobald die Anweisung mit der Extraktionsoperation auf cin erreicht ist, wartet das Programm so lange wie nötig, bis eine Eingabe eingegeben wird.

Die Extraktionsoperation auf cin verwendet den Typ der Variablen nach dem >>-Operator, um zu bestimmen, wie die aus der Eingabe gelesenen Zeichen interpretiert werden, wenn es sich um eine ganze Zahl handelt, das erwartete Format eine Ziffernfolge ist, wenn eine Zeichenfolge eine Zeichenfolge usw .

Wie Sie sehen können, scheint das Extrahieren aus cin die Aufgabe, Eingaben von der Standardeingabe zu erhalten, ziemlich einfach und unkompliziert zu machen. Aber diese Methode hat auch einen großen Nachteil. Was passiert im obigen Beispiel, wenn der Benutzer etwas anderes eingibt, das nicht als ganze Zahl interpretiert werden kann? Nun, in diesem Fall schlägt der Extraktionsvorgang fehl. Und dies lässt das Programm standardmäßig fortfahren, ohne einen Wert für die Variable i festzulegen, was zu unbestimmten Ergebnissen führt, wenn der Wert von i später verwendet wird.

Dies ist ein sehr schlechtes Programmverhalten. Von den meisten Programmen wird erwartet, dass sie sich unabhängig vom Benutzertyp wie erwartet verhalten und ungültige Werte entsprechend behandeln. Nur ganz einfache Programme sollten sich auf Werte verlassen, die ohne weitere Prüfung direkt aus cin extrahiert wurden. Etwas später werden wir sehen wie Stringstreams kann verwendet werden, um eine bessere Kontrolle über die Benutzereingaben zu haben.
Extraktionen auf cin können auch verkettet werden, um mehr als ein Datum in einer einzigen Anweisung anzufordern:

In beiden Fällen wird vom Benutzer erwartet, dass er zwei Werte eingibt, einen für die Variable a und einen anderen für die Variable b. Jede Art von Leerzeichen wird verwendet, um zwei aufeinanderfolgende Eingabeoperationen zu trennen. Dies kann entweder ein Leerzeichen, ein Tabulator oder ein Zeilenumbruchzeichen sein.

Cin und Streicher

Der Extraktionsoperator kann auf cin verwendet werden, um Zeichenfolgen auf die gleiche Weise wie bei grundlegenden Datentypen zu erhalten:

Die cin-Extraktion betrachtet jedoch Leerzeichen (Leerzeichen, Tabulatoren, new-line. ) immer als Abschluss des zu extrahierenden Werts, und daher bedeutet das Extrahieren einer Zeichenfolge, immer ein einzelnes Wort zu extrahieren, nicht eine Phrase oder einen ganzen Satz.

Um eine ganze Zeile von cin abzurufen, gibt es eine Funktion namens getline , die den Stream ( cin ) als erstes Argument und die String-Variable als zweites verwendet. Zum Beispiel:

Beachten Sie, dass wir in beiden Aufrufen von getline denselben Zeichenfolgenbezeichner ( mystr ) verwendet haben. Beim zweiten Aufruf ersetzt das Programm einfach den bisherigen Inhalt durch den neu eingeführten Inhalt.

Das Standardverhalten, das die meisten Benutzer von einem Konsolenprogramm erwarten, besteht darin, dass jedes Mal, wenn das Programm den Benutzer zur Eingabe auffordert, der Benutzer das Feld einführt und dann die EINGABETASTE (oder RETURN ) drückt. Das heißt, Eingaben werden im Allgemeinen in Form von Zeilen in Konsolenprogrammen erwartet, und dies kann erreicht werden, indem getline verwendet wird, um Eingaben vom Benutzer zu erhalten. Daher sollten Sie immer getline verwenden, um Eingaben in Ihre Konsolenprogramme zu erhalten, es sei denn, Sie haben einen triftigen Grund, anstatt aus cin zu extrahieren.

Stringstream

Der Standard-Header <sstream> definiert einen Typ namens stringstream, der es ermöglicht, einen String als Stream zu behandeln und somit Extraktions- oder Einfügeoperationen aus/in Strings auf die gleiche Weise zuzulassen, wie sie bei cin und cout ausgeführt werden. Diese Funktion ist am nützlichsten, um Zeichenfolgen in numerische Werte umzuwandeln und umgekehrt. Um beispielsweise eine ganze Zahl aus einer Zeichenfolge zu extrahieren, können wir schreiben:

Dies deklariert einen String mit initialisiert auf einen Wert von "1204" und eine Variable vom Typ int . Dann verwendet die dritte Zeile diese Variable, um aus einem Stringstream zu extrahieren, der aus dem String konstruiert wurde. Dieses Codestück speichert den numerischen Wert 1204 in der Variablen namens myint .

In diesem Beispiel erhalten wir numerische Werte aus dem Standardeingang indirekt: Anstatt numerische Werte direkt aus cin zu extrahieren, bekommen wir Zeilen daraus in ein String-Objekt ( mystr ) und extrahieren dann die Werte aus diesem String in die Variablen price und Quantity . Sobald es sich um numerische Werte handelt, können mit ihnen arithmetische Operationen durchgeführt werden, beispielsweise durch Multiplikation, um einen Gesamtpreis zu erhalten.