Solution based on what you have:
std::regex
is not std::string
, these are completely different types. I also doubt, if you can get any sensible results, using std::regex
as map key. What's more, std::map will never work as you expected. If you like to test a string against list of regexes and pick the one that matches, you have to do exactly that: iterate over all regexes and test each one. If you are going to laxer these regexes, it is what you'll need.
Much easier approach would be to convert all read strings to lowercase, and then using standard map of strings. Something like:
#include <cctype>
static inline void stringToLower(std::string &s) {
for (uint i = 0; i < s.size(); ++i) {
s[i] = tolower(s[i]);
}
}
istream& operator>>(istream& is, Card& d)
{
std::map<std::string,Card::Rank> mr;
std::map<std::string,Card::Suit> ms;
mr["two"] = Card::TWO;
mr["three"] = Card::THREE;
...
mr["king"] = Card::KING;
ms["clubs"] = Card::CLUBS;
...
string srank, ssuit, c1;
if (is >> srank >> c1 >> ssuit)
{
stringToLower(c1);
if (c1 == "of")
{
stringToLower(srank);
stringToLower(ssuit);
Card::Rank rank = mr[srank];
Card::Suit suit = ms[ssuit];
d = Card(rank, suit);
}
else
{
is.clear(ios_base::failbit);
}
}
return is;
}
Note, that I changed c1 to string. In yout version, c1 would be the first character after srank (it would be some whiltespace). Also, char
value can never be equal to 'of'
('of'
is of type int). I changed it to "of"
(double quotes), which is of type const char *
. Remember, that it wouldn't work properly, if c1 was char*
.
By the way, it is very innefficient to create mr
and ms
maps for every <<
call separately. Consider using some kind of singleton. Possible solution may be something like:
static std::map<std::string,Card::Rank> createmr() {
std::map<std::string,Card::Rank> mr;
mr["two"] = Card::TWO;
mr["three"] = Card::THREE;
...
mr["king"] = Card::KING;
return mr;
}
static std::map<std::string,Card::Rank> createms() {
std::map<std::string,Card::Rank> ms;
ms["clubs"] = Card::CLUBS;
...
return ms;
}
istream& operator>>(istream& is, Card& d)
{
static std::map<std::string,Card::Rank> mr = createmr(); // note `static` keyword
static std::map<std::string,Card::Suit> ms = createms();
...
}
Explanation: I used static
keyword here, in 2 different kinds of places. One is before functin declaration. That static
means, that this functions will be not available in other source files. I also used it in mr
and ms
declarations. There it means, that these variables are common for all calls of function, in which they were defined (in this case, operator>>
). One consequence of that is, that createmr() and createms() will be called only once, in the first call of operator.
Possibly better way is to define mr
and ms
outside the function:
static std::map<std::string,Card::Rank> mr = createmr(); // note `static` keyword
static std::map<std::string,Card::Suit> ms = createms();
istream& operator>>(istream& is, Card& d)
{
...
}
static
keyword here means, that these variables (which are now global), will be not accessible from outside this source file. It may be omitted here, but it is good practice to mark static
all functions and global variables, that are not going to be used outside.