Verifying that inputs are in range - c++

I'm having a problem implementing this.. the program is meant to take date input in the format dd.mm.yyyy, it does that already but I've been trying to add the code that checks
if the date is more than 31 or February is more than 28
if the month is more than 12
It should return an error since the input is incorrect
And also if a user start input with . then the program shouldn't allow more than 2 inputs of .. so that the user can just just go back with the arrow buttons and type in the correct input
#include "examplevalidator.h"
ExampleValidator::ExampleValidator(QObject* parent)
: QValidator (parent)
{
}
ExampleValidator::~ExampleValidator()
{
}
QValidator::State ExampleValidator::validate( QString & input, int & pos ) const
{
if (input.isEmpty()) return Intermediate;
bool ok;
QString str;
str = input[pos-1];
if(input.size() == 10
&& ((input[2] == '.'))
&& ((input[5] == '.'))
&& input[0].isDigit()
&& input[1].isDigit() && (input.toInt(&ok, 10) <= 31)
&& input[3].isDigit()
&& input[4].isDigit() && (input.toInt(&ok, 10) <= 12)
&& input[6].isDigit()
&& input[7].isDigit()
&& input[8].isDigit()
&& input[9].isDigit() && (input.toInt(&ok, 10) <= 2020)
// && (pos == 1 )&& (input.toInt(&ok, 10) <= 3)
// && (pos == 2 )&& (input.toInt(&ok, 10) <= 31)
)
return Acceptable;
if(input.size() > 10)
return Invalid;
if((pos == 1 )&& (input.toInt(&ok, 10) <= 3) && input[0].isDigit())
{return Intermediate;}
if((pos == 2) && (input.toInt(&ok, 10) <= 31) && input[pos-1].isDigit())
{return Intermediate;}
if((pos == 3) && (input.toInt(&ok, 10) <= 1) && input[pos-1].isDigit())
{return Intermediate;}
if((pos == 4) && (input.toInt(&ok, 10) <= 1) && input[3].isDigit())
{return Intermediate;}
if((pos == 5) && (input.toInt(&ok, 10) <= 12) && input[4].isDigit())
{return Intermediate;}
// if((pos == 6) && (input.toInt(&ok, 10) <= 999999) && input[pos-1].isDigit())
// {return Intermediate;}
if((pos == 7) && (input.toInt(&ok, 10) <= 9) && input[6].isDigit())
{return Intermediate;}
if((pos == 8) && (input.toInt(&ok, 10) <= 99) && input[7].isDigit())
{return Intermediate;}
if((pos == 9) && (input.toInt(&ok, 10) <= 999) && input[8].isDigit())
{return Intermediate;}
if((pos == 10) && (input.toInt(&ok, 10) < 99999) && input[9].isDigit())
{return Intermediate;}
if (input[0] == '.' )
{return Intermediate;}
if(pos > 1)
{
if (input.isEmpty()) return Intermediate;
if((pos > 1) || (pos <=2 ) && (input[pos-1] == '.'))
return Intermediate;
if(pos > 8 && pos <= 10 && input[pos-1].isDigit())
{return Intermediate;}
else {return Invalid;}
}
}

You can use a regular expression to validate dd.mm.yyyy
Have a look at https://regex101.com/ for trying them out.
Something like the code below should get you started
#include <regex>
std::smatch match;
const std::regex ddmmyyyyRegExp(R"((([0-9]{2})\.([0-9]{2})\.([0-9]{4})))");
std::string dd;
std::string mm;
std::string yyyy;
if (std::regex_search(input, match, ddmmyyyyRegExp) && match.size() == 4)
{
dd= match.str(1);
mm= match.str(2);
yyyy= match.str(3);
}

I've been able to fix the code, but still I'm unable to check if the inputs are in a particular range. I'm trying to check if the date limit isn't more than 31 and month isn't greater than 12
ExampleValidator::ExampleValidator(QObject* parent)
: QValidator (parent)
{
}
ExampleValidator::~ExampleValidator()
{
}
QValidator::State ExampleValidator::validate( QString & input, int & pos ) const
{
if (input.isEmpty()) return Intermediate;
bool ok;
QString str;
str = input[pos-1];
if(pos > 0 && input[0] != '.')
{
if (input.isEmpty()) return Intermediate;
if(((pos == 1 )&& (input.toInt(&ok, 10) <= 9) && input[0].isDigit() && input.size() != 10))
{return Intermediate;}
if(((pos == 2) && (input.toInt(&ok, 10) <= 99) && input[1].isDigit() && input.size() != 10))
{return Intermediate;}
if(((pos == 3) && (input.toInt(&ok, 10) <= 999)) && (input[2].isDigit() || input[2] == '.') && input.size() != 10)
{return Intermediate;}
if((pos == 4) && (input.toInt(&ok, 10) <= 9999) && input[3].isDigit() && input.size() != 10)
{return Intermediate;}
if((pos == 5) && (input.toInt(&ok, 10) <= 99999) && input[4].isDigit() && input.size() != 10)
{return Intermediate;}
if(((pos == 6) && (input.toInt(&ok, 10) <= 999999)) && (input[5].isDigit() || input[5] == '.') && input.size() != 10)
{return Intermediate;}
if((pos == 7) && (input.toInt(&ok, 10) <= 99999999) && input[6].isDigit() && input.size() != 10)
{return Intermediate;}
if((pos == 8) && (input.toInt(&ok, 10) <= 999999999) && input[7].isDigit() && input.size() != 10)
{return Intermediate;}
if((pos == 9) && (input.toInt(&ok, 10) <= 999999999) && input[8].isDigit() && input.size() != 10)
{return Intermediate;}
if((pos == 10) && (input.toInt(&ok, 10) < 2020) && input[9].isDigit() && input[2] == '.' && input[5]=='.' )
{
return Acceptable;}
}
if(((pos == 1) && (input[0] == '.')) || ((pos == 2) && (input[1] == '.')))
{
return Intermediate;
}
else if (input.isEmpty()) {return Intermediate;}
}```

Related

Checking correctness of infix expression in c++

I read an infix expression from the file, how can I check if it is a true or false input? I can only do 1 such case. I can think many situations but I don't know how to check in c++. Everyone please help me. Thanks very much!
int32_t check_error(string& str)
{
unsigned len = str.length();
if (str[0] != '(' || str[len-1] != ')')
{
return -1;
}
for (unsigned i = 3; i < len-3; i++)
{
if (str[i] >='0' && str[i] <= '9' && str[i + 1] = ' ' && str[i + 2] >= '0' && str[i + 2] <= '9')
return -2;
if ((str[i] == '+' || str[i] == '-' || str[i] == '*' || str[i] == '/' || str[i] == '%' || str[i] == '^') && (str[i - 2] < '0' || str[i - 2]>'9' || str[i + 2] < '0' || str[i + 2]>'9'))
return -3;
if (str[i] == ' ' && str[i + 1] == ' ')
return -4;
}
return 0;
}

Process all elements in map based on multiple conditions

I have the following data structure:
struct Data
{
int p1;
int p2;
int p3;
int size;
};
I need to sum size of all elements in map based on p1, p2 and p3 parameters. Here is an example code:
std::unordered_map<int, Data> m;
m[1] = Data{ 11, 22, 33, 10 };
m[2] = Data{ 33, 22, 11, 15 };
m[3] = Data{ 55, 55, 55, 25 };
int p1 = -1, p2 = 22, p3 = -1;
int size = 0;
for(const auto [key, data]: m)
{
if ((p1 >= 0) && (p2 >= 0) && (p3 >= 0))
{
if ((p1 == data.p1) && (p2 == data.p2) && (p3 == data.p3))
{
size += data.size;
}
}
else if ((p1 >= 0) && (p2 >= 0) && (p3 < 0))
{
if ((p1 == data.p1) && (p2 == data.p2))
{
size += data.size;
}
}
else if ((p1 >= 0) && (p2 < 0) && (p3 >= 0))
{
if ((p1 == data.p1) && (p3 == data.p3))
{
size += data.size;
}
}
else if ((p1 < 0) && (p2 >= 0) && (p3 >= 0))
{
if ((p2 == data.p2) && (p3 == data.p3))
{
size += data.size;
}
}
else if ((p1 < 0) && (p2 < 0) && (p3 >= 0))
{
if (p3 == data.p3)
{
size += data.size;
}
}
else if ((p1 < 0) && (p2 >= 0) && (p3 < 0))
{
if (p2 == data.p2)
{
size += data.size;
}
}
else if ((p1 >= 0) && (p2 < 0) && (p3 < 0))
{
if (p1 == data.p1)
{
size += data.size;
}
}
else
{
size += data.size;
}
}
As you can see map items are matched based on p1, p2 and p3 values. The size sum equals 25 for the above parameters. Is it possible to simplify that code using c++17/stl features ?
If I understand correctly, you can highly simplify your for range loop as follows
for ( auto const & [key, data] : m )
if ( ((p1 < 0) || (p1 == data.p1))
&& ((p2 < 0) || (p2 == data.p2))
&& ((p3 < 0) || (p3 == data.p3)) )
size += data.size;
If you prefer, you can use std::for_each(), including <algorithm>
std::for_each(m.cbegin(), m.cend(), [&](auto const & p)
{ if ( ((p1 < 0) || (p1 == p.second.p1))
&& ((p2 < 0) || (p2 == p.second.p2))
&& ((p3 < 0) || (p3 == p.second.p3)) )
size += p.second.size; });
but I don't see advantages over the preceding solution.

Optimize/Reduce condition expression in if statement

The goal is to optimize big condition expression by finding values dependencies between variables in order to reduce the logical OR statements.
Let's say we have the following condition:
if((A == 0 && B == 0) || (A == 0 && B == 1) || (A == 0 && B == 2) ...
a certain number of time...
Is there a way to reduce this kind of example by having automatically the following condition:
if(A == 0 && (B >= 0 && B <= 2))
The numbers involved in the first condition are only known just before the condition, it can't be typed manually. There can be also hundreds of logical OR operators involved in the condition. There can be gap between values (maybe use of % operator is needed) but there is always a pattern.
Any library or existing algorithm which can find the dependencies between the variables ?
Let's have another example:
if((A == 0 && B == 0) || (A == 0 && B == 2) || (A == 0 && B == 4)
can be translated to:
if((A == 0 && B%2 == 0)
One more:
if((A == 0 && B == 0 && C == 0) || (A == 0 && B == 2 && C == 0) || (A == 0 && B == 4 && C == 0) || (A == 0 && B == 0 && C == 1) || (A == 0 && B == 2 && C == 1) || (A == 0 && B == 4 && C == 1))
would be transformed into:
if(A==0 && B%2==0 && C>=0 && C<=1)
For the variables involved, I have all the values per terms.
I have something like [[0,0,0],[0,2,0],[0,4,0],[0,0,1],[0,2,1],[0,4,1]] (e.g. the last example)
Thanks for your time and answers !
if((A == 0 && B == 0) || (A == 0 && B == 2) || (A == 0 && B == 4)
cannot be translated to
if((A == 0 && B%2 == 0)
cuz
B == 6
and etc

Azure SQL - Code works locally but not on Azure

We are trying to check a scenario before displaying a pop-up message. The code below works great from Visual Studio but not from Azure after being published. Both are pointing to the same Azure SQL database.
PTO objPTOExist = db.PTOes.Where(p =>
(p.UserId == model.UserId && p.StartDate <= model.StartDate && model.StartDate <= p.EndDate && p.PTOId != model.PTOId)
|| (p.UserId == model.UserId && p.StartDate <= model.EndDate && model.EndDate <= p.EndDate && p.PTOId != model.PTOId)
|| (p.UserId == model.UserId && model.StartDate <= p.StartDate && p.StartDate <= model.EndDate && p.PTOId != model.PTOId)
|| (p.UserId == model.UserId && model.StartDate <= p.EndDate && p.EndDate <= model.EndDate && p.PTOId != model.PTOId)
|| (p.Name == "Holiday" && p.StartDate <= model.StartDate && model.StartDate <= p.EndDate && p.PTOId != model.PTOId)
|| (p.Name == "Holiday" && p.StartDate <= model.EndDate && model.EndDate <= p.EndDate && p.PTOId != model.PTOId)
|| (p.Name == "Holiday" && model.StartDate <= p.StartDate && p.StartDate <= model.EndDate && p.PTOId != model.PTOId)
|| (p.Name == "Holiday" && model.StartDate <= p.EndDate && p.EndDate <= model.EndDate && p.PTOId != model.PTOId)
).FirstOrDefault();
I know I can make the code simpler but that also had bad results on Azure even though it works locally.
Thank you for any insight as to why Azure behaves differently.

What is wrong with my logic?

if(location[0] <= 'H' || location[0] >= 'A'
&& location[1] <= 8 || location[1] >= 1)
I am checking to see if the first indice is between 'A' and 'H' and the second indice is between 1 - 8.
so the argument would = 1 if the user entered { A, 1 }
-1 if the user entered { J, 1 }
And (&&) has higher precedence than or (||), so to express what you want you need:
if ((location[0] <= 'H' || location[0] >= 'A') && (location[1] <= 8 || location[1] >= 1))
Otherwise what's happening is that it does the equivalent of this:
if (location[0] <= 'H' || (location[0] >= 'A' && location[1] <= 8) || location[1] >= 1)
Which is clearly not what you intended.
You can put as many expressions in the condition as you want, but you must remember the precedence rules; I suggest always using extra parentheses for clarity.
As Jeremiah has pointed out in the comments, the condition still wouldn't be doing what you wanted -- you are asking if something is in a given range by checking if it's either less than the upper bound or greater than the lower bound (this covers all input), when you intended to check whether the input was both larger than the lower bound and smaller than the upper:
if (location[0] <= 'H' && location[0] >= 'A' && location[1] <= 8 && location[1] >= 1)
In this case, since the operators are all &&, no extra parentheses are needed, though you can add them for extra clarity.
You need &&s not ||s. For example: 'Z' >= 'A' || 'Z' <= 'H' is true.
if(location[0] <= 'H' && location[0] >= 'A' && location[1] <= 8 && location[1] >= 1)
While not necessary in this case, you should group your logic together with parenthesis (and if they were ||s you would have to for it to work as expected):
if((location[0] <= 'H' && location[0] >= 'A') && (location[1] <= 8 && location[1] >= 1))
Add parenthesis to group the conditions:
if( (location[0] <= 'H' || location[0] >= 'A') && (location[1] <= 8 || location[1] >= 1))
If location[0] was equal to 'J' (definitely NOT between 'A' and 'H'), your if-clause would be TRUE because even though location[0] <= 'H' is FALSE, location[0] >= 'A' is TRUE and you are using || (OR). The problem is that you are using || (OR) instead of && (AND). You need to use all && (AND) in the if-clause.
&& has higher precedence than ||. So, you may want to write it as
if((location[0] <= 'H' || location[0] >= 'A') && (location[1] <= 8 || location[1] >= 1))
If you already tried this, please tell what error you got
Sorry guys, new here. I should have posted my entire method. Thank you for explaining the precedence of the operators, but my issue was that I was comparing a char with an int. All I needed to do was put ' ' around my numbers.
void GameBoard::enterShips()
{
char location[2];
int ships = 0;
int count = 1;
while( ships < NUM_SHIPS )
{
cout << "Enter a location for Ship " << count << ": ";
cin >> location[0];
cin >> location[1];
cout << endl;
if((location[0] <= 'H' && location[0] >= 'A') && (location[1] <= '8' && location[1] >= '1'))
{
location[0] = location[0] - 64;
location[1]--;
Grid[location[0]][location[1]] = SHIP;
ships++;
count++;
}
else
{
cout << "Wrong coordinates entered. Try again." << endl << endl;
}
}
}
As you can see in this operator precedence table, && is #13. It's higher up than ||, which is #14.
Therefore:
if(location[0] <= 'H' || location[0] >= 'A'
&& location[1] <= 8 || location[1] >= 1)
Is equivalent to:
if(location[0] <= 'H' || (location[0] >= 'A'
&& location[1] <= 8) || location[1] >= 1)
You want:
if((location[0] <= 'H' || location[0] >= 'A') &&
(location[1] <= 8 || location[1] >= 1))
Or even better:
if(((location[0] <= 'H') || (location[0] >= 'A')) &&
((location[1] <= 8) || (location[1] >= 1)))
I always put brackets around everything except when */ and +- are concerned. Even if you memorize the table, you shouldn't assume others do.
It helps code readability and helps prevent bugs... even compiler bugs! Triple bonus. :)
EDIT: Ah, you want ALL of them to be true. Just use all &&s, then! This works:
if(((location[0] <= 'H') && (location[0] >= 'A')) &&
((location[1] <= 8) && (location[1] >= 1)))