Wie boost::regex befragen: Welches Zeichen ist für neg. Test verantwortlich? Jetzt auch boost::spirit
-
N'Abend allerseits!
Hat boost::regex die Möglichkeit mir zu sagen an welcher Stelle im String es den ersten Verstoß findet?
Kleines Bsp.:
Regex: "^abcd$"
String: "abed"
Ergebnis: An der dritten Pos. ist die erste Regelverletzung.Danke und Gruß,
Goran
-
Da es bei einem nicht übereinstimmen eines RegExp sich nicht um einen "Regelverstoß" handelt sondern schlicht dass das Muster nicht auf den string passt wirst Du es IMHO mit der boost::regex nicht herausfinden können. Vielleicht wirst Du aber mit boost::spirit fündiger. Der parser gibt nach dem parsen eine parse_info struktur zurück die enthält infos ob es fehl geschlagen ist und an welcher Stelle er aufgehört hat mit parsen.
Gut Schuß
VuuRWerK
-
Danke VuuRWerK.
Ich habe mich an boost::spirit gemacht. Doch ohne Erfolg

Hier ein kurzer Versuch der leider nicht das erwünschte Ergebnis bringt:
#include <boost/spirit.hpp> #include <string> #include <iostream> int main() { using namespace std; using namespace boost::spirit; // config string conf = "Somevar=1234"; // variable rule<> someVar = strlit<>("SomeVar"); // value rule<> someVal = int_p >> int_p >> int_p >> int_p; // declaration rule<> confDec = someVar >> strlit<>("=") >> someVal; // parsing parse_info<> pI = parse(conf.c_str(),confDec); if(pI.full) cout << "OK.\n"; return 0; }Hat jemand Verbesserungsvorschläge?
Gruß, Goran
-
Da möchte ich Dir mal folgendes Tutorial ans herz legen: Klick Da wird Spirit sehr gut anhand eines INI-File Parsers erklärt, denke das geht in die Richtung was Du machen möchtest.
Gut Schuß
VuuRWerK
-
int_p ist bereits für mehrstellige Zahlen gedacht.
-
Danke für eure Hilfe. Ich hatte im obigen Bsp. in Zeile 11 einen Schreibfehler innerhalb des Strings.
Jetzt geht das Bsp.Das von VuuRWerK verlinkte Tutorial habe ich mir heute morgen reingezogen. Doch stellt sich mir eine Frage:
Wie kann ich Variablen überprüfen (Variablen aufgebaut wie in meinem Bsp.) wenn ich deren Reihenfolge nicht kenne? Ich möchte dem User nicht vorschreiben in welcher Reihenfolge er die Variablen angibt. Aber er soll sie nur einmal angeben können.
Gruß, Goran
-
du kannst den einzelnen parsern semantic actions mitgeben, z.B. eine action die den gerade geparsten Variablennamen in einer Symboltabelle nachschlägt und bei einer wiederholten Deklaration Alarm schlägt.
-
Hallo, ich habe mich heute wieder an boost::spirit gemacht.
Folgender Code funktioniert:
#include <iostream> #include <iostream> #include <fstream> #include <string> #include <boost/spirit.hpp> using namespace std; using namespace boost::spirit; int main() { // rules rule<> comment = chlit<>('#') >> *(anychar_p - eol_p) >> eol_p; rule<> space = *(space_p | comment); rule<> hostName = repeat_p(4)[range<>('a','d')]; rule<> hostIp = repeat_p(4)[range<>('1','4')]; rule<> converter = strlit<>("converter") >> space >> strlit<>("=") >> space >> strlit<>("\"") >> hostName >> strlit<>("\"") >> space; rule<> analyser = strlit<>("analyser") >> space >> strlit<>("=") >> space >> strlit<>("\"") >> hostIp >> strlit<>("\"") >> space; rule<> conf = space >> repeat_p(2)[converter | analyser] >> space; // open file ifstream f("test.conf"); if(!f) { cerr << "Can't open config file!\n"; exit(1); } // read file string s; while(f.good()) getline(f,s,'~'); // parse parse_info<> pi = parse(s.c_str(),conf); if(pi.full) cout << "File is OK:\n"; else cout << "Can't understand \"Test.conf\" at position " << pi.length << ". Stopped at:\n" << pi.stop; return 0; }Bei folgender test.conf ist alles OK:
converter ="abcd" # bla analyser="1234" # fooSobald die Datei die def. Regeln verletzt (z.B. indem man aus "1234" "123" macht) beendet sich das Prog. mit einer Statusmeldung. Aber ich bekomme hier folgende Ausgabe:
Can't understand "test.conf" at position 4294967295. Stopped here:
"
# fooNun ist 4294967295 = 2^32-1. Was bedeutet das? Läuft hier was über? Damit kann ich dem Nutzer nicht sagen wo seine Datei fehlerhaft ist.
Wisst ihr Rat?
Gruß, Goran
-
Hab' jetzt eine Lösung:
#include <iostream> #include <fstream> #include <string> #include <boost/spirit.hpp> using namespace std; using namespace boost::spirit; int main() { // rules rule<> comment = chlit<>('#') >> *(anychar_p - eol_p) >> eol_p; rule<> space = *(space_p | comment); rule<> hostName = repeat_p(4)[range<>('a','d')]; rule<> hostIp = repeat_p(4)[range<>('1','4')]; rule<> converter = strlit<>("converter") >> space >> strlit<>("=") >> space >> strlit<>("\"") >> hostName >> strlit<>("\"") >> space; rule<> analyser = strlit<>("analyser") >> space >> strlit<>("=") >> space >> strlit<>("\"") >> hostIp >> strlit<>("\"") >> space; rule<> conf = space >> repeat_p(2)[converter | analyser] >> space; // open file ifstream f("test.conf"); if(!f) { cerr << "Can't open config file!\n"; exit(1); } // read file string s; while(f.good()) getline(f,s,'~'); const char * c = s.c_str(); // parse parse_info<> p = parse(c,conf); if(p.full) cout << "File is OK:\n"; else cout << "Can't understand \"Test.conf\" at position " << p.stop-s.c_str() << ".\n"; return 0; }