009
15.09.2004, 14:55 Uhr
virtual
Sexiest Bit alive (Operator)
|
Zitat von CaesarCortezz: |
@virtual Nur noch ne kleine (eigentlich große) Frage
C++: |
const char* datei_name = "lc.cpp"; std::ifstream in(datei_name); in.unsetf(std::ios_base::skipws); int count = std::count(std::istream_iterator<char>(in), std::istream_iterator<char>(),'\n'); std::cout<<datei_name<<" hat "<<count<<" Zeilen."<<std::endl;
|
Ich seh überhaupt net durch könntest du mir das erklären. Wäre sehr freundlich, danke. Caesar
|
Nun gut:
C++: |
const char* datei_name = "lc.cpp";
|
Dürfte klar sein, ich möchte nur an einer Stelle den Dateinamen ändern, deshalb mach ich eine entsprechende Variable.
C++: |
std::ifstream in(datei_name);
|
Erzeuge einen EingabeStream, öffnet diesen gleich. Übrigens is kein explizites in.close() nachher erforderlich, weil das automatisch durch den Destructor gemacht wird, wenn die Funktion verlassen wird.
C++: |
in.unsetf(std::ios_base::skipws);
|
Standardmäßig sind input streams so eingestellt, daß sie einfach die Zeichen überspringen, die als Whitespaces gelten. Neben dem Space als solchen gilt auch das newline als Space. Genau an diesem Zeichen sind wir aber interessiert, deshalb lösche ich dieses Flag im Stream, welches die Whitespaces überspringt.
C++: |
int count = std::count(std::istream_iterator<char>(in), std::istream_iterator<char>(),'\n');
|
Ich denke mal, das interessiert dich am meisten. Fangen wir mal mit dem count an: Im besser zu begreifen, was es genau macht, nehmen wir mal diesen Code hier:
C++: |
int zahlen[] = { 1, 2, 2, 5, 9 }; int c = std::count(&zahlen[0], &zahlen[5], 2);
|
Das count soll einen bereich nach einem bestimmten Wert durchsuchen und die Anzahl der Vorkommnisse zurückgeben. Die ersten beiden parameter geben an, was der Bereich ist (Nennen wir es mal für ein paar Momente "Bereichsgrenzen") und der letzte gibt den gesuchten Wert an. Wir suchen also im einem wie auch immer definierten Bereich den Wert 2. Spannend ist die Sache mit den Bereichsgrenzen: Im obigen Beispiel ist die untere Bereichgrenze &zahlen[0], also der Zeiger auf das erste Element im Array zahlen; die obere grenze zeigt auf das erste Element, welches uns nicht mehr interessiert. (Der Zeiger &zahlen[5] zeigt also sozusagen auf das 6te Element in zahlen, allerdings is das ja garnicht da).
Code: |
count(anfang, ende, wert)
|
Durchsucht also alle Werte beginnend an Stelle anfang bis (aber ohne!) ende nach wert.
In C++ wird sehr viel Iteratoren gearbeitet. Vereinfacht sind Iteratoren objekte, die sich sehr ähnlich wie Zeiger benehmen können. Minimal gesehen, muß ein Iterator folgende Operationen bereitstellen:
Code: |
*i : Deferenzieren, dh den Inhalt preisgeben, wo der Iterator hinzeigt ++i und i++: Auf das nächste Element zeigen i==j: Prüfen, ob die Iteratoren gleich sind.
|
Weitere Operationen können auch Unterstützt werden, das hängt von dem konkreten Iterator ab. Ein Iterator is also ein Stinknormaler Zeiger, oder eben eine Klasse, die bestimmte Operatoren überladen hat, mindestens die von oben, manchmal weitere. Ist ein weites feld, belassen wir es erstmal dabei. Um zum count zurückzukommen: die Bereichsgrenzen werden also mit Iteratoren markiert. In dem ursprünglichen Beispiel wurde eben kein zeiger, sondern ein Iterator verwendet. der istream_iterator<char> stellt die og Funktionen etwa so bereit:
Code: |
*i : Das aktuelle Zeichen der Ausgabedatei zurückgeben ++i und i++: Das nächste zeichen aus der Ausgabe datei lesen.
|
std::istream_iterator<char>(in) Ist also ein iterator für das erste noch nicht gelesene ZEichen im Stream std::istream_iterator<char>() Ist also ein iterator für EOF, also dem nicht existenten zeichen nach dem letzten Zeichen im Stream.
Leider ist die ganze Sache recht komplex, deshalb wirst du ggf. nicht alles verstanden haben, aber ich nehme mal an, ein wenig mehr dunkel ins licht gebracht zu haben -- Gruß, virtual Quote of the Month Ich eß' nur was ein Gesicht hat (Creme 21) |