Methode zum Parsen von Strings gesucht
-
Ich suche eine Bibliothek, die das Parsen von simplen Strings einfacher macht.
Also z.B. eine Art scanf, mit dem man folgendes machen kann:std::string a; int b; double c; std::atomic_int d; std::string line="abcdef delim var=1, 2, 3 delim"; if (sscanf(line,"%*delim %s=%d, %u, %d delim",a,b,c,d)==4)...;k.A. ob es überhaupt möglich ist, zur Laufzeit die richtigen Konversionen und Zuweisungen auszuführen, aber Templatemagier sind bekanntlich erfinderisch.
Muss natürlich nicht genau solch ein scanf sein, alternativen Ansätze sind willkommen, solange sie nur einfach zu benutzen sind.Wie macht ihr das?
-
scanf war praktisch schrieb:
Wie macht ihr das?
std::regex
-
von regex wollte ich mich fern halten, da das meist unleserlichen Code erzeugt. Wenn ich 10 Minuten brauche, um eine besonders clevere Zeile regex zu verstehen, dann möchte ich jemanden hauen, am besten den verantwortlichen Autor.
Dennoch, ich probiere mal, ob das für den aktuellen Anwendungsfall ausreichend gut funktioniert.
-
-
-
lieber sone schrieb:
Arcoth schrieb:
Ist dir der Unterschied von scanf und printf bekannt?
Tut mir Leid, mein Fehler - ich meinte mich erinnern zu können, dass Boost.Format auch parst. Aber das ist offensichtlich nicht der Fall.
#include <iostream> #include <sstream> #include <limits> std::istream& gen_scanf( std::istream& is, char const* format ) { while( *format ) if( is.get() != *format++ ) { is.setstate( std::ios_base::failbit ); break; } return is; } template< typename Input > void extract( std::istream& is, char const*, Input& input ) { is >> input; } void extract( std::istream& is, char const*& format, std::string& input ) { std::getline(is, input, *format++); } template< typename First, typename... Tail> std::istream& gen_scanf( std::istream& is, char const* format, First& first, Tail&... tail ) { while( *format && is ) { if( *format == '%' ) if( *++format == '*' ) { ++format; while( is && is.get() != *format ); ++format; } else { extract(is, format, first); return gen_scanf(is, format, tail...); } else if( *format++ != is.get() ) { is.setstate( std::ios_base::failbit ); break; } } return is; } template< typename First, typename... Tail> std::istream& gen_sscanf( char const* input, char const* format, First& first, Tail&... tail ) { std::istringstream stream{input}; return gen_scanf(stream, format, first, tail...); } int main () { std::string a; int b; double c; std::string line="abcdef delim var=1, 2 delim"; gen_sscanf(line.c_str(),"%* delim %=%, % delim",a,b,c); std::cout << "a: " << a << '\n' << "b: " << b << '\n' << "c: " << c << '\n'; }Das ist eine minimalistische Implementierung, die obigem entspricht.