Created
April 5, 2014 21:43
-
-
Save hamsham/9998434 to your computer and use it in GitHub Desktop.
Skeleton code for a command-Line argument tokenizer. It will input command-line arguments, convert them into a native data type, and place them into an std::vector as tuples.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/** | |
* Simple string-to-type tokenizing. | |
* This program can be used as skeleton code for creating a tokenizer for | |
* command-line arguments. It will convert values into a tuple-type where values | |
* can be extracted using their intended data type. | |
* | |
* Example: | |
* token +3.14159 | |
* Results in two returned values: | |
* String: "token" (without quotes) | |
* Float: 3.14159 | |
* | |
* Compile with: | |
* g++ -std=c++11 -Wall -Werror -Wextra -pedantic -pedantic-errors token.cpp -o token | |
*/ | |
#include <iostream> // stds::cout | |
#include <utility> // std::move(...) | |
#include <string> // std::string | |
#include <cctype> // isDigit(...) | |
#include <vector> // std::vector | |
#include <cstdlib> // strtod(...), strtol(...) | |
enum data_t : int { | |
CHAR, | |
INT, | |
FLOAT, | |
STRING | |
}; | |
struct tuple { | |
data_t type; | |
union { | |
char c; | |
int i; | |
float f; | |
const char* s; | |
}; | |
std::string asString; | |
}; | |
bool tokenize(std::string&& s, tuple& t) { | |
bool containsDecimal = false; | |
bool containsString = false; | |
bool containsNumber = false; | |
// Initialize the token | |
t.asString = std::move(s); | |
const std::string& str = t.asString; | |
// do an initial check to see if the token is a character | |
if (str.size() == 1 && isdigit(str[0]) == 0) { | |
t.type = data_t::CHAR; | |
t.c = str[0]; | |
} | |
else { | |
// parse the token for its data type | |
for (unsigned i = 0; i < str.size(); ++i) { | |
// look for a number | |
if (isdigit(str[i]) != 0) { | |
containsNumber = true; | |
continue; | |
} | |
// determine if the first digit might be minus or plus sign | |
if (i == 0 && (str[0] == '-' || str[0] == '+')) { | |
continue; | |
} | |
if (str[i] == '.') { | |
// tokenize as a string if a decimal was already found | |
if (containsDecimal == true) { | |
containsString = true; | |
break; | |
} | |
containsDecimal = true; | |
} | |
else { | |
containsString = true; | |
break; | |
} | |
} | |
// convert the token into a tuple | |
if (containsString == true) { | |
t.type = data_t::STRING; | |
t.s = t.asString.c_str(); | |
} | |
else if (containsDecimal == true) { | |
t.type = data_t::FLOAT; | |
t.f = (float) strtod(str.c_str(), nullptr); | |
} | |
else if (containsNumber == true) { | |
t.type = data_t::INT; | |
t.i = (int) strtol(str.c_str(), nullptr, 10); | |
} | |
else { | |
return false; | |
} | |
} | |
return true; | |
} | |
int main(int argc, const char** argv) { | |
std::vector<tuple> tokens{(unsigned)argc}; | |
for (int i = 0; i < argc; ++i) { | |
tuple t; | |
bool wasTokenized = tokenize(std::move(std::string{argv[i]}), t); | |
if (wasTokenized == true) { | |
tokens[i] = t; | |
} | |
else { | |
std::cout << "ERROR: Unable to tokenize " << argv[i] << std::endl; | |
return -1; | |
} | |
} | |
for (const tuple& pToken : tokens) { | |
if (pToken.type == data_t::CHAR) { | |
std::cout << "CHAR --- " << pToken.c; | |
} | |
else if (pToken.type == data_t::INT) { | |
std::cout << "INT --- " << pToken.i; | |
} | |
else if (pToken.type == data_t::FLOAT) { | |
std::cout << "FLOAT --- " << pToken.f; | |
} | |
else { | |
std::cout << "STRING --- " << pToken.s; | |
} | |
std::cout << '\n'; | |
} | |
return 0; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment