Reputation: 392
I am looking to make this function in c++, input("x = ");, somewhat like in python, this function prints the message in the () and the expects input. It can take only bool,str,int,double. I thought of making a struct input like so
struct input {
std::string str;
int num;
double dub;
bool boolean;
input(const char *s) {
std::cout << s;
std::cin >> ### ; //here is my problem
}
};
But that's as I far as I got. I tried templates but still couldn't figure it out.
Extracting the input shouldn't be so difficult, I will figure that out, for now I just want to see how to get my data in the struct.
Upvotes: 1
Views: 328
Reputation: 392
What i did was make a class,
template <typename T> using couple = std::pair<bool, T>;
struct input {
std::string inp;
couple<std::string> str = {false, ""};
couple<int> num = {false, 0};
couple<double> dbl = {false, 0};
couple<bool> bl = {false, 0};
input(const char *s) {
std::cout << s;
std::cin >> inp;
fillinput(inp);
}
bool check_bool(std::string inputVal) {
transform(inputVal.begin(), inputVal.end(), inputVal.begin(), ::tolower);
if (inputVal == "false") {
bl.first = true;
bl.second = false;
return true;
}
if (inputVal == "true") {
bl.first = bl.second = true;
return true;
}
return false;
}
bool check_double(std::string inputVal) {
int dots = std::count(inputVal.begin(), inputVal.end(), '.');
bool digits = std::all_of(inputVal.begin(), inputVal.end(), ::isdigit);
if (dots == 1 && digits) {
dbl.first = true;
dbl.second = std::stod(inputVal);
return true;
}
return false;
}
bool check_int(std::string inputVal) {
bool digits = std::all_of(inputVal.begin(), inputVal.end(), ::isdigit);
if (digits) {
num.first = true;
num.second = std::stoi(inputVal);
return true;
}
return false;
}
void fillinput(std::string Input) {
if (check_int(Input) || (check_bool(Input)) || (check_double(Input)))
return;
else {
str.first = true;
str.second = Input;
}
}
};
It takes some more work to make this usable but this is the way. I know its not good code but it is what it is.
Upvotes: 0
Reputation: 122994
Generally translating Python to C++ is difficult due to the fundamentally different type systems. However, thats not an issue here. From documentation:
If the prompt argument is present, it is written to standard output without a trailing newline. The function then reads a line from input, converts it to a string (stripping a trailing newline), and returns that. When EOF is read, EOFError is raised.
Python's input
does'nt do any conversion. It just returns a string. The EOF
exception can be enabled, but it requires a bit of boilerplate to reset the streams exceptions settings when an exception is actually thrown. It can be done with the help of a RAII class whose only purpose is to reset the streams previous exception settings, no matter whether the function returns or throws.
struct eof_exception_enabled {
std::istream & inp;
std::ios::iostate old;
eof_exception_enabled(std::istream& inp) : inp(inp), old(inp.exceptions()) {
inp.exceptions(old | std::ios::eofbit);
}
~eof_exception_enabled() {
inp.exceptions(old);
}
};
std::string input(std::string prompt = "") {
std::cout << prompt;
std::string res;
auto inp = eof_exception_enabled{std::cin};
std::getline(inp.inp, res);
return res;
}
Actually it would be more idiomatic to pass also the input stream to input
so that different streams can be used. Not sure how much sense this would make for a function that prompts the user and typically reads from standard input.
If you want to enable conversions you can use a function template that utilizes a stringstream for the conversion:
template <typename T>
T from_string(const std::string& str) {
std::stringstream ss{str};
T t;
ss >> t;
return t;
}
Usage would be
auto age = from_string<int>( input("enter your age:"));
However, correctly handling errors due to unexpected input requires a bit more. from_string
does just return 0
when extraction from the stream fails for integer types. Though, now we are talking about the conversion, which also in Python is not done by input
.
Upvotes: 4