[EDIT]Whoops there was a mistake in the code, and now all the responses to the question seem bizzare, but basically the for loop used to be, for(i=0; i<15; i++). I also edited to make the question more clear.[/EDIT]
I am trying to make a for loop, that checks a 16 element array, so it loops from 0 to 15. I then use the i variable later, however sometimes i == 16, which causes problems by being out of bounds.
I have a solution but it doesnt seem elegant, which makes me think I am missing something. I've tried while loops, but I can never get any loop to go from 0 to 15, and never end at a value greater than 15.
Is there any way to make a loop go and check all 16 elements of the array, while never being greater than 15 at the end of the loop?
int i;
for(i=0; i<16; i++)
{
someClass.someMethod(i);
if(someClass.Test())
{
break;
}
}
if (i == 16)
{
i = 15;
}
I suggest using some other variable other than i after your loop is finished. The criteria of using a for loop instead of a while loop is that you know beforehand exactly how many times a for loop will execute. If you already know this, just set some other variable to the ending value of your loop and use it instead of giving i a dual purpose.
int j = 15;
for(int i=0; i <= j; i++)
{
someClass.array[i];
}
// continue on using j, which value hasn't changed
Well for starters, your sample code loops from 0 to 14. But if you loop from 0 to 15, naturally i has to be 16 before the loop can end. What happens is it becomes 16, THEN your loop notices it's out of bounds and breaks out. If you want it to end at 15, honestly the easiest thing to do is just decrement just after the loop end.
i is incremented on last check to be 16, which is not less than 15, so loop exits with i being 16.
Maybe it's useful to know that:
for (before; check; after) { body }
it's the same as:
before
while(check) {
body
after
}
If you think at your for loop in that term, maybe you'll find out easily why i, at the exit, is 16.
There seems to be some fundamental flaws in your approach.
You shouldn't really use an index variable outside the scope of the loop.
You should use a variable or function to determine the limit of the loop.
It would be better to use iterators instead of numeric indexes.
Generic algorithms can remove the need for loops.
Just my $0.02.
So - if you're checking a 16 element array, normally you'd do this:
for(i=0; i<16; i++)
How for works, is it starts with the first statement of three:
i=0
Then it does your check, in the second statement:
i < 16 // True here, since 0 < 16
That happens before your loop. Then it runs the block of your loop with that set:
someClass.array[i]; //0
Finally, it does the final statement:
i++
Then it repeats the second and third statements, in a sequence.
Before the last run, i == 14, then it does i++, setting i to 15, and executes the block. Finally, it does i++, setting:
i==16
At this point, the condition is no longer true:
i < 16 // False, since i==16
At this point, your block does not execute, but i is still set to 16.
You must have missed something.
In this loop it wouldn't even hit 15, you'd need to say i <= 15, as soon as i = 14 it'd run once and bail.
The for loop is equivalent to the following while loop:
i = 0;
while(i < 16) {
someClass.array[i];
i++;
} // while
i needs to reach 16 to get out of the loop correctly.
Technically there are ways of writing the loop such that i is 15 on exiting the loop, but you shouldn't do them:
int i = 0;
while (1) {
someclass.someMethod(i);
if (i < 15) {
i++;
} else {
break;
}
}
Yes, it does what you ask. But the flow is horrible.
You cannot accomplish this with the built-in loop structures, and as Bill The Lizard said, you probably don't really want to reuse the for-loop variable.
But, if you really want to, here's a way to do it. The trick is to put the loop condition in the middle of the loop:
int i = 0;
while (true)
{
someclass.array[i];
if (i == 15)
break;
++i;
}
The key issue to understand here is that there are 17 different answers to the question "What value of i causes the test to succeed?". Either i can be in {0, 1, ..., 15}, or no value of i causes the test to succeed, which is denoted by i == 16 in this case. So if i is restricted to only 16 values, the question cannot be answered.
There are legitimate cases where you do not want to go past the last valid value. For instance, if you had 256 values and for some reason you only have one byte to count with. Or, as happened to me recently, you want to examine only every ith element of an array, and the last addition to your iterator takes you far beyond the end of the array. In these cases loop unrolling is necessary.
However, for this problem it would be cleaner to use a flag:
bool flag = false;
for (int i = 0; i < 15; ++i)
{
someClass.someMethod(i);
if (someClass.Test())
{
flag = true;
break;
}
}
Then it's clear whether or not the test ever succeeded.
If your loop terminates natuarally, rather than with a break, i will be 16. There's no way to avoid this. Your code is perfectly acceptable if what you want is for i to end up as 15 or less:
int i;
for (i=0; i<16; i++) {
someClass.someMethod(i);
if (someClass.Test())
break;
}
if (i == 16)
i = 15;
Anything that changes i from 16 to 15 after the loop body will do:
if (i == 16) i = 15;
i = (i == 16) ? 15 : i;
i = MAX (15,i); /* where MAX is defined :-) */
and so on.
However that assumes that i is going to be used for something meaningful as a post-condition with respect to that loop. I find that's rarely the case, people tend to re-initialize it before re-use (such as another for loop).
In addition, what you are doing makes it very difficult (impossible, even) to figure out as a post-condition, wheteher your loop terminated normally or whether it terminated prematurely because someClass.Test() returned true for i == 15. This means using i to make further decision is fraught with danger.
My question would be: Why do you think you need to leave i as 15 or less?
I am trying to make a for loop, that
checks a 16 element array, so it loops
from 0 to 15. I then use the i
variable later, however sometimes i ==
16, which causes problems by being out
of bounds.
You need to check for the case where your for loop didn't break, because this information determines whether or not whatever you wanted to do with i is valid.
There are a couple of ways to do this. One is to keep track of it in a bool, such as "foundClass" or "testSucceeded". Default it to false, then set it to true on your break. Enclose any uses of i later in the function in "if (foundClass) { }" blocks.
Another is to just do what you've done. Although your fallback doesn't look right at all. If you're setting i to 15, you're lying to your code and telling it that someClass.Test() succeeded for i == 15, which isn't true. Avoid setting the value to something that's wrong just so your code doesn't error later on. It's much better to put bounds checks around the actual usage of i later in the code.
for(int i=0; i<17; i++)
{
if(i<16)
{
someClass.someMethod(i);
if(someClass.Test())
{
break;
}
}
else if(i==16)
{
i=15;
}
}
if you say you have an array with 16 elements, you don't have to define that, use the array to get that info (DO NOT DUPLICATE INFORMATION)
afterwards if you want to get the last index again use the array to get that info.
for(int i = 0; i < myArray.length; ++i){
myArray[i].somemethod();
}
// lastindex = myArray.length-1;
Related
Is break the most efficient way to exit a loop? In the code snippet below, would line A or line B be the more efficient way to exit the loop? Any links to material on how the break instruction works under the hood would be appreciated.
for (int i = 0; i < 10; i++) {
cout << i << endl;
if (i == 3) {
break; // A
i = 15; // B
}
}
I assume the difference is trivial in most situations, and that A is faster because B requires an assignment, an increment, and then a comparison, but I don't actually know how break works and it's better to know than assume. Thanks!
Let's compile the following code and look at the assembly:
#include <stdio.h>
int loop_with_break() {
for (int i = 0; i < 10; i ++) {
puts("Hello, world!");
if (i == 3) {
break;
}
}
}
int loop_with_assignment() {
for (int i = 0; i < 10; i ++) {
puts("Hello, world!");
if (i == 3) {
i = 10;
}
}
}
int main() {
loop_with_break();
loop_with_assignment();
}
As you can see, when you use break, if i == 3, it'll jump straight out of the loop to the end of the function, whereas if you use i = 10, it'll set i to 10, increment it by 1, then do the comparison, which is slower. However, this was compiled with no optimizations. If you use optimizations, they both end up becoming the same thing. However, since break is more readable and these optimizations are not guaranteed, you should use it for breaking out of loops.
The keyword break will just quit the loop without any comparison made in the loop condition. If you use i = 15 syntax, the loop will iterate next time to verify whether the variable i is greater than 10, if so, then quit.
In short words, break will break the loop without thinking anything, whereas i = 15 will lead one more iteration to look if the condition satisfies it.
You're right! Actually break keyword is very faster for breaking loop!
In your example, if you use line A, then as soon as control reaches this statement, it will immediately break the loop.
On the other hand, if you use line B, then first the assignment will be performed and again the control will go to the condition checking and when the condition will get false then it will exit from the loop!
if you choose while loop you can prefer to make condition false in the while loop. But in this case using break make sense.
I'm failing to understand why would the loop exit at the value of character variable i = '\x1'
#include <iostream>
using namespace std;
int main()
{
char i;
for (i = 1; i < 10, i++;)
{
cout << i << endl;
}
return 0;
}
Can somebody please explain this behavior ?
This is wrong
for (i = 1; i < 10, i++;)
/* ^ should be ; */
You only declared 3 regions for the loop, but put your increment statement in the middle area, and left your increment area empty. I have no idea which statement in the middle area your compiler will choose to execute. Best not to try to be cute and deceive your compiler. Let alone some colleague who will read your code years from now and go WTF???
A for loop has 3 distinct areas delimited by semi-colons:
The initialization area. You can declare as many variables in here as you want. These can be delimited by commas.
The test area. This is where an expression goes to test if the loop should continue.
The post loop area. This region of code gets executed after every loop.
Try to keep it simple. If it is going to be more complicated then use a while loop.
The reason that i ends up being 1 is that when i++ is zero, which terminates the loop, then i will become 1 (That is what the form of the ++ operator you used does). As the other answered have pointed out, once you fix your code by moving i++ out of the condition by replacing the comma with a semicolon, then i will make it all the way to 10 as desired.
for (i = 1; i < 10; i++)
You wrote for statement wrong.
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
I'm making a C++ game which requires me to initialize 36 numbers into a vector. You can't initialize a vector with an initializer list, so I've created a while loop to initialize it faster. I want to make it push back 4 of each number from 2 to 10, so I'm using an int named fourth to check if the number of the loop is a multiple of 4. If it is, it changes the number pushed back to the next number up. When I run it, though, I get SIGABRT. It must be a problem with fourth, though, because when I took it out, it didn't give the signal.
Here's the program:
for (int i; i < 36;) {
int fourth = 0;
fourth++;
fourth%=4;
vec.push_back(i);
if (fourth == 0) {
i++;
}
}
Please help!
You do not initialize i. Use for (int i = 0; i<36;). Also, a new variable forth is allocated on each iteration of the loop body. Thus the test fourth==0 will always yield false.
I want to make it push back 4 of each number from 2 to 10
I would use the most straight forward approach:
for (int value = 2; value <= 10; ++value)
{
for (int count = 0; count < 4; ++count)
{
vec.push_back(value);
}
}
The only optimization I would do is making sure that the capacity of the vector is sufficient before entering the loop. I would leave other optimizations to the compiler. My guess is, what you gain by omitting the inner loop, you lose by frequent modulo division.
You did not initialize i, and you are resetting fourth in every iteration. Also, with your for loop condition, I do not think it will do what you want.
I think this should work:
int fourth = 0;
for (int i = 2; i<=10;) {
fourth++;
fourth%=4;
vec.push_back(i);
if (fourth==0) {
i++;
}
}
I've been able to create a static array declaration and pass that array into the vector at initialization without issue. Pretty clean too:
const int initialValues[36] = {0,1,2...,35};
std::vector foo(initialValues);
Works with constants, but haven't tried it with non const arrays.
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;