Converting string to int for switch manipulator

The question is this that I have to ask the user a month and according to the month I have to set a hoursMax value. I need the user input to be in string but the thing I found out is that switch does not work with strings. Now, is there a way I can work this around? I can use if/else but I want to know if there is a way I can make switch work with strings

I have also looked online and I found a way to convert string into an integer but I not quite familiar with those syntaxs so can you guide me?

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
#include <iostream>

using namespace std;

int main()
{
    string month;

    cout << "Choose a month you want to get bill for: ";
    cin >> month;
    
    
    switch (month) {
        case "Jan":
        case "January":
        case "Mar":
        case "March":
        case "May":
        case "Jul":
        case "July":
        case "Aug":
        case "August":
        case "Oct":
        case "October":
        case "Dec":
        case "December":
            hoursMax = 744;
            break;

        case "Apr":
        case "April":
        case "Jun":
        case "June":
        case "Sept":
        case "September":
        case "Nov":
        case "November":
            hoursMax = 720;
            break;

        case "Feb":
        case "February":
            hoursMax = 672;
            break;
    }
    
    return 0;
}
Last edited on
Switch does not work with strings because switch isn't doing what you think it's doing. Switch and case works for integer constants only, you cannot compare strings with a switch statement.

What you want here is a data structure, not a switch statement. I would use a map<string, int> and just look up the max hours from that.
for a small number of strings you can do this:
string s = "Feb";
unsigned int * ip = (unsigned int*)&s[0];
cout << *ip << endl; //find out what the number is
...
case 73421: //whatever the above number was goes here

with some legwork. Turn each string into its integer.
name each integer with an enum.
use the enum name and you get
switch Feb: //note the lack of quotes, its an int constant now

this isnt portable, so if you change OS the integers change, so it is of very limited value but its extremely fast. If you want it to be portable, use a portable algorithm to hash the string into an integer. Most hash functions are much slower than just the raw bytes repurposed to int.
* you probably need to pad short strings with the zero character until you get to sizeof int (which is probably 4, or use 64 bit, then it is 8).
eg string feb = "Feb\0\"; Its kind of a hacky way to do it...

here is a link to an old function I wrote that does this as well. (scroll down to my post) http://cplusplus.com/forum/general/268492/
its large but its just a lookup table of integers and a small for loop. Its pretty quick.

------------------
or you can do a redesign.
int rates[] = {0,744,672,...}//put all 12 months in, skipping month 0 to start at 1 for convention
have user enter month in number not string, eg 1 for jan, 2 for feb, etc
check is from 1 to 12 and complain if not, then:
return rates[input];
if you can't use the numbers, the map mentioned above is the correct modern approach. I am just giving you a workaround because you asked for it, and it may be useful to know that you can indeed turn strings into numbers (and someday you likely will have to do this) when there is a need.
Last edited on
closed account (z05DSL3A)
An old post from 2014...
http://www.cplusplus.com/forum/beginner/138012/#msg731831
Hello scyp101,

This may not be as neat as other suggestions and it still need some finish work, but something to consider.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
#include <iostream>
#include <string>
#include <vector>

int main()
{
    constexpr int MAXNAMES{ 12 };
    const enum monthNames { JAN, FEB, MAR, APR, MAY, JUN, JUL, AUG, SEP, OCT, NOV, DEC };

    int monthNum{}, hoursMax{};
    std::string month;
    const std::vector<std::string> shortMonthNames{ "Jan", "Feb", "Dec" };
    const std::vector<std::string> LongMonthNames{ "January", "February", "December" };
    const std::vector<int> monthNumbers{ 0, 1, 11 };

    std::cout << "Choose a month you want to get bill for: ";
    std::cin >> month;

    for (int idx = 0; idx < MAXNAMES; idx++)
    {
        if (month == shortMonthNames[idx] || month == LongMonthNames[idx])
        {
            monthNum = idx;

            break;
        }
    }

    switch (monthNum)
    {
        case JAN:
            break;
        case MAR:
            break;
        case APR:
            break;
        case MAY:
            break;
        case JUN:
            break;
        case JUL:
            break;
        case AUG:
            break;
        case SEP:
            break;
        case OCT:
            break;
        case NOV:
            break;
        case DEC:
            break;

        case FEB:
            hoursMax = 672;
            break;
        default:
            break;
    }

    return 0;  // <--- Not required, but makes a good break point.
}

If you are not familiar with vectors you could just use arrays.

Andy
As was suggested by gaxio, why not just a simple map? As an example, consider:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
#include <unordered_map>
#include <string>
#include <iostream>
#include <cctype>

int main()
{
	const std::unordered_map<std::string, int> months {{"jan", 744}, {"january", 744}, {"feb", 672}, {"february", 672}, {"apr", 720}, {"april", 720}};

	std::string month;

	std::cout << "Choose a month you want to get bill for: ";
	std::cin >> month;

	for (auto& ch : month)
		ch = (char)std::tolower(ch);

	if (auto fnd {months.find(month)}; fnd != months.end())
		std::cout << "Hours max is " << fnd->second << '\n';
	else
		std::cout << "Month not found\n";
}


which also converts the entered name to lowercase. Obviously the months variable to be extended to cover required month names.

Also, just using an array consider:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
#include <string>
#include <iostream>
#include <cctype>

struct Months {
	const char* const moj {};
	int hours {};
};

int main()
{
	constexpr Months months[] {{"jan", 744}, {"january", 744}, {"feb", 672}, {"february", 672}, {"apr", 720}, {"april", 720}};

	std::string month;

	std::cout << "Choose a month you want to get bill for: ";
	std::cin >> month;

	for (auto& ch : month)
		ch = (char)std::tolower(ch);

	bool got {};

	for (const auto& [mon, hmax] : months)
		if (month == mon) {
			std::cout << "Hours max is " << hmax << '\n';
			got = true;
			break;
		}

	if (!got)
		std::cout << "Month not found\n";
}

Last edited on
Topic archived. No new replies allowed.