D: C++ Streamoperator
Ich hatte gestern mal wieder mit C++ zu tun und muss sagen: ich liebe dessen Streamoperatoren. Gut bei der Ausgabe mittels cout nervt es mich schon hin und wieder, aber das einlesen von Konsoleneingaben mittels cin und vor allem bei Dateien ist es wirklich bequem und meiner Meinung nach nicht schwer zu verstehen. Vielleicht etwas kryptisch auf den ersten Blick, zugegeben, aber das legt sich bald wenn man sich erstmal daran gewöhnt hat. ![]()
Für die zukünftige Version von Dgame habe ich mir die Streamoperationen von C++ emuliert, indem ich den Shift Operator überladen habe.
Damit habe ich mir eine Input/Output sowie File Stream Emulierung gebastelt:
Input & Output:
import std.stdio; import std.conv : to; immutable(string) endl = "\n\r"; /** * Beispiel: * * --- * Output cout = new Output(); * Input cin = new Input(); * * string name; * ubyte age; * * cout << "Hallo Welt!" << endl; * cout << "Wie lautet dein Name?" << endl; * cin >> name; * cout << "Und wie alt bist du?" << endl; * cin >> age; * * writefln("My name is %s. I'm %d years old!", name, age); * * cout << "Das ist also " << name << ". Nice to meet you." << endl; * --- */ /** * Autor: Randy Schütt */ class Output { public: void output(T)(T param) const { write(param); } typeof(this) opBinary(string op, T)(T param) if (op == "<<") { this.output(param); return this; } } class Input { public: void input(T)(ref T param) const { string value = readln(); try { param = to!(T)(value[0 .. $ - 1]); } catch (Exception e) { param = cast(T)(null); } } typeof(this) opBinary(string op, T)(ref T param) if (op == ">>") { this.input(param); return this; } }
Und File Stream:
private import std.stdio; private import std.file; private import std.regex; /** * Beispiel: * * --- * File f = File.open("test.txt"); * * foreach (line; f) { * writeln(" > ", line); * } * * writeln("Erste Zeile: "); * writeln(f.readline()); * writeln("Zweite Zeile: "); * writeln(f.readline()); * * string third_line; * f >>> third_line; * writeln("Dritte Zeile: "); * writeln(third_line); * * string content; * f >> content; * * writeln("Content: "); * writeln(content); * * f << "// Abschlusszeile"; * --- */ interface Iterator { void next(); void previous(); } class File : public Iterator { private: const string _filename; string[] _lines; uint _current_line; bool _close; public: alias readlines this; static typeof(this) open(string filename) { if (!File.exists(filename)) { throw new Exception("File not found: " ~ filename); } return new this(filename); } static bool exists(string filename) { return std.file.exists(filename); } static void put_content(string filename, string content) { std.file.write(filename, content); } static string get_content(string filename) { return cast(string) std.file.read(filename); } this(string filename) { if (!File.exists(filename)) { throw new Exception("File not found: " ~ filename); } this._filename = filename; this._current_line = 0; this.open(); this.refresh(); } void open() { this._close = false; } bool closed() const { return this._close; } void close() { this._close = true; } string read() const { if (this._close) { throw new Exception("File is closed!"); } return File.get_content(this._filename); } void write(string content) { if (this._close) { throw new Exception("File is closed!"); } std.file.append(this._filename, content ~ "\r\n"); this.refresh(); } void refresh() { if (this._close) { throw new Exception("File is closed!"); } this._lines = []; string line; auto f = std.stdio.File(this._filename, "r"); while (!f.eof()) { line = f.readln(); this._lines ~= line; } f.close(); } const(string)[] readlines() const { if (this._close) { throw new Exception("File is closed!"); } return this._lines; } string readline(int line = -1) { if (this._close) { throw new Exception("File is closed!"); } if (line >= 0) { this._current_line = line; } return this._lines[this._current_line++]; } void next() { if (this._close) { throw new Exception("File is closed!"); } this._current_line++; if (this._current_line >= this._lines.length) { this._current_line = this._lines.length; } } void previous() { if (this._close) { throw new Exception("File is closed!"); } if (this._current_line > 0) { this._current_line--; } } uint current_line() const { return this._current_line; } string get_filename() const { return this._filename; } /* bool opBinary(string op, T)(T param, out int line) { switch (op) { case "in": foreach (string line; this) { auto result = std.regex.match(regex(r"" ~ param), line, "g"); if (!result.empty()) { return true; } } break; default: break; } return false; } */ typeof(this) opBinary(string op, T)(T value) if (op == "<<") { if (this._close) { throw new Exception("File is closed!"); } this.write(value); return this; } typeof(this) opBinary(string op, T)(ref T value) if (op == ">>") { if (this._close) { throw new Exception("File is closed!"); } value = this.read(); return this; } typeof(this) opBinary(string op, T)(ref T value) if (op == ">>>") { if (this._close) { throw new Exception("File is closed!"); } value = this.readline(); return this; } }
Vielleicht hat ja jemand Interesse und/oder Spaß daran.