/** * ------------------------------------------------------------ * Show how convenient it is to use classes instead of a bunch * of C functions. * * Part of the OOP course for PhD students and Researchers. * * Contact: fmaerten@gmail.com * ------------------------------------------------------------ */ #include #include #include #include using namespace std ; /** * @brief A convenient class which help to analyse arguments passed to a command-line. * An argument starts with a minus (a switch), the next argument is either its * value or a next switch. * @note We didn't put any comment in the class as it is self explanatory. * @note Public are first since this is what we are interested in (client code). * Private methods and members follow as they are useless for us. * @note Note how public methods are indented for a better reading of the return * type and the arguments. * @note It is better to write the implementation elsewhere, even if it requires more * writting...That way, the class interface is more simple, less overloaded and * more clear. */ class Args { public: Args(const string& argv) ; bool exists (const string& name) const ; bool hasValue(const string& name) const ; string value (const string& name) const ; vector switches() const ; void display () const ; private: vector split(const string& str, int delimiter(int) = ::isspace) ; int index(const string& name) const ; string argv_ ; vector toks_ ; } ; // ----------------------------------------------------------------------------------- // A convenient function for testing // void check(const Args& a, const string& name) { if (a.exists(name)) { cerr << "switch '" << name << "' exists with value " << a.value(name) << endl ; } else { cerr << "switch '" << name << "' does not exist!" << endl ; } } // ----------------------------------------------------------------------------------- int main(int argc, char** argv) { Args a("-aux 23 -u toto -tol 1e-8 -c -o aaa -name \"filename.txt\" -j") ; cerr << "---------------------------------" << endl ; check(a, "tol") ; cerr << "---------------------------------" << endl ; check(a, "epsilon") ; cerr << "---------------------------------" << endl ; vector switches = a.switches() ; cerr << "List of switches:" << endl ; for (const string& s : switches) { if (a.hasValue(s)) cerr << " [" << s << "] has value [" << a.value(s) << "]" << endl ; else cerr << " [" << s << "]" << endl ; } cerr << "---------------------------------" << endl ; } // ================== IMPL ================================================== Args::Args(const string& argv): argv_(argv) { toks_ = split(argv) ; } bool Args::exists(const string& name) const { return index(name) !=-1 ; } string Args::value(const string& name) const { int i = index(name) ; if (i==-1) { return "" ; } if (i>=toks_.size()-1) { return "" ; } return toks_[i+1] ; } bool Args::hasValue(const string& name) const { int i = index(name) ; if (i==-1) { return false ; } if (i>=toks_.size()-1) { return false ; } if (toks_[i+1][0]=='-') { return false ; } return true ; } vector Args::switches() const { vector s ; for (int i=0; i Args::split(const string& str, int delimiter(int)) { vector result ; auto e=str.end() ; auto i=str.begin() ; while(i!=e) { i = find_if_not(i,e, delimiter) ; if (i==e) { break ; } auto j = find_if(i,e, delimiter) ; result.push_back(string(i,j)) ; i = j ; } return result ; } int Args::index(const string& name) const { for (int i=0; i