Umfangreiche Lösungen für triviale Probleme - sinnvoll?


  • Administrator

    Hallo zusammen,

    Ich habe den Beitrag von Firefighter gelesen, hier:
    http://www.c-plusplus.net/forum/viewtopic-var-p-is-1635770.html#1635770

    Dabei dachte ich: "Das muss doch einfacher über die STD-Algorithmen gehen!"
    Also Testprojekt geöffnet und angefangen rumzuwerkeln. Heraus kam der folgende Code:

    #include <string>
    #include <vector>
    #include <fstream>
    #include <iostream>
    #include <iterator>
    #include <algorithm>
    
    template
    <
    	typename CharT,
    	typename TraitsT = std::char_traits<CharT>,
    	typename AllocatorT = std::allocator<CharT>
    >
    struct BasicLine
    {
    	typedef std::basic_string<CharT, TraitsT, AllocatorT> Data;
    
    	Data data;
    
    	operator Data&()
    	{
    		return data;
    	}
    
    	operator Data const&() const
    	{
    		return data;
    	}
    };
    
    typedef BasicLine<char> Line;
    typedef BasicLine<wchar_t> WLine;
    
    template
    <
    	typename CharT,
    	typename TraitsT,
    	typename AllocatorT
    >
    std::basic_istream<CharT, TraitsT>&
    operator >>(
    	std::basic_istream<CharT, TraitsT>& input,
    	BasicLine<CharT, TraitsT, AllocatorT>& line
    	)
    {
    	return std::getline(input, line.data);
    }
    
    int main()
    {
    	std::vector<std::string> lines;
    
    	std::ifstream file("C:/fpRedmon.log");
    
    	std::copy(
    		std::istream_iterator<Line>(file),
    		std::istream_iterator<Line>(),
    		std::back_inserter(lines)
    		);
    
    	return 0;
    }
    

    Ich wusste doch, dass es einf.... ehm ... dass es geht 🙂

    Finde das immer wieder interessant, wie man sich mit den Standardalgorithmen wahnsinnig schnell verirren kann. Denn es ist klar, dass diese Lösung deutlich mehr kann, als die von Firefighter, aber grundsätzlich ist es völlig unnötig für das eigentliche Problem.

    Mir ist das nun schon mehrfach aufgefallen, dass ich für kleine Probleme, riesige Lösungen gefunden habe, welche viel mehr lösen könnten, als nur das eine Problem.

    Geht euch das manchmal auch so?
    Und als wie sinnvoll erachtet ihr solche Lösungen? Vor allem im Hinblick auf die Zukunft. Habt ihr schon erlebt, dass solche grössere Lösungen euch später geholfen haben?

    Grüssli



  • Schöne Lösung Dravere, auch wenn ich nicht alles verstanden habe,was ich gestehen muss. 🤡 Aber ich kenne dein Problem auch sehr gut. Man will ein Projekt schreiben und zerbricht sich den Kopf wie man das am besten universell lösen kann. Natürlich schießt dann manchmal mti Kanonen auf Spatzen, aber es hat einen Vorteil, sobal das eigentlich Problem komplexer wird, hat man schon einen Ansatz der eventuell sogar schon das neue komplexe Problem lösen kann.Ich denke es zeigt programmiertechnisches können, wenn man selbst triviale Probleme mit komplexen Ansätzen lösen kann und somit die Lösung auch für andere(gleiche) nur schwerer Problemstellungen nutzen kann. Meine Meinung 🙂



  • Dravere schrieb:

    Mir ist das nun schon mehrfach aufgefallen, dass ich für kleine Probleme, riesige Lösungen gefunden habe, welche viel mehr lösen könnten, als nur das eine Problem.

    Geht euch das manchmal auch so?
    Und als wie sinnvoll erachtet ihr solche Lösungen? Vor allem im Hinblick auf die Zukunft. Habt ihr schon erlebt, dass solche grössere Lösungen euch später geholfen haben?

    ich gebe zu, dass ich auch dazu tendiere.
    Ich finde diese Art Lösungen immer genau dann sinnvoll, wenn ihre einzelnen Komponenten bestimmte 'allgemein gültige' Schnittstellen zur Verfügung stellen. Mit 'allgemein gültig' meine ich die Schnittstellen, die im Standard definiert sind. Und das sind oft Iterator und Stream (also istream und ostream und die Templateform).
    Das stellt sicher, dass man sie mit anderen Komponenten, entweder bestehende aus dem Standard, oder andere selbst erstellte kombinieren kann. Und erst das macht ihre Wiederverwendbarkeit aus.

    Das mag zwar umfangreich im Sinne von 'viele Zeilen Code' aussehen, aber überhaupt nicht kompliziert; es fällt auf, dass weder eine Abfrage (if) noch eine Schleife (for,while,..) in Deinem Code auftauchen. Das macht ihn 'ganz einfach'.

    Firefighter schrieb:

    Schöne Lösung Dravere, auch wenn ich nicht alles verstanden habe,was ich gestehen muss.

    .. vorausgesetzt man versteht C++ vollständig, und damit auch die Template-Syntax und z.B. istream_iterator<> und Co. 😉

    Auch wenn ich es in diesem speziellen Fall es etwas über das Ziel hinausgeschossen empfinde, lässt sich Deine Lösung sofort für die Lösung des nächsten erwähnten Problems einsetzen:

    morbius schrieb:

    Hätte jetzt noch ne Frage. Ich lese ja ein File ein. Gibt es nun eine Methode, um zu prüfen, ob irgendwo ein "[blabla_xyz]" vorkam? Denn wenn ich das finden könnte, muss ich in die nächste Zeile springen. Wie würde ich das machen?

    Steht der Ausdruck allein in der Zeile, so sollte diese Stelle mit

    find( std::istream_iterator<Line>(file), std::istream_iterator<Line>(), string("[blabla_xyz]") );
    

    zu finden sein.

    Im Allgemeinen habe ich die Erfahrung gemacht, dass diese Art des Vorgehens unter anderem den Vorteil hat, dass der entstandene Code weniger Fehler enthält, die man erst zur Laufzeit bemerkt. Es ist gerade bei Templates oft mühsam, es durch den Compiler zu bringen, aber wenn's dann erstmal so weit ist, dann ist der Code auch oft gleich korrekt.

    :xmas2: Werner



  • Naja, sagen wir mal so... Ich würde sicherlich, zumindest im ersten Anlauf, genau so etwas schreiben wie Firefighter. Einfache Lösungen für einfache Probleme 🙂

    Ich mag zwar die STL-Algorithmen mit ihrer eher funktionalen Art zu programmieren sehr gerne, aber ich weiß halt auch, wie schnell man sich damit in irgendwelchen unnötig komplizierten Konstrukten verlaufen kann (was m.M.n. weniger ein Problem mit der Herangehensweise an sich ist, als vielmehr eine Schwäche der Sprache).

    Andererseits sehe ich allerdings auch den Vorteil von Draveres Lösung, zumal man sowas ja wirklich immer wieder gebrauchen kann. Eigentlich wundert es mich sogar sehr, daß weder STL noch Boost oder sonstwer eine einfache Lösung für das zeilenweise Iterieren über eine Datei mitbringen.

    Hat vielleicht mal jemand versucht, sowas mittels Boost.Iterator zu lösen? Ich dachte eigentlich, daß damit eine halbwegs einfache Lösung möglich sein sollte, aber irgendwie scheint mir selbst da kein wirklich passender Adapter dabei zu sein. Vielleicht habe ich auch nur das Entscheidende übersehen?



  • Das hab ich manchmal auch, diesen Zwang, alles "sauber" lösen zu wollen. Also möglichst viel STL und maximale Kapselung etc. 🙂

    Oft sieht es nachher so aus, dass ich für irgendein std::find() oder std::for_each() zusätzliche Konstrukte bastle, um eine Ein-Zeilen-Lösung zu haben. Dabei wäre doch eine Schleife viel einfacher gewesen...



  • Ich wollte hier mal nach einem Link fragen, der einem so tiefen Wissen vermittelt, dass man auch solche Sachen alleine kommen kann.
    Denn allein über die Doku oder die üblichen Tutorials/Bücher hätte ich so was nicht hinbekommen.
    Oder ist das einfach nur Erfahrung bzw. viel lesen der Implementierungen der std-container?

    Danke
    Franz



  • franz schrieb:

    Ich wollte hier mal nach einem Link fragen, der einem so tiefen Wissen vermittelt, dass man auch solche Sachen alleine kommen kann.
    Denn allein über die Doku oder die üblichen Tutorials/Bücher hätte ich so was nicht hinbekommen.
    Oder ist das einfach nur Erfahrung bzw. viel lesen der Implementierungen der std-container?

    Danke
    Franz

    Ich denke mal es ist einfach nur Jahre lange Erfahrung und viel viel viel Selbstsudium 🙂



  • franz schrieb:

    Denn allein über die Doku oder die üblichen Tutorials/Bücher hätte ich so was nicht hinbekommen.

    Kommt ganz drauf an was man unter "übliche Tutorials/Bücher" versteht. Mit der "üblichen" Anfängerlektüre kommt man sicher nicht so ohne weiteres darauf. Wenn man sich aber über die fortgeschrittene Lektüre wie z.B. die Exceptional C++-Reihe von Herb Sutter, den C++ Templates-Guide von Josuttis/Vandervoorde, Modern C++ von Alexandrescu und ein paar Dokus zu einzelnen Boost-Bibliotheken hergemacht hat und sich dabei die darin enthaltenen Ideen und Vorgehensweisen verinnerlicht hat, dann kommt man auch auf solche Verallgemeinerungen.

    Firefighter schrieb:

    Ich denke mal es ist einfach nur Jahre lange Erfahrung und viel viel viel Selbstsudium 🙂

    Jahre vielleicht nicht, aber doch sicher ein paar Monate, angefangen bei kleinen Verallgemeinerungen und schrittweisem Vorantasten. Inklusive den Stellen wo man sich völlig verzettelt und aus einem "unschönen, uneleganten" Vierzeiler einen eleganten Einzeiler macht mit Hilfe einer Template-Verallgemeinerung die 6 STL-Header und 80 Zeilen Code braucht 😉



  • pumuckl schrieb:

    Wenn man sich aber über die fortgeschrittene Lektüre wie z.B. die Exceptional C++-Reihe von Herb Sutter, den C++ Templates-Guide von Josuttis/Vandervoorde, Modern C++ von Alexandrescu und ein paar Dokus zu einzelnen Boost-Bibliotheken hergemacht hat und sich dabei die darin enthaltenen Ideen und Vorgehensweisen verinnerlicht hat, dann kommt man auch auf solche Verallgemeinerungen.

    Danke, dann weiß ich ja was ich mir hol wenn mal wieder Geld da ist...
    Müssen jetzt erstmal die Boost-Dokus usw. herhalten.
    Hab auch grad gesehen dass in meinem
    "Thinking in C++, 2nd ed. Volume 2"
    auch einiges zu templates drinnen steht.

    Ansonsten danke für die Tips!



  • franz schrieb:

    Hab auch grad gesehen dass in meinem
    "Thinking in C++, 2nd ed. Volume 2"
    auch einiges zu templates drinnen steht.

    Das ist im Vergleich zu dem, was Alexandrescu macht ziemlich Anfängermässig. 🙂


Anmelden zum Antworten