Avoiding incrementing in if statement in C++ - c++

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;
}

Related

Increment operator not working in while condition

I've written a while loop to increment a pointer until the content is a null byte or the difference between adjacent elements is greater than 1, and this has worked fine:
while (i[1] && *i + 1 == i[1]) i++;
Then I tried to rewrite it as:
while (i[1] && *(i++) + 1 == *i);
But in this way, it got stuck in an infinite loop, as if i was not being incremented. Why is this so?
Edit:
I must apologize for being misleading but I discovered now that it does not get stuck inside the while loop I showed you, rather it simply exits that while loop and instead gets stuck in its parent loop, let me just share with you the whole code:
char accepted[strlen(literal)+1];
strcpy(accepted, literal);
std::sort(accepted, accepted + strlen(accepted));
char *i = accepted-1;
while (*++i){
uint8_t rmin = *i;
//while (i[1] && *i + 1 == i[1]) i++;
while (i[1] && *(i++) + 1 == *i);
uint8_t rmax = *i;
ranges.push_back(Range{rmin, rmax});
if (!i[1]) break;//is this necessary?
}
My question is no longer valid.
And yes, "clever" unreadable code is a bad idea.
There are two problems in your code:
while (i[1] && *(i++) + 1 == *i);
The && operator uses short circuit evaluation, that is if the left part (i[1]) is 0, then the right part (*(i++) + 1 == *i) is never evaluated. That's the reason why your code loops indefinitely.
the expression *(i++) + 1 == *i yields undefined behaviour because the order of evaluation of the sub expressions left and right of the == is not specified.
It's usually not advised to write "clever" code. Write readable code and let the compiler take care of optimizations.

How to remove empty (or filled with incorrect data) fields

As I have read, the C++ compiler initialize table with the random data, before I initialize it by myself.
I've got a program which after performing (for example) give me this output - char table.
{'D','K','2','EMPTY FIELD','1','+','EMPTY FIELD','EMPTY FIELD','3','EMPTY FIELD','/'}
Now I would like to delete whole inconvenient data like letters, and empty fields.
I'm trying to achieve this by this code, but I think it transfer it into ASCII code. Am I able to achieve this in another way ?
char wynik[20];
int j = 0;
for (int i = 0; i <20; i++)
{
if (wyjscie[i] == '+' || wyjscie[i] == '-' || wyjscie[i] == '/' || wyjscie[i] == '*' || (wyjscie[i] >-241241 || wyjscie[i] < 2141242142 ))
{
wynik[j] = wyjscie[i];
j++;
}
}
(wyjscie[i] >-241241 || wyjscie[i] < 2141242142 ) is your problem. You're confusing the integer values represented by a character and the integer codes of characters. If you want to check if a character c is between 0 and 9 you could do c >= '0' && c <= '9'.

Is condition evaluation optimized ? Is this code bad?

1.Imagine condition if (obj.is_x() || obj.is_y() || obj.is_z())
Will obj.is_y() and obj.is_z() be called and evaluated if obj.is_x() returned true ?
2.Is this a bad idea(in general)? Does this code look bad ?
bool isbn13_prefix_valid (const string& prefix)
{
unsigned num = stoi(prefix);
if (num == 978 || num == 979) return 1; //super common ones
else if ( num >= 0 && num <= 5 || num == 7 || num >= 600 && num <= 649
|| num >= 80 && num <= 94 || num >= 950 && num <= 989
|| num >= 9900 && num <= 9989 || num >= 99900 && num <= 99999)
return 1;
return 0;
}
No, it will not, due to short-circuiting.
Yes, that code looks bad. Not because it's incorrect, but because you're stuffing an extremely long conditional into a single if statement. Try refactoring your code to make it cleaner.
Your code is absolutely fine. I'd like to see a comment where these strange numbers come from, that's all.
Turning it into a dozen trivial functions as has been suggested is in no way helpful. It actually makes it a lot harder to read the code, because it gets spread out over many many lines of code. Yes, it is complex. But that's due to the problem being complex, and trying to spread the complexity out doesn't help one bit.
Your actual question: In a || b, a is evaluated first. If it is true, then b is not evaluated and the result is true. If a is false, then b is also evaluated and the result is true or false, depending on the result of b.
An optimising compiler may start evaluating b before it has finished evaluating a, if it can prove that the evaluation of b has no side effects, and if it believes that (mostly due to parallelism in the hardware) it is on average faster to evaluate as much in parallel as possible, even if some things are evaluated when it wasn't necessary. But this is not noticable in the results of your code, and will only make the code faster.

