Vectoren sortieren, Zahlen erkennen
-
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.