Vectoren sortieren, Zahlen erkennen
-
Pringles schrieb:
Was versteht man denn unter klassischen Mitteln?
Furble Wurble hat mir eigentlich schon gut geholfen.Eben das, was Furble Wurble meinte.
Bloß muss ich jetzt irgendwie das s1e1 in die 2 shorts bekommen. Bloß wie erkenne ich denn jetzt am besten eine Zahl?
Dann hast du nicht verstanden, was Furble Wurble meinte. Du sollst deine Daten direkt einlesen, nicht händisch irgendwelche Strings zerlegen. Die Streams bieten doch schon tolle Lesefunktionen für allerlei Datendarstellungen an. Daraus bastelst du dir ein paar schicke Funktionen, die du zu größeren Funktionen zusammen setzt, die du zu noch größeren Funktionen zusammen setzt, die dann letztendlich eine Lesefunktion für dein Gesamtobjekt ergeben (die du dann üblicherweise "operator>>" nennst, damit du so etwas wie
cin >> meine_serieschreiben kannst*)
Hier böten sich an:
-Funktionstemplate, welches einen Buchstaben liest und mit einer Vorgabe vergleicht. Schlägt der Vergleich fehl, wird ein Fehlerflag gesetzt. Hier am besten noch mit expliziter Nichtbeachtung von Groß- und Kleinschreibung.
-Einlesen von short gibt's ja schon.
-Damit dann Einlesen der Staffelinformation: Lese_und_prüfe<E>; Lese short -> Staffel; Lese_und_prüfe<S>; Lese short -> EpisodeIch kann's gerade leider nicht vormachen, da der Rechner an dem ich sitze nicht für Entwicklung ausgerüstet ist und remote oder bei ideone ist mir das zu fummelig.
*: Die Bezeichnung "serie" für deine Klasse scheint mir sehr unpassend. Es scheint sich doch um eine einzelne Episode zu handeln. Aber "episode" wäre auch falsch, da es nicht die Episode selbst ist, sondern Information über ihren Titel. Also "titelinformation" oder ähnliches. Und eigentlich programmiert man auch auf englisch, wenn du nicht gerade für eine deutsche Behörde arbeitest.
-
Ok danke.
Bin grade aber noch bei Vererbungen das mit Templates kommt erst später im Buch
Naja das ganze hätte ich ja auch noch in einer Funktion gepackt und das mit überladen von den operator hätte ich auch noch hin bekommen. Bloß muss ich ja trotzdem das Format s1e1 erkenne.
Ich hätte das ganze jetzt so gelöst:
1. Suche nach Buchstaben s
2. Überprüfe ob das Zeichen nach es eine Zahl ist mit isdigit
3. Überprüfe ob das Zeichen nach der Zahl ein e ist
4. Überprüfe ob das Zeichen nach dem e eine Zahl ist
Falls Punkt 2-4 nicht erfüllt sind wird Punkt 1 wiederholt das ganze bis die Zeile leer ist.
Bloß geht das bestimmt besser aber wie?Zu dem Namen der Klasse bzw. des Ziels des Programmes. Das Programm soll aus der Datei erkennen bei welcher Serie ich wie weit bin. Also soll das Programm erkennen bei Game of Thrones bin ich in der 3 Staffel in der 6 Episode. Die Serien die nicht mehr weiter Produziert werden sind halt mit /final makiert.
Das mit den Englischen besser ich nach
War halt nur schnell geschrieben.
-
Man kann das zwar auch ziemlich gut direkt mit den klassischen Mitteln lesen, aber das Format scheint mir so dermaßen nach einem regulären Ausdruck zu schreien, dass ich die klassische Lösung mal lieber nicht vormache, sondern auf jemanden warte, der sich mit Regex auskennt.
Ich kenne mich natürlich kein bisschen mit Regex aus, aber einen Versuch habe ich gestartet - er versagt allerdings beim allerletzten Fall, wenn kein Leerzeichen nach dem Namen vorhanden ist... genauso versagt er, wenn ein Leerzeichen zwischen Episodeninformation oder /final und dem Semikolon vorhanden ist. Sicher kann das jemand korrigieren, der sich auskennt.
#include <string> #include <algorithm> #include <regex> #include <ostream> #include <istream> class serie { public: serie( std::string const& name_ = "dummy", unsigned short staffel_ = 0, unsigned short episode_ = 0, bool final_ = false) : name_(name_), staffel_(staffel_), episode_(episode_), final_(final_){} //ist es ok das die Parameter und die Memeber den selben Namen haben? std::string const& name() const { return name_; } unsigned short staffel() const { return staffel_; } unsigned short episode() const { return episode_; } bool final() const { return final_; } private: std::string name_; unsigned short staffel_, episode_; bool final_; friend std::istream& operator>>( std::istream& is, serie& s ) { std::string str; if (!std::getline(is >> std::ws, str, ';')) return is; static const std::regex reg("(.+) +(s([0-9]+)e([0-9]+))? *(/final)?"); std::smatch match; if (std::regex_match(str, match, reg)) { s.name_ = match[1]; if( match[2].matched ) { s.staffel_ = std::stol(match[3]); s.episode_ = std::stol(match[4]); } else s.staffel_ = s.episode_ = 0; s.final_ = match[5].matched; } else is.setstate( std::ios_base::failbit ); return is; } }; #include <sstream> #include <iostream> int main() { std::istringstream stream( R"(game of throne s4e6; walking dead s4e16/final; criminal minds s9e19; breaking bad s5e16/final; prison break s4e24; Homeland ;)" ); serie s; while (stream >> s) std::cout << "Name: " << s.name() << '\n' << "\tStaffel: " << s.staffel() << (s.final()? " (die letzte!)" : "") << '\n' << "\tEpisode: " << s.episode() << '\n'; }Edit: Das Problem ist, dass der Ausdruck
(.+)gerne auf den ganzen String gematcht wird statt nur auf den Namen. Wie kann man diesen eingrenzen?
-
@Arcoth
Welchen Compiler nutzt du? Bei mir bekomme ich ein Laufzeitfehler:This application has requested the Runtime to terminate it in an unusual way. Please contact the application's support team for more information. terminate called after throwing an instance of 'std::regex_error' what(): regex_error
-
Pringles schrieb:
@Arcoth
Welchen Compiler nutzt du? Bei mir bekomme ich ein Laufzeitfehler:This application has requested the Runtime to terminate it in an unusual way. Please contact the application's support team for more information. terminate called after throwing an instance of 'std::regex_error' what(): regex_errorKann sein, dass der Compiler das einfach nicht supported?
Du nutzt den GCC oder? Der unterstützt das AFAIK ab 4.8.
-
Ja ist hab so ein "MinGW Installer" mit dem ich das irgendwie installiert hab.
Hat jemand ein Link zu ner Anleitung wie ich GCC 4.8 bekomme. Hab damals einfach auf paar Button gedrückt und irgendwann hat das dann compiliert...
-
Pringles schrieb:
Ja ist hab so ein "MinGW Installer" mit dem ich das irgendwie installiert hab.
Hat jemand ein Link zu ner Anleitung wie ich GCC 4.8 bekomme. Hab damals einfach auf paar Button gedrückt und irgendwann hat das dann compiliert...Du solltest den Installer nochmal neu runterladen und ausführen. Die aktuellste Version von MinGW ist 4.8.1-4
-
Ich hab da ja ganz viele "Package". Eins davon ist mingw32-gcc-g++ in der Version 4.8.1-4.
Woran kann das jetzt liegen?
-
Pringles schrieb:
Ich hab da ja ganz viele "Package". Eins davon ist mingw32-gcc-g++ in der Version 4.8.1-4.
Woran kann das jetzt liegen?Das bedeutet, du hast schon die aktuelle Version. Wenn du auf der Konsole
g++ --versioneingibst, sollte auch 4.8.1-4 kommen.
-
Hab ich mir auch so gedacht.
Es kommt 4.8.1 also ohne -4 ist das schlimm?
Heißt das jetzt das gcc mit Version 4.8.1 das immer noch nicht unterstützt?
Wenn ja welche Compiler alternativen gibt es?
Wenn nein was ist falsch?
-
Mit meinem MinGW32 bekomme ich Fehler bei std::stol, das ist aber ein bekannter Bug. Wenn ich das ersetze, bekomme ich auch den Laufzeitfehler.
Mit meinem MinGW-w64 (gcc 4.9.0) kompiliert und läuft es einwandfrei.
-
Vielen Dank. Läuft nun alles.
Werde mir regex mal genauer anschauen.
Ist das mit Absicht das die main kein return hat? Muss ich das verstehen bzw. ist das erst "später" wichtig/Interessant?
-
Pringles schrieb:
Ist das mit Absicht das die main kein return hat? Muss ich das verstehen bzw. ist das erst "später" wichtig/Interessant?
return 0 in main (und zwar nur in main!) ist überflüssig, weil implizit eingefügt.
-
Ok verstehe.
Ich hab das jetzt hinbekommen das es funktioniert. Würde mich Interessieren ob ich eventuellen schwächen findet.std::istream& operator>>( std::istream& is, serie& s ) { std::string str; if (!std::getline(is >> std::ws, str, ';')) return is; static const std::regex reg("(s[[:space:]]*([0-9]+)[[:space:]]*e[[:space:]]*([0-9]+)*[[:space:]]*)([[:space:]]*/[[:space:]]*final)*"); std::smatch match; if (std::regex_search(str, match, reg)) { s.name_ = match.prefix(); s.staffel_ = std::stol(match[2]); s.episode_ = std::stol(match[3]); s.final_ = match[4].matched; } else { s.name_ = str; s.staffel_ = s.episode_ = 0; s.final_ = 0; } return is; }Restliche Code ist gleich.
Mit Ausnahme das staffel jetzt episode heißst
-
Würde mich Interessieren ob ich eventuellen schwächen findet.