c++ validate range of characters [closed]

Closed. This question does not meet Stack Overflow guidelines. It is not currently accepting answers.
This question appears to be off-topic because it lacks sufficient information to diagnose the problem. Describe your problem in more detail or include a minimal example in the question itself.
Closed 8 years ago.
Improve this question
I'm writing a function that is passed a character as the first argument and an integer as the second. I need to validate both simultaneously. Specifically, the character must be between A and J (including A and J), and the integer must be between 1 and 10 (including 1 and 10).
The line I wrote is:
if (toupper(row) < 'A' || toupper(row) > 'J' || col < 1 || col > 10)
{
return 0;
}
else
{ ... rest of function ... }
but this is not working correctly. In my book I read that you could perform comparisons with characters because they really are just integers themselves, but I can't figure out why ths won't work. Could anyone point me in the right direction?
Edit to address some comments
0 is the number we're supposed to return if the input is not valid.
This line of code is part of a project that is being graded by a "test driver" that my teacher wrote. The test driver is reporting that my function is not returning the correct result when the input is invalid (character that is not between A or J, or a number that is lower than 1 or greater than 10).
I structured my code so that if the statement above is true, then it returns the code we were supposed to return, otherwise it proceeds with the rest of the function... So I can't figure out why his test driver is telling me that I'm not returning the code when given invalid input. The other problem is he doesn't let us see what the test driver is sending to our function, so I have no way of trouble shooting this.
I think that you shouldn't use toupper. Why?
Because maybe your professor use invalid input like:
a, 5
and you shouldn't allow lower cases to pass your test.
So in the end your if statement:
if ((row >= 'A' && row <= 'J') && (col > 0 && col < 11))
From your post it is not clear what does not work. You wrote if statement without any compound statement. So what is the criterion that something is wrong?!
For example you could write
if (toupper(row) < 'A' || toupper(row) > 'J' || col < 1 || col > 10) return false;
Take into account that negation of expression
if ((toupper(row) >= 'A' && toupper(row) <= 'J') && (col > 0 && col < 11) )
as it is written by #Ardel is equivalent to
if ( !( ( toupper(row) >= 'A' && toupper(row) <= 'J') && (col > 0 && col < 11 ) ) )
that in turn is equivalent to
if ( !( toupper(row) >= 'A' && toupper(row) <= 'J') || !(col > 0 && col < 11 ) ) )
that is equivalent to
if ( !( toupper(row) >= 'A' ) || !( toupper(row) <= 'J') || !(col > 0 ) || !( col < 11 ) )
that is equivalent to
if ( toupper(row) < 'A' || toupper(row) > 'J' || col <= 0 ) || col >= 11 )
that is at last equivalent to
if (toupper(row) < 'A' || toupper(row) > 'J' || col < 1 || col > 10) return false;
That is your original expression.
So there is no any sense in your post and in the answer of #Ardel.
So I do not understand for example why the answer of #Ardel was uo voted. Maybe it was up voted by whose who is unable to do such conversions as the negation of boolean expressions?:)
I can suppose (moreover after thinking about I am sure) that you should not apply function toupper to the character. For example
if ( row < 'A' || row > 'J' || col < 1 || col > 10) return 0;
The other problem is that you did not say what the function shall do if this condition will be passed successfuly. Maybe inside the function body you should reassign row the following way
row -= 'A';
that to use it as integer value between 1 and 10 inclusively.

while loop excluding a condition

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;
}