Skip to content

Instantly share code, notes, and snippets.

@xaliphostes
Last active October 14, 2022 06:38
Show Gist options
  • Save xaliphostes/58eae0a04a38c6f11476702865b139ab to your computer and use it in GitHub Desktop.
Save xaliphostes/58eae0a04a38c6f11476702865b139ab to your computer and use it in GitHub Desktop.
https://repl.it/CYSv/30 created by xaliphostes
/**
* ------------------------------------------------------------
* 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 <iostream>
#include <string>
#include <vector>
#include <algorithm>
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<string> switches() const ;
void display () const ;
private:
vector<string> split(const string& str, int delimiter(int) = ::isspace) ;
int index(const string& name) const ;
string argv_ ;
vector<string> 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<string> 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<string> Args::switches() const {
vector<string> s ;
for (int i=0; i<toks_.size(); ++i) {
if (toks_[i][0]=='-') {
s.push_back(toks_[i].substr(1,string::npos)) ;
}
}
return s ;
}
void Args::display () const {
for (int i=0; i<toks_.size(); ++i) {
if (toks_[i][0]=='-') {
cerr << toks_[i].substr(1,string::npos) ;
if (i<toks_.size()-1 && toks_[i+1][0]!='-') {
cerr << "\t" << toks_[i+1] ;
i++ ;
}
cerr << endl ;
}
}
}
// private
vector<string> Args::split(const string& str, int delimiter(int)) {
vector<string> 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<toks_.size(); ++i) {
if (toks_[i][0]=='-') {
if (toks_[i].substr(1,string::npos)==name) {
return i ;
}
}
}
return -1 ;
}
gcc version 4.6.3
Command launched:
args -aux 23 -u toto -tol 1e-8 -c -o aaa -name "filename.txt" -j
>>> ---------------------------------
switch 'tol' exists with value 1e-8
---------------------------------
switch 'epsilon' does not exist!
---------------------------------
List of switches:
[aux] has value [23]
[u] has value [toto]
[tol] has value [1e-8]
[c]
[o] has value [aaa]
[name] has value ["filename.txt"]
[j]
---------------------------------
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment