Define User Input From an Integer List in C++
C++
There are many ways to collect user input. In this example a user is prompted to make a selection from a numbered list. This sets the int choice
variable, which can then be used to control programme flow.
The possible values for user selection, along with a related string label for each value are set up using a struct
.
Input is handled by std::getline()
, with the input converted to an integer by means of the std::stringstream
operator >>
. I’ve done it this way rather than using std::cin
so that an empty return can be handled and interpreted as the default value, if this has been set in the selectAction()
function call.
Example Code
Compile this using c++11 standards. for example: g++ -o test -std=c++11 test.cpp
#include <iostream>
#include <algorithm> // Needed for any_of()
#include <string>
#include <map>
#include <sstream>
int selectAction(int defaultChoice);
int main(int argc, char const *argv[])
{
int userChoice = 0;
std::cout << "This program prompts a user for input." << std::endl;
// Pass in a default value 1
userChoice = selectAction(1);
std::cout << "Choice made: " << userChoice << std::endl;
return 0;
}
int selectAction(int defaultChoice)
{
// Create a data structure `optionPair` so that values may be associated with
// labels, and initialize an array of `optionPair` elements.
struct optionPair {
std::string label;
int value;
} options[] = {
{"Label for Option 1", 1},
{"Label for Option 2", 2},
{"Label for Option 3", 3}
};
// Create an array of valid input values
const int nOptions = sizeof(options)/sizeof(optionPair);
int validChoices[nOptions];
for (int i = 0; i < nOptions; i++) {
validChoices[i] = options[i].value;
}
int choice;
bool validChoice;
while (true) {
int choice = 0;
std::string input = "";
std::cout << "Please select an option:" << std::endl;
for (auto&& option : options)
{
std::cout << option.value << ") " << option.label << std::endl;
}
std::getline(std::cin, input);
std::stringstream tempStream(input);
// Is it empty? User just hit return
if (tempStream.str().empty()) {
choice = -1;
} else {
// The user entered something, so convert it to an integer. If the
// entry is not a number, it will be transformed to 0.
tempStream >> choice;
}
// `[&]` specifies that the lambda uses variable capture - needed here
// since the lambda accesses the `choice` variable.
validChoice = std::any_of(std::begin(validChoices), std::end(validChoices), [&](const int& i)
{
return i == choice;
});
if (defaultChoice && choice == -1) {
// User entered return & a default exists - return the default
return defaultChoice;
} else if (validChoice) {
// User selection returned if valid
return choice;
}
// User feedback for invalid entry
std::cout << "You've entered an invalid selection." << std::endl
<< "Please enter a number from the specified list. Thanks." << std::endl;
}
}
I’m sure there are better ways to allow users to choose from a list of integer values - please leave a comment if you have a suggestion.
References
comments powered by Disqus