I'm increasing a pointer and decreasing a counter in a while loop. I want to exit the loop when the counter reaches zero or the pointer is equal to a max point (IF present). That if part is giving me the problem.
Consider the following:
char * pIt = utf8str;
char ** pEnd = 0;
size_t nVal = 10;
while ( 0 < nVal && (pEnd && pIt < *pEnd || true) )
{
--nVal;
++pIt;
}
If pEnd is null, I want it to be excluded from the comparison so pIt will have no upper bound. Obviously the above code doesn't work since when pIt >= pEnd the 'or' comes into play and will always be true.
How would one do this?
Ok let's deconstruct your condition a bit. So at the top level we have two parts the counter and the iterator and both conditions must be met to continue so we have:
A && B
Now A, is the simplest and thats: nVal > 0 (it's more natural at least for me to have what I'm comparing to on the right side).
Now be is a little bit trickier. Either pEnd is null and pIt has no upper bound, or pEnd exists. Which means B == C || D. So let's sub.
A && (C || D)
Now, if pEnd is null we want it to be true right? null is false, so we want true when false so what do we do ? !pEnd. That gives us C.
Finally we have D. Which is the case where pIt has an upper bound. pIt < *pEnd.
Let's put this all together and we have:
nVal > 0 && (!pEnd || (pIt < *pEnd))
Hope this helps!
How about:
while ( 0 < nVal && (!pEnd || pIt < *pEnd) )
If you are used to reading the ternary operator, this is pretty clear:
while (0 < nVal && (pEnd ? pIt < *pEnd : true))
Just:
((pEnd == NULL) || (pIt < *pEnd))
This is not intended as an answer but as a comment with code. Shakes fist at SOs lousy comment-code options
When you run into a brain-bending logic issue and sleeping on it is not an option, deconstruct with a for(;;) loop.
for (;;) {
if (nVal <= 0)
break;
if (pEnd == nullptr) {
// logic test you want here
}
--nVal;
++pIt;
}
Related
I am working through the "Add Binary" problem on leetcode and a solution which I found online is the following:
#include <string>
using std::string;
class Solution {
public:
string addBinary(string a, string b) {
string ret;
bool carry{false};
for (auto apos=a.size(), bpos=b.size(); apos || bpos || carry; ) {
bool abit{apos && a[--apos] == '1'};
bool bbit{bpos && b[--bpos] == '1'};
ret = (abit ^ bbit ^ carry ? "1" : "0") + ret;
carry = abit + bbit + carry >= 2;
}
return ret;
}
};
My question is regarding the for loop above. I understand that two iterations are being instantiated with the first two expressions that are separated by a comma. However, I don't understand how the three units being or'd (ie: ||) is supposed to behave. I'm also curious why it's ok to exclude the iterator expression in this instance, ie the final expression in the for-loop.
Please help me to understand how this code functions.
basically the for loop consist of 3 parts separted by ';'(semi-colon)
1)first part, this part is about initialization of variables, again you can leave it if you want
2)second part, it defines the condition on basis of which for loop will keep running, again you can leave it if you want
3) third part, this is the part where you want to do some operations, conventially iteration value is increment, but again you can leave it if you want
so if you go with this model, I think you can easily break down what is happening in the for loop that you mentioned.
Sometimes it helps to consider the equivalent while loop:
for (auto apos=a.size(), bpos=b.size(); apos || bpos || carry; /*no increment*/) {
// ...
}
->
{
auto apos = a.size();
auto bpos = b.size();
while( apos || bpos || carry ) {
bool abit{apos && a[--apos] == '1'};
bool bbit{bpos && b[--bpos] == '1'};
ret = (abit ^ bbit ^ carry ? "1" : "0") + ret;
carry = abit + bbit + carry >= 2;
/* increment would be here*/
}
}
The loop initializes apos and bpos and continues to loop as long as the condition apos || bpos || carry yields true, ie as long as apos, bpos and carry are not all 0 (0 is converted to false any other number to true).
Any idea why the else if statment will be never executed ? The value of difference is constantly changing when the program runs.
double difference = abs(reale_x[0] - reale_x[1]);
if (0 <= difference < 45) {
timer_counter += 1;
if (timer_counter == 30) {
cout << "CLICK" << '\n';
}
}
else if (difference > 50) {
timer_counter = 0;
}
That is not how comparation works in c++.
What this code
if (0 <= difference < 45) {
does is it first compares if 0 is smaller or equal to difference. It is then "replaced" by a bool value either true or false. And then a bool value (so either 1 or 0) is compared to 45. And it will always be smaller than 45. What you have there is an always true statement.
So the way you would write this if statement is
if (difference >= 0 && difference < 45){
Note that because of your else if statement it will not execute if the difference is >44 and <51
if (0 <= difference < 45) will be executed as if ((0 <= difference) < 45), which will be either 0<45 or 1<45 and will always be true. That's why the else part is not getting executed.
in mathematics, we see and write 0 <= x < 45 or something like that to define the range of the variable x. But in order to tell the computer the same thing, you have to tell more clearly. Saying, to have to tell the compiler, that the value of x is greater than or equal to zero and at the same time, that value will be less than 45, and you can tell the compiler by this statement: difference >= && difference < 45 . the && is an 'AND' operator in most of the languages.
I would like to avoid incrementing and decrementing in if-statement since there is a segmentation fault error in the following code while checking conditions (if we start with p = 1 and k = 1 for example):
if (((heights[k--][p--] < heights[k][p]) || (heights[k--][p--] == heights[k][p])) &&
((heights[k--][p++] < heights[k][p]) || (heights[k--][p++] == heights[k][p])) &&
((heights[k++][p--] < heights[k][p]) || (heights[k++][p--] == heights[k][p])) &&
((heights[k++][p++] < heights[k][p]) || (heights[k++][p++] == heights[k][p]))){
width[k][p] = 3;
}
For example, the second check fails with k = -1.
I would like to check neighbouring elements of a two-dimensional array heights in an if-statement and than run some logic in case it was true.
How can I optimise it and generally rewrite it to make it look (and work) better? I haven't found any information on it.
As others have indicated, replacing 'k--' with 'k-1' and 'k++' with 'k+1' for all 'k' and 'p' variables may resolve the segmentation error. 'k+1' is a reference to the next array index after 'k', while 'k++' increments the value of 'k' after it's used. It's also good programming practice to avoid using expressions as arguments.
https://en.cppreference.com/w/cpp/language/operator_incdec
To clean up the code, you could also simplify the logical OR by replacing '<' with '<='.
if ((heights[k-1][p-1] <= heights[k][p]) &&
(heights[k-1][p+1] <= heights[k][p]) &&
(heights[k+1][p-1] <= heights[k][p]) &&
(heights[k+1][p+1] <= heights[k][p])){
width[k][p] = 3;
}
Running my app through callgrind revealed that this line dwarfed everything else by a factor of about 10,000. I'm probably going to redesign around it, but it got me wondering; Is there a better way to do it?
Here's what I'm doing at the moment:
int i = 1;
while
(
(
(*(buffer++) == 0xffffffff && ++i) ||
(i = 1)
)
&&
i < desiredLength + 1
&&
buffer < bufferEnd
);
It's looking for the offset of the first chunk of desiredLength 0xffffffff values in a 32 bit unsigned int array.
It's significantly faster than any implementations I could come up with involving an inner loop. But it's still too damn slow.
I'd go for the search_n suggestion, too, because I'm pretty sure it does this properly. It's actually pretty easy, and it can be sped up basically by a factor of desired_length. unless the target values are really dense in the array.
Here's the idea: if you have K consecutive instances of a value starting at position I, then it must be the case that position I + K - 1 contains that value. So you check that first; if it doesn't, then the earliest position which might contain the K consecutive values is I + K, so you can restart the algorithm there.
If, on the other hand, you find the value at I + K - 1, then you scan backwards until you either reach I (in which case you succeeded), or you reach some position J - 1 which doesn't contain the target value. In the latter case, you know there are target values from J to I + K - 1, so you now check J + K - 1. If that works, you only have to scan backwards to I + K. If it doesn't work, you restart the algorithm at J + K.
Most of the time, you'll only look at every K'th position in the vector. For large K, that's a big win.
You tagged c++ so I assume you have STL algorithms available:
std::search_n(buffer, bufferEnd, desiredLength, 0xffffffff);
Try to use memcmp from C standard library. Modern compilers shall have very optimized implementations of memxxx functions making the most speed out of modern CPUs.
Just a thought but you're iterating over the int array one at a time right? Think about this, if *(buffer) != 0xffffffff and buffer[desiredLength-1] != 0xffffffff then you can be sure that there's no point in checking in between so you can just move buffer on by desiredLength rather than just by 1 which may significantly improve your speed if desiredLength is much larger than one. Of course it complicates your function because:
If both *(buffer) and buffer[desiredLength-1] equal 0xffffffff then you can't assume it's contiguous between them so you'll still need to check that.
If *(buffer) doesn't equal 0xffffffff but buffer[desiredLength-1] does equal 0xffffffff then you've got to track to the beginning of the 0xffffffff sequence.
You've got to ensure you don't overrun the buffer when you check buffer[desiredLength-1]
A bit more complex but it may speed things up. Hope that makes sense.
If I want to implement this I will do it using memchr and memcmp:
bool found = false;
std::vector<unsigned char> tmp(desiredLength*sizeof(uint32_t), 0xFF);
while( true ) {
void* p = memchr(bufferStart, 0xFF,
(bufferEnd-bufferStart-desiredLength) * sizeof(uint32_t));
if( !p ) break;
if( !memcmp(p, &tmp[0], desiredLength * sizeof(uint32_t)) ) {
found = true;
break;
}
}
Also you can use std::search_n that may be better optimized than your own code
For when std::search_n isn't available:
int i = 1;
while
(
(
i == 1
&&
buffer < bufferEnd
&&
(
(
*buffer == desired
&&
*(buffer + desiredLength - 1) == desired
&&
(i = 3)
)
||
(buffer += desiredLength && (i = 1))
)
)
||
(
i == 2
&&
(
(
buffer > arr
&&
(*(--buffer) == desired)
)
||
(i = 3)
)
)
||
(
i >= 3
&&
buffer < bufferEnd
&&
(
(
*(buffer++) == desired
&&
(i++ || true)
)
||
(i = 1)
)
&&
(
i < 3
||
i - 3 < desiredLength + 1
)
)
);
buffer -= i - 4;
if (buffer > bufferEnd - (i-3))
buffer = bufferEnd;
Returns identical results only slightly slower than std:search_n:
buffer = std::search_n(buffer, bufferEnd-1, desiredLength, desired);
if (buffer == bufferEnd-1)
buffer = bufferEnd;
I have an if statement that looks as follows:
int count=0;
string Check;
if ((count==4 && Check!="-s")||(count==4 && Check!="-S"))
If count equals 4 and Check equals "-s" or "-S" it still enters this if statement because of the count == 4. It totally seems to ignore the second part. Is there something I'm doing wrong?
It's always going to be the case that either Check!="-s" or Check!="-S". Hence, your if statement is equivalent to if (count==4).
Well, if Check is "-S", then it will not even check the second pair of conditions, because you check with ||. The same holds true for the opposite case. If one is false, the other is true. Replace that with a &&.
int count = 4;
string Check = "-S";
if( (count == 4 && // count is 4, alright.
Check != "-s") || // Check is "-S", alright I'm done thanks to || (OR)
(count == 4 &&
Check != "-S") )
{
// ...
}
int count = 4;
string Check = "-s";
if( (count == 4 && // count is 4, alright.
Check != "-s") || // Check is "-S", time to check the other condition pair...
(count == 4 && // count is 4, alright.
Check != "-S") ) // Check is "-s", which is different from "-S", perfect.
{
// ...
}
Now the corrected version:
int count = 4;
string Check = "-S";
if( (count == 4 && // count is 4, alright.
Check != "-s") && // Check is "-S", different from "-s", now on to the other condition!
(count == 4 && // count is 4, alright.
Check != "-S") ) // Check is "-S"... oh dang! No executed code for you.
{
// ...
}
If count == 4 and Check == "-s", then the expression to the right of the || is true. If count == 4 and Check == "-S", then the expression to the left of the || is true. So you have true or true which is true. Thus, your if-block is executed.
The right statement is:
if(count==4 && (Check != "-s" || Check!="-S"))
The statement that you wrote is true if you have count = 4 and Check = "-S" because then the first part of the OR is true.
Might be more clear to use:
if (count==4 && Check!="-s" && Check!="-S")
You should use !strcmp(Check, "-s") and !strcmp(Check, "-S") instead of !=.
If you use == you compare the pointers and that is no what you want. The pointers will always be different thus your second argument will always be true.
You want to enter the if body if and only if Check is != from either -s or -S and count is = 4 right?
if ( (Check!="-s" && Check!="-S") && count==4 )
should work.
or
if ( Check.tolower() !="-s" && count==4 )
should work.
(Do not remember the name of the function to lowercase a string, you have got to look it up)
Hope this help.