Reputation: 1574
I am trying to parse input from a file to represent a standard deck of cards (i.e. 2C represents the two of clubs). However, my solution is not working as expected, and is declaring all inputs to be invalid. I can't see any logical errors in my code, so I wanted to get a second opinion. The code is below:
/*
* Determines if the input string is valid.
*
* A string is considered valid if it begins with either a number (2-10)
* or a letter (J/j, Q/q, K/k) to deetermine rank, followed by a letter to
* determine suit (C/c, D/d, H/h, S/s).
*/
bool inputValidator(string cardData)
{
if (cardData.length() == 2) //Input string is two characters long
{
if (cardData[0] < '2' || cardData[0] > '9'
|| cardData[0] != 'J' || cardData[0] != 'j'
|| cardData[0] != 'Q' || cardData[0] != 'q'
|| cardData[0] != 'K' || cardData[0] != 'k'
|| cardData[0] != 'A' || cardData[0] != 'a')
{
cout << "Card with data " << cardData << " has an invalid rank." << endl;
return false;
}
if (cardData[1] != 'C' || cardData[1] != 'c' //Parse suit
|| cardData[1] != 'D' || cardData[1] != 'd'
|| cardData[1] != 'H' || cardData[1] != 'h'
|| cardData[1] != 'S' || cardData[1] != 's')
{
cout << "Card with data " << cardData << " has an invalid suit." << endl;
return false;
}
return true;
}
else if (cardData.length() == 3) //Input string is three characters long
//This occurs only if the number is 10.
{
if (cardData[0] != '1' || cardData[1] != '0') //Parse rank
{
cout << "Card with data " << cardData << " has an invalid rank." << endl;
return false;
}
if (cardData[2] != 'C' || cardData[2] != 'c' //Parse suit
|| cardData[2] != 'D' || cardData[2] != 'd'
|| cardData[2] != 'H' || cardData[2] != 'h'
|| cardData[2] != 'S' || cardData[2] != 's')
{
cout << "Card with data " << cardData << " has an invalid suit." << endl;
return false;
}
return true;
}
return false;
}
If there are any logical flaws (or an inherently better way to do this), I would appreciate being told. Thanks.
Upvotes: 0
Views: 101
Reputation: 45450
Your logic expression isn't correct, also you are duplicating code, try to simply them to functions.
bool inputValidator(string cardData)
{
if (cardData.length() == 2 && IsValidCard(cardData[0])) //Input string is two characters long
{
return IsValidSuite(cardData[1]);
}
else if(cardData.length() == 3)
{
if (isValidRank(cardData[0]))
{
return IsValidSuite(cardData[2]);
}
}
return false;
}
bool isValidRank(char c)
{
if (c =='0' || c=='1')[
{
return true;
}
return false;
}
bool IsValidCard(char c)
{
if (c > '2' && c < '9')
{
return true;
}
switch(c)
{
case 'J':
case 'j':
case 'Q':
case 'q':
case 'K':
case 'k':
case 'A':
case 'a':
return true;
}
return false;
}
bool IsValidSuite(char c)
{
switch(c)
{
case 'C':
case 'c':
case 'D':
case 'd':
case 'H':
case 'h':
case 'S':
case 's':
return true;
}
return false;
}
Upvotes: 1
Reputation: 10161
You can simplify the conditions a bit: And your conditions must be changed to do what you want.
bool inputValidator(string cardData)
{
if (cardData.length() == 2) //Input string is two characters long
{
if (!((cardData[0] >= '2' && cardData[0] <= '9')
|| (cardData[0]|32) == 'j'
|| (cardData[0]|32) == 'q'
|| (cardData[0]|32) == 'k'
|| (cardData[0]|32) == 'a'))
{
cout << "Card with data " << cardData << " has an invalid rank." << endl;
return false;
}
if (!((cardData[1]|32) == 'c' //Parse suit
|| (cardData[1]|32) == 'd'
|| (cardData[1]|32) == 'h'
|| (cardData[1]|32) == 's'))
{
cout << "Card with data " << cardData << " has an invalid suit." << endl;
return false;
}
return true;
}
else if (cardData.length() == 3) //Input string is three characters long
//This occurs only if the number is 10.
{
if (!(cardData[0] == '1' || cardData[1] == '0')) //Parse rank
{
cout << "Card with data " << cardData << " has an invalid rank." << endl;
return false;
}
if (!((cardData[2]|32) == 'C' //Parse suit
|| (cardData[2]|32) == 'd'
|| (cardData[2]|32) == 'h'
|| (cardData[2]|32) == 's'))
{
cout << "Card with data " << cardData << " has an invalid suit." << endl;
return false;
}
return true;
}
return false;
}
The code duplication for the second / third character should also be refactored.
Upvotes: 1
Reputation: 16612
You're writing clauses like this:
cardData[2] != 'D' || cardData[2] != 'd'
Which will always be true, as the variable being tested can't be both values at the same time. You probably meant to use &&
rather than ||
.
You could certainly simplify the logic, for example by converting the input to lower or upper case before comparing it.
Upvotes: 4
Reputation: 126542
The problem seems to be in the way you combine your conditions. If I understand your expectation correctly, what you want for the first conditions is this:
if (!(cardData[0] > '2' && cardData[0] < '9')
&& cardData[0] != 'J' && cardData[0] != 'j'
&& cardData[0] != 'Q' && cardData[0] != 'q'
&& cardData[0] != 'K' && cardData[0] != 'k'
&& cardData[0] != 'A' && cardData[0] != 'a')
And what you want for the second condition is this:
if (cardData[1] != 'C' && cardData[1] != 'c' //Parse suit
&& cardData[1] != 'D' && cardData[1] != 'd'
&& cardData[1] != 'H' && cardData[1] != 'h'
&& cardData[1] != 'S' && cardData[1] != 's')
Upvotes: 2