Evaluate a string with a switch in C++
C++C++ Problem Overview
I want to evaluate a string with a switch but when I read the string entered by the user throws me the following error.
#include<iostream>
using namespace std;
int main() {
string a;
cin>>a;
switch (string(a)) {
case "Option 1":
cout<<"It pressed number 1"<<endl;
break;
case "Option 2":
cout<<"It pressed number 2"<<endl;
break;
case "Option 3":
cout<<"It pressed number 3"<<endl;
break;
default:
cout<<"She put no choice"<<endl;
break;
}
return 0;
}
> error: invalid cast from type 'std::string {aka std::basic_string
C++ Solutions
Solution 1 - C++
As said before, switch can be used only with integer values. So, you just need to convert your "case" values to integer. You can achieve it by using constexpr from c++11, thus some calls of constexpr functions can be calculated in compile time.
something like that...
switch (str2int(s))
{
case str2int("Value1"):
break;
case str2int("Value2"):
break;
}
where str2int is like (implementation from here):
constexpr unsigned int str2int(const char* str, int h = 0)
{
return !str[h] ? 5381 : (str2int(str, h+1) * 33) ^ str[h];
}
Another example, the next function can be calculated in compile time:
constexpr int factorial(int n)
{
return n <= 1 ? 1 : (n * factorial(n-1));
}
int f5{factorial(5)};
// Compiler will run factorial(5)
// and f5 will be initialized by this value.
// so programm instead of wasting time for running function,
// just will put the precalculated constant to f5
Solution 2 - C++
You can map the strings to enum values, then switch on the enum:
enum Options {
Option_Invalid,
Option1,
Option2,
//others...
};
Options resolveOption(string input);
// ...later...
switch( resolveOption(input) )
{
case Option1: {
//...
break;
}
case Option2: {
//...
break;
}
// handles Option_Invalid and any other missing/unmapped cases
default: {
//...
break;
}
}
Resolving the enum can be implemented as a series of if
checks:
Options resolveOption(std::string input) {
if( input == "option1" ) return Option1;
if( input == "option2" ) return Option2;
//...
return Option_Invalid;
}
Or a map lookup:
Options resolveOption(std::string input) {
static const std::map<std::string, Option> optionStrings {
{ "option1", Option1 },
{ "option2", Option2 },
//...
};
auto itr = optionStrings.find(input);
if( itr != optionStrings.end() ) {
return itr->second;
}
return Option_Invalid;
}
Solution 3 - C++
A switch
statement can only be used for integral values, not for values of user-defined type. (And even if it could, your input operation doesn't work, either. The >>
operation extracts single tokens, separated by whitespace, so it can never retrieve a value "Option 1"
.)
You might want this:
#include <string>
#include <iostream>
std::string input;
if (!std::getline(std::cin, input)) { /* error, abort! */ }
if (input == "Option 1")
{
// ...
}
else if (input == "Option 2")
{
// ...
}
// etc.
Solution 4 - C++
You can only use switch-case on types castable to an int.
You could, however, define a std::map<std::string, std::function> dispatcher
and use it like dispatcher[str]()
to achieve same effect.
Solution 5 - C++
You can't. Full stop.
switch
is only for integral types, if you want to branch depending on a string you need to use if/else
.
Solution 6 - C++
what about just have the option number:
#include <iostream>
#include <string>
using namespace std;
int main()
{
string s;
int op;
cin >> s >> op;
switch (op) {
case 1: break;
case 2: break;
default:
}
return 0;
}
Solution 7 - C++
Switch value must have an Integral type. Also, since you know that differenciating character is in position 7
, you could switch on a.at(7)
. But you are not sure the user entered 8 characters. He may as well have done some typing mistake. So you are to surround your switch statement within a Try Catch. Something with this flavour
#include<iostream>
using namespace std;
int main() {
string a;
cin>>a;
try
{
switch (a.at(7)) {
case '1':
cout<<"It pressed number 1"<<endl;
break;
case '2':
cout<<"It pressed number 2"<<endl;
break;
case '3':
cout<<"It pressed number 3"<<endl;
break;
default:
cout<<"She put no choice"<<endl;
break;
}
catch(...)
{
}
}
return 0;
}
The default clause in switch statement captures cases when users input is at least 8 characters, but not in {1,2,3}.
Alternatively, you can switch on values in an enum
.
EDIT
Fetching 7th character with operator[]()
does not perform bounds check, so that behavior would be undefined. we use at()
from std::string
, which is bounds-checked, as explained here.