bubble sort algorithm for loop statement warning - c++

I saw a piece of bubble sort code and initially I thought the code is wrong. But after compile and run, it surprised me that it actually works. I want to know how come second statement in the first for loop is not a condition but an assignment. In addition, how come this code will not go into infinitely loop?
PS: It will generate an warning: "suggest parentheses around assignment used as truth value [-Wparentheses]" complaining about the first for loop. Surprisingly it's not an error.
#include <iostream>
void bubblesort(int A[], int n)
{
for (bool sorted = false; sorted = !sorted; n--)
{
for (int i = 1; i < n; ++i)
{
if (A[i-1] > A[i])
{
int tmp = 0;
tmp = A[i];
A[i] = A[i-1];
A[i-1] = tmp;
sorted = false;
}
}
}
}
int main()
{
int a[5] = {1,4,5,2,3};
bubblesort(a, 5);
for (unsigned int i = 0; i < 5; ++i)
{
std::cout << a[i] << std::endl;
}
return 0;
}

The result of an assignment is the left operand, so the condition
sorted = !sorted
is using sorted as the condition after it's assigned a new value. The warning is there to give you a notice that using assignment as condition is sometimes not what you expected. You can use
(sorted = !sorted) == true
to silence the warning.

It's one of the quirks of C and C++ that they allow an assignment in the middle of a statement. Usually it's an error (= instead of ==) so a good compiler will warn you about it.
The value of such an expression is the same as the assigned value.
In this case it's a very tricky optimization; if the value was false it's reset to true and the loop continues, if it was true then it becomes false and the loop termination condition is met. I would never use this in code that anybody was expected to maintain.

An explanation for the code. Basically, if sorted ever is true before the condition the loop will stop.
1st loop: sorted is true
Within the second for loop, it basically checks if the array is sorted. If it isn't sorted -> false and the loop continues. If it is, sorted-> true and execution stops.

The comparision normally is as follows:
sorted != sorted
Of course, this does not make any sense. But instead, you have the following:
sorted = !sorted
By doing this, you just negate the condition for sorting, meaning that the array, which is unsorted, is assumed to be sorted. Then, if you traverse the complete array without making any swap, the left side of the assignment is taken as a condition (which in this case is true).

Related

in a for loop, does the variable used in the condition get checked at every iteration, or only the first?

I want to run a loop on a std::vector<std::vector<int>> array to delete desired elements.
I'm using for (i = 0; i < array.size(); i++)
is it safe to invoke array.erase() from within the loop?
In my head I assume for checks array.size() at every iteration, but maybe it only does it once at initiation. If it did, for (i = 0; i < &array.size(); i++) would work a fine solution, would it not?
Thank you.
is it safe to invoke array.erase() from within the loop?
Yes, it is perfectly safe. Compiler is allowed to optimize the check by calling array.size() only once out of the loop only if it can prove that vector is not modified inside the loop, e,g, if the vector is constant and thus not modifiable. In that case optimizing that way won't change observable behavior. But since you are calling erase inside the loop compiler is not allowed to call array.size() only once.
In general, an implementation is allowed to do only those code transformations that do not change observable behavior. This is called as-if rule.
I'm using for (i = 0; i < array.size(); i++)
is it safe to invoke array.erase() from within the loop?
It is safe but it is going throw your iteration logic off.
Let's say you have {1 2 3 4 5} in array.
You removed 2 from the array. At that time, i is 1. After removing 2, array is now {1 3 4 5}. You increment i in the for statement, which makes i 2. You will end up accessing 4 from the array in the loop, which skips 3 altogether.
In my head I assume for checks array.size() at every iteration, but maybe it only does it once at initiation.
No, it does that check in every iteration of the loop.
If it did, for (i = 0; i < &array.size(); i++) would work a fine solution, would it not?
Not sure where you got that idea but it's wrong. Don't even go there.
You can use:
for ( i = 0; i < array.size(); /* Don't increment here */ )
{
// Code
// Check for erase.
if ( check-for-erase-logic )
{
// Erase item
// Don't increment iteration counter.
}
else
{
// Increment iteration counter.
++i;
}
}
i < array.size() is the condition part of the for statement which is evaluated before each iteration, and if it yields false, the loop is exited. This answers the question in your title.
However, erase will invalidate iterators. So you should be careful. It is better to use algorithms to achieve this. One way would be the remove/erase idiom.
In contrast to a range for loop aka for (T element : container), in normal loops the condition is checked every time. So yes your normal for loop is safe.
However be aware of iterator, references and pointer invalidation after erase, and also that your i could be outside of the new range after the erase
Here some do's and dont's
#include <iostream>
#include <vector>
int main() {
using T = std::vector<int>;
std::vector<T> vector{{3,4},{3,5},{5,9}};
for (size_t i = 0; i < vector.size(); ++i) {
auto &vec2 = vector.at(2);
if (i == 2) {
vector.erase(vector.begin() + 1); //fine}
}
auto &v = vector[i]; //NOT FINE UNDEFINED BEHAVIOUR!
if (i < vector.size()) //Could be optimized out by compiler because of UB!, when compiling with line above,
// as the for check
break;
std::cout << vec2.at(1); //Also UNdefined behaviour since many things are invalidated after erase
}
for (auto v : vector) {
vector.erase(vector.begin()); //Also NOT ALLOWED since for ranges are allowed to cache iterators
}
}