Würde mich freuen wenn ihr schaut ob es Fehler gibt bzw was ihr anders/besser machen würdet.
-
Ich hätte den Regex so gemacht:
if (!std::getline(is, str, ';')) // der Regex kümmert sich um Leerzeichen drum rum return is; // \d: [0-9], \s: [[:space:]], +?: Non-greedy matching, ^ und $: alles anschauen, keinen Substring suchen static const std::regex reg(R"(^\s*(.+?)(\s+s(\d+)e(\d+))?(\s*/final)?\s*$)"); std::smatch match; if (!std::regex_match(str, match, reg)) assert(false); // always matchesDein Regex schlägt fehl bei z.B. "prison s4e24 break s4e24;".
-
Hier noch der Rest vom Code:
s.name_ = match[1]; if (match[2].matched) { s.staffel_ = std::stol(match[3]); s.episode_ = std::stol(match[4]); } else { s.staffel_ = s.episode_ = 0; } s.final_ = match[5].matched; return is;
-
Geht bei mir gar nicht.
Er findet die Namen der Serien nicht. Außerdem verstehe ich dein Regex nicht wirklich "(^\s*(.+?)" was macht das?
Was bewirkt das Doller Zeichen?
Mit den assert bekomme ich ein Laufzeit Fehler:File: main.cpp, Line 41 Expression: falseLine 41:
assert(false); // always matches"prison s4e24 break s4e24;"
So ein Format sollte nicht vorkommen.
if (!std::getline(is, str, ';')) // der Regex kümmert sich um Leerzeichen drum rum
Hab vergessen zu sagen das nach den ';' Kommentare kommen.
Trotzdem Danke.