Event, hook oder überschreiben von cout?



  • Hi!

    Ich habe hier eine .cpp Datei in der an diversen Stellen ein cout / std::cout vorkommt. Ich möchte nun eine Header Einbinden, welche die Ausgabe an eine eigene Funktion (in der Header) umleitet. Mit

    std::cout.rdbuf(...)
    

    kann zwar den darunterliegenden Buffer ändern und die Ausgabe umleiten, aber ich möchte wissen wann ein '\n' oder std::endl in den Buffer geschrieben wird. Dann habe ich überlegt eine Klasse zu schreiben die vom ostream erbt und den operator<<(const char 😉 zu überladen:

    class MyOStringstream : public std::ostringstream {
    	MyOStringstream& operator<<(const char *_Val) {	// insert NTBS into char stream
    		int i = 0;
    		char nextChar = _Val[i];
    		while (nextChar != '\0') {
    			std::ostringstream::operator<<(_Val[i]);
    			if (nextChar == '\n') {
    				//Do additional stuff
    			}
    			nextChar = _Val[++i];
    		}
    
    		return (*this);
    	}
    }
    

    Bin dann darauf gestoßen, dass ich 3 Operatorn überladen müsste für std::string, const char* und für das std::endl. Und letztendlich scheitere ich daran, dass ich die freie Funktion

    template<class _Traits> inline
    std::basic_ostream<char, _Traits>& operator<<(
    	std::basic_ostream<char, _Traits>& _Ostr,
    	const char *_Val) {...}
    

    nicht überladen kann wegen mehrdeutigkeit (und weil die original funktion für mich ein wenig konfus ist). Dann habe ich nach __event und __hook geschaut, aber ich kann mein Ziel nicht erreichen. Kann mir Jemand weiterhelfen?

    TL;DR: Ich möchte, durch einbinden eines Headers, std::cout überwachen und wissen wann cout ein '\n', "\n" oder std::endl erhält und dann code im header ausführen.



  • Vielleicht erzählst Du besser, was Du erreichen willst. Nicht wie.



  • Auf der Website Codingame.com kann man eigenen Quellcode in einer .cpp Datei hochladen. Die Quelldatei enthält die Lösung für ein von Codingame.com gestelltest Porblem.
    Als Beispiel das Tutorial "Onboarding":

    Your program must destroy the enemy ships by shooting the closest enemy on each turn.

    Rules
    On each start of turn (within the game loop), you obtain information on the two closest enemies:
    enemy1 and dist1: the name and the distance to enemy 1.
    enemy2 and dist2: the name and the distance to enemy 2.
    Before your turn is over (end of the loop), output the value of either enemy1 or enemy2 to shoot the closest enemy.

    Die Lösung dafür:

    #include <iostream>
    using namespace std;
    int main(){
        // game loop
        while (1) {
            string enemy1; // name of enemy 1
            cin >> enemy1; cin.ignore();
            int dist1; // distance to enemy 1
            cin >> dist1; cin.ignore();
            string enemy2; // name of enemy 2
            cin >> enemy2; cin.ignore();
            int dist2; // distance to enemy 2
            cin >> dist2; cin.ignore();
    
            if (dist1 < dist2) {
                cout << enemy1 << endl;
            }  else {
                cout << enemy2 << endl;
            }
        }
    }
    

    Nun möchte ich das cout in meiner IDE analysieren und meinen eigenen Referee* schreiben. Da ich aber sehr viele dieser Puzzles gelöst habe möchte ich einfach nur eine Header am Anfang einbinden und damit das cout beobachten. Ich möchte nicht alle meine .cpp Dateien nach den couts durchforsten und diese dann umschreiben.

    *Referee ist das Programm welches mich mit den Daten enemy1, enemy2, etc. füttert und meine Antwort auswertet.


  • Mod

    Was hat irgendetwas davon mit cout, endl oder \n zu tun? Leite einfach die Ausgabe an den Referee!



  • hast du noch andere cout Aufrufe?

    Wenn ich dich richtig verstehe, brauchst du für die Abgabe sowas:

    [code="cpp"]referee << enemy1[code]

    Klingt für mich eher nach "Suchen und ersetzen".

    Für die Zukunft wäre es wahrscheinlich einfacher einen eigenen Referee Stream zu haben, der alles auf cout umbiegt. Dann kannst du den einfach raus nehmen wenn du deine Lösung hochladen möchtest.



  • SeppJ schrieb:

    [...]Leite einfach die Ausgabe an den Referee!

    Und wie mache ich das am besten, damit ich einfach wechseln kann zwischen "Version in meiner IDE" und "Version zur Abgabe"?

    #define cout myReferre
    

    in die Header von meinem Referee setzen und die Header dann nach bedarf auskommentieren? (Ich kann nur eine, nicht besonders große .cpp Datei hochladen und keine eigenen Header einbinden.) Das beißt sich wenn ich std::cout irgendwo stehen habe.

    oder für jede Ausgabe sowas (so hab ich Schlangenmensch verstanden):

    #ifdef VERSION_IDE
    myReferee << enemy1;
    #else
    cout << enemy1;
    #endif
    

    Womit ich dann in jeder .cpp die ich habe suchen und ersetzen müsste.

    Am bequemsten wäre es, wenn ich eine Header einbinde, welche den Code des Referees enthält und das cout kapert. (Was meinen Eingangspost erklärt)

    Schlangenmensch schrieb:

    hast du noch andere cout Aufrufe?

    Alle cout Aufrufe gehören zur Antwort für den Referee. Die Antwort endet mit einem '\n'.



  • SeppJ schrieb:

    Was hat irgendetwas davon mit cout, endl oder \n zu tun? Leite einfach die Ausgabe an den Referee!

    Yay, wir haben einen winn0r 🙂 :p

    Aber diese Deine simple Arbeitsanweisung haben leute vor 15 jahren schon durchwegs nimmer kapiert.

    @OP: Du schreibst eine solution.cpp und eine referee.cpp . kompilierst beide. Beim Ausführen leitest Du daa STDOUT von solution in das STDIN von referee 😉.

    😉 Wie das Umleiten geht, steht im Handbuch deines <3-OS.


Anmelden zum Antworten