Simple recursive function to determine if two elements are transitively true

newbie here. Even newer to recursion. I'm writing a function for my C++ program, and as you'll be able to tell, I'm a bit clueless when it comes to recursive algorithms. I'd appreciate it greatly if someone could fix my function so I can get it working and perhaps have a better idea how to handle recursion afterward.
My function takes a two-dimensional square array of booleans, and integer i, and an integer array_size as parameters. The function returns a boolean value.
The array is an adjacency matrix that I use to represent a set of conditionals. For example, if the value at [0][3] is true, then 0 -> 3 (if 0, then 3). If [3][7] is true, then 3 -> 7 (if 3, then 7). By the transitive property, 0 -> 7 (if 0, then 7).
The integer i is a particular element in the set of conditionals. The function will return true if this element is transitively connected to the last element in the array. The last element in the array is the integer (array_size - 1),
The integer array_size is the size of each dimension of the square array. If array_size is 20, then the array is 20x20.
The idea of this function is to determine if there is any logical "path" from the first integer element to the last integer element by the transitive property. When the path exists, the function returns true, otherwise, it returns false. The recursive call should allow it to traverse all possible paths, returning true once it finally reaches the last element and false if all paths fail.
For example, if i = 0 and array_size = 10, then the function will return whether or not 0 -> 9 is valid according to the conditionals provided by the matrix and the transitive property.
This is my code so far:
bool checkTransitivity(bool **relations, int i, int array_size){
bool isTransitive = false;
if (i == array_size - 1)
{
isTransitive = true;
}
else
{
for (int j = i; j < array_size; j++){
if (relations[i][j])
{
isTransitive = checkTransitivity(relations, j, array_size);
}
}
}
return isTransitive;
Currently, the function returns true for all input.
Any help at all is appreciated. Thanks in advance!
EDIT: This first part is unnecessary because of your if-else statement. Move on to END OF EDIT.
Let's start with what a base case in a recursive function is:
if (i == array_size - 1)
{
isTransitive = true;
}
Well you do have a base case, but nothing is being returned. You are just setting a flag to true. What you want to do is:
if (i == array_size - 1) {
return true;
}
Now the function will work its way up the recursive stack to return true. END OF EDIT.
But we still need to fix the recursive case:
else {
for (int j = i; j < array_size; j++) {
if (relations[i][j]) {
isTransitive = isTransitive || checkTransitivity(relations, j, array_size);
}
}
}
return isTransitive;
The || means binary OR. So you have the logic right. You want to check each possible path to see if it can get there, but by setting isTransitive to the result of each check, isTransitive is only going to be set to the last call. By doing isTransitive = isTransitive || recursive call, isTransitive will be true as long as one of the calls results in a true value.
The last thing I want to say is a caution: if relations[i][j] == true and relations[j][i] == true, your code will still be in an infinite loop. You must find a way to eliminate the potential backtracking. One way to do this is to create another array that stores which paths you have already checked so you do not infinitely loop.
More information can be found here: Depth First Search
I think all you need is a break condition to stop continuing the loop when you encounter a non-transitive item. See below (haven't tested)
bool checkTransitivity(bool **relations, int i, int array_size){
bool isTransitive = false;
if (i == array_size - 1)
{
isTransitive = true;
}
else
{
for (int j = i; j < array_size; j++){
isTransitive = relations[i][j] && checkTransitivity(relations, j, array_size);
if (!isTransitive)
break;
}
}
return isTransitive;
}

It is safe to use i+1 in O(n) searching?

I'm asking myself if it is safe to use i+1 to check if the next number is the same as current... Example :
int search(int el, int* a, int n) {
if(a == NULL && n<0)
{
return NULL;
}
for(int i=0; i<n; i++)
{
if((a[i] == el )&& (a[i+1] != el)) // here I check next element
{
return i; // if I find it, return a position.
}
}
return -1; // else return -1
}
If we have an array with length 4, then a[i+1] will be passed an array length, but program will still work.
No, accessing elements out of bounds is Undefined Behavior.
Your program may "seem" to work, but you cannot expect anything out of it. It could work on your machine, and crash on another one. Or it could work on all machines now, but not tomorrow. You should check if the index is out-of-bounds before using the subscript operator.
You may consider changing your cycle so that it never accesses out-of-bounds elements:
for (int i = 0; i < n - 1; i++)
// ^^^^^
Then, you would have to take care of the last element in the array separately, as a special case.
That's not correct, when i reaches its last value (n-1) you check the value of a nonexistent element (the C standard allows you to have a pointer to one-after-last element, but not to dereference it).
You can fix your code like this:
if((a[i] == el ) && ((i == n-1) || (a[i+1] != el)))
If n is the last element in the array, then i + 1 is safe in this case. If n is the number of elements in the array, i + 1 may appear to work most of the time, but it is not safe.
In that case, you're accessing an element outside the bounds of the array, which may do anything from giving you incorrect results to crashing your program. Most of the time it will appear to work, though, making the problem very hard to debug when it happens.
It is not clear to me what you're asking. Even if array access is expensive, accessing both a[i] and a[i+1] remains of O(N) complexity. What you can't do is adding complexity that's based on i (for example an additional loop from 0 to i), or modifying i (for example decrementing it based on some condition).
The problem, as others have already pointed out, is that the last element is compared to a nonexistent datum: either you'll get an error and a possible crash, or the program will appear to be working - and actually work most of the time - until the time where that unknown and possibly random last-and-one item will trigger the comparison, and yield an unexpected result.
You should check that the array size is at least 1 (that ought to be a special case anyway, can't run a compare on a single element!) and then loop only up to n-1. Or you could save the previous value in a temporary variable; depending on the platform, this will be a (possibly much faster) register, or a (possibly much slower) stack location. In most cases I'd just state my intention of comparing with the next element, as you did, and let the compiler sort it out.
No.
int main(void)
{
char pumpkin[8];
int a[4];
int i, p;
a[0] = 3760;
a[1] = 100001;
a[2] = 595959;
a[3] = 1886221680;
pumpkin[0] = 'p';
pumpkin[1] = 'u';
pumpkin[2] = 'm';
pumpkin[3] = 'p';
for (i = 0; i < 4; i++) {
p = search(a[i], a, 4);
if (p >= 0)
printf("Found it at position %d: %d.\n", p, a[i]);
else
printf("Value not found.\n");
}
return 0;
}
In my machine:
$ gcc -std=c11 -o boundserror boundserror.c
$ ./boundserror
Found it at position 0: 3760.
Found it at position 1: 100001.
Found it at position 2: 595959.
Value not found.
What happened ? Compiler wrote value 1886221680 both in a[3] and where a[4] would be if it existed. About the program working on your machine: read about the works on my machine concept.
http://www.codinghorror.com/blog/2007/03/the-works-on-my-machine-certification-program.html

C++ Sieve of Eratosthenes finding 3 too many primes

I have a programming assignment to write a program in C++ that finds all primes less than n (user input). One half of the assignment involves the Sieve of Eratosthenes. My code is working (read: assignment is complete), but before I edited the output, it was unconditionally printing out n-3, n-2, and n-1 as primes even if they were not prime. I'm not sure why this is happening. I'd appreciate a bit of feedback and ideas as to why the program is acting the way it is. Here is the unaltered code:
Please note that I am using a ListNode class and a LinkedList class, both of which are fully functional. EDIT: partial main added; notice the second item in the for loop is size-3. If it's left at size, the program outputs 3 extra non-primes.
int main()
{
for(int i = 0; i<my_list.size()-3; i++)
{
if(marked[i]==true)
cout<<my_list[i]<<"\n";
}
}
void eratosthenes(int item)
{
bool run=true;
int p=2, count=0;
for(int i=2; i<=item; i++)
{
my_list.append(i); // Entire list is filled with integers from 2 to n
marked.append(true); // Entire list is filled with true entries
}
while(run==true&&(2*p)<item)
{
count = 0;
int i = (2*p);
do {
marked[i-2]=false; // marked values are false and not prime
i+=p;
} while(i<item-2);
for(int i=0; i<item-2; i++) // i starts at 0 and increments by 1
{ // each time through the loop
if(my_list[i]>p)
{
if(marked[i]==true) // If a value stored in a node is true
{ // (prime), it becomes the new p.
p=my_list[i]; // The loop is then broken.
break;
}
}
}
for(int j=1; j<item-2; j++)
{
if(marked[j]==false)
{
count=1;
}
}
if(count==0)
run=false;
}
Complete method
void Eratosthenes(int upperBound)
{
bool Prime[upperBound];
for(int i = 0;i<upperBound;i++)
Prime[i]=true;
for (int i = 2; i <= sqrt(upperBound); i++)
{
if (Prime[i])
{
for (int j = i * 2; j < upperBound; j += i)
Prime[j] = false;
}
}
for(int i=2;i<upperBound;i++)
{
if(Prime[i]==true)
cout<<i<<" ";
}
}
From your code:
do{
marked[i-2]=false;//marked values are false and not prime
i+=p;
}while(i<item-2);
This loop is responsible for going through all numbers i that are integer multiples of the prime number p and marking them not prime, as I understand. Why are you stopping on the condition i < item - 2? This would be fine if i were your index for the my_list and marked lists, but in this case it's not; it's the actual number you're marking not prime. I suspect this is why you're getting numbers near your limit (item) that are marked as prime—your loop here exits before i ever gets to those numbers!
By the way, you could do this as a for loop instead, which would be easier to read. The for loop has the meaning "go through each element in a set" (whether that's consecutive integers, or every nth integer, or elements in an array/list/deque, etc.), so a programmer reading your code knows that immediately and doesn't have to figure it out from your while loop.
// mark every multiple of the current prime as not prime
for(int i = 2*p; i < item - 2; i += p)
{
marked[i-2] = false;
}
(This is the same as your original code, no fixes applied).
Some general comments to improve your algorithm/code:
Try using more descriptive variable names. Your use of i two times to mean different things is confusing, and in general single letters don't mean much as to what the variable represents (although sometimes they're sufficient, e.g. a for loop where i is the index of a list/array).
Also, you're looping over your list a lot more than you need to. The minimum a sieve of Eratosthenes algorithm needs is two nested for loops (not including initializing a list/array to all true).
One example of where you're doing more work than necessary is that you're looping starting from index 0 to find the next p to use—instead of just remembering where your current p is and starting from there. You wouldn't even need to check my_list[i] > p in that case, since you know you'd be beyond it to start off. Also, your last loop could break; early and avoid continuing on after it finds a non-prime (and I'm not sure what the point of it is).
Nikola Mitev's second answer is a more efficient and more readable implementation of the sieve (but replace sqrt(upperBound) with upperBound/2 for it to work correctly; the reason for upperBound/2 should be pretty clear from the way the Sieve works), although he didn't really give much comment or explanation on it. The first loop is "go through every number up to upperBound"; inside it, "if the current number is a prime, go through all the multiples of that prime and mark them non-prime". After that innerloop executes, the outer loop continues, going through the next numbers—no need to start from the beginning, or even type out another for loop, to find the next prime.
EDIT: sqrt(upperBound) is correct. I wasn't thinking about it carefully enough.
Why don't you work with array of booleans for simplicity starting from index 2, and when you will print the result, you will print indices with value of true

Post-increment and pre-increment within a 'for' loop produce same output [duplicate]

This question already has answers here:
Difference between pre-increment and post-increment in a loop?
(22 answers)
Closed 8 years ago.
The following for loops produce identical results even though one uses post increment and the other pre-increment.
Here is the code:
for(i=0; i<5; i++) {
printf("%d", i);
}
for(i=0; i<5; ++i) {
printf("%d", i);
}
I get the same output for both 'for' loops. Am I missing something?
After evaluating i++ or ++i, the new value of i will be the same in both cases. The difference between pre- and post-increment is in the result of evaluating the expression itself.
++i increments i and evaluates to the new value of i.
i++ evaluates to the old value of i, and increments i.
The reason this doesn't matter in a for loop is that the flow of control works roughly like this:
test the condition
if it is false, terminate
if it is true, execute the body
execute the incrementation step
Because (1) and (4) are decoupled, either pre- or post-increment can be used.
Well, this is simple. The above for loops are semantically equivalent to
int i = 0;
while(i < 5) {
printf("%d", i);
i++;
}
and
int i = 0;
while(i < 5) {
printf("%d", i);
++i;
}
Note that the lines i++; and ++i; have the same semantics FROM THE PERSPECTIVE OF THIS BLOCK OF CODE. They both have the same effect on the value of i (increment it by one) and therefore have the same effect on the behavior of these loops.
Note that there would be a difference if the loop was rewritten as
int i = 0;
int j = i;
while(j < 5) {
printf("%d", i);
j = ++i;
}
int i = 0;
int j = i;
while(j < 5) {
printf("%d", i);
j = i++;
}
This is because in first block of code j sees the value of i after the increment (i is incremented first, or pre-incremented, hence the name) and in the second block of code j sees the value of i before the increment.
The result of your code will be the same. The reason is that the two incrementation operations can be seen as two distinct function calls. Both functions cause an incrementation of the variable, and only their return values are different. In this case, the return value is just thrown away, which means that there's no distinguishable difference in the output.
However, under the hood there's a difference: The post-incrementation i++ needs to create a temporary variable to store the original value of i, then performs the incrementation and returns the temporary variable. The pre-incrementation ++i doesn't create a temporary variable. Sure, any decent optimization setting should be able to optimize this away when the object is something simple like an int, but remember that the ++-operators are overloaded in more complicated classes like iterators. Since the two overloaded methods might have different operations (one might want to output "Hey, I'm pre-incremented!" to stdout for example) the compiler can't tell whether the methods are equivalent when the return value isn't used (basically because such a compiler would solve the unsolvable halting problem), it needs to use the more expensive post-incrementation version if you write myiterator++.
Three reasons why you should pre-increment:
You won't have to think about whether the variable/object might have an overloaded post-incrementation method (for example in a template function) and treat it differently (or forget to treat it differently).
Consistent code looks better.
When someone asks you "Why do you pre-increment?" you'll get the chance to teach them about the halting problem and theoretical limits of compiler optimization. :)
This is one of my favorite interview questions. I'll explain the answer first, and then tell you why I like the question.
Solution:
The answer is that both snippets print the numbers from 0 to 4, inclusive. This is because a for() loop is generally equivalent to a while() loop:
for (INITIALIZER; CONDITION; OPERATION) {
do_stuff();
}
Can be written:
INITIALIZER;
while(CONDITION) {
do_stuff();
OPERATION;
}
You can see that the OPERATION is always done at the bottom of the loop. In this form, it should be clear that i++ and ++i will have the same effect: they'll both increment i and ignore the result. The new value of i is not tested until the next iteration begins, at the top of the loop.
Edit: Thanks to Jason for pointing out that this for() to while() equivalence does not hold if the loop contains control statements (such as continue) that would prevent OPERATION from being executed in a while() loop. OPERATION is always executed just before the next iteration of a for() loop.
Why it's a Good Interview Question
First of all, it takes only a minute or two if a candidate tells the the correct answer immediately, so we can move right on to the next question.
But surprisingly (to me), many candidates tell me the loop with the post-increment will print the numbers from 0 to 4, and the pre-increment loop will print 0 to 5, or 1 to 5. They usually explain the difference between pre- and post-incrementing correctly, but they misunderstand the mechanics of the for() loop.
In that case, I ask them to rewrite the loop using while(), and this really gives me a good idea of their thought processes. And that's why I ask the question in the first place: I want to know how they approach a problem, and how they proceed when I cast doubt on the way their world works.
At this point, most candidates realize their error and find the correct answer. But I had one who insisted his original answer was right, then changed the way he translated the for() to the while(). It made for a fascinating interview, but we didn't make an offer!
Hope that helps!
Because in either case the increment is done after the body of the loop and thus doesn't affect any of the calculations of the loop. If the compiler is stupid, it might be slightly less efficient to use post-increment (because normally it needs to keep a copy of the pre value for later use), but I would expect any differences to be optimized away in this case.
It might be handy to think of how the for loop is implemented, essentially translated into a set of assignments, tests, and branch instructions. In pseudo-code the pre-increment would look like:
set i = 0
test: if i >= 5 goto done
call printf,"%d",i
set i = i + 1
goto test
done: nop
Post-increment would have at least another step, but it would be trivial to optimize away
set i = 0
test: if i >= 5 goto done
call printf,"%d",i
set j = i // store value of i for later increment
set i = j + 1 // oops, we're incrementing right-away
goto test
done: nop
If you wrote it like this then it would matter :
for(i=0; i<5; i=j++) {
printf("%d",i);
}
Would iterate once more than if written like this :
for(i=0; i<5; i=++j) {
printf("%d",i);
}
Both i++ and ++i is executed after printf("%d", i) is executed at each time, so there's no difference.
You could read Google answer for it here:
http://google-styleguide.googlecode.com/svn/trunk/cppguide.xml#Preincrement_and_Predecrement
So, main point is, what no difference for simple object, but for iterators and other template objects you should use preincrement.
EDITED:
There are no difference because you use simple type, so no side effects, and post- or preincrements executed after loop body, so no impact on value in loop body.
You could check it with such a loop:
for (int i = 0; i < 5; cout << "we still not incremented here: " << i << endl, i++)
{
cout << "inside loop body: " << i << endl;
}
The third statement in the for construct is only executed, but its evaluated value is discarded and not taken care of.
When the evaluated value is discarded, pre and post increment are equal.
They only differ if their value is taken.
Yes, you'll get exactly same outputs for both. why do you think they should give you different outputs?
Post-increment or pre-increment matters in situations like this:
int j = ++i;
int k = i++;
f(i++);
g(++i);
where you provide some value, either by assigning or by passing an argument. You do neither in your for loops. It gets incremented only. Post- and pre- don't make sense there!
There is a difference if:
int main()
{
for(int i(0); i<2; printf("i = post increment in loop %d\n", i++))
{
cout << "inside post incement = " << i << endl;
}
for(int i(0); i<2; printf("i = pre increment in loop %d\n",++i))
{
cout << "inside pre incement = " << i << endl;
}
return 0;
}
The result:
inside post incement = 0
i = post increment in loop 0
inside post incement = 1
i = post increment in loop 1
The second for loop:
inside pre incement = 0
i = pre increment in loop 1
inside pre incement = 1
i = pre increment in loop 2
Compilers translate
for (a; b; c)
{
...
}
to
a;
while(b)
{
...
end:
c;
}
So in your case (post/pre- increment) it doesn't matter.
EDIT: continues are simply replaced by goto end;