is this loop statement is correct?
if not correct then what alternative way?
I am trying to o(n) loop statement like this-
for(int i=0 ; i<n ; i++ , j=n ; j<n*2 ; j++){
continue;
}
The construct is wrong, you cannot you two loops in one construct, but you can have more than one variable controlling the iteration.
For example, you can have
Two (or more) variables, i and j, initialized with certain values.
A loop controlling statement, involving operation and condition check on i and j (and others, if defined).
Finally, you can control the increment or decrement of i and j (and others, if defined).
A sample construct can be:
for (int i = 0, j = n; i < n && j < n * 2; ++i, ++j)
|^^^^^^^| -------- variable modification
| | |^^^^^^^^^^^^^^^^^| ---------------- loop condition
|^^^^^^^^^^^^^^^|--------------------------------------- initialization
What you seem to want is something like:
for (int i = 0, j = n; i < n && j < n * 2; ++i, ++j)
{
continue;
}
To help you better understand what I did and why, and how you can do such transformations in the future, you need to understand how a for loop is really handled by the compiler: As a special while loop.
For example, if you have
for (a; b; c)
{
d;
}
then that's equivalent to this:
{
a;
while (b)
{
d;
c;
}
}
If we take what you (probably) want, in the form of a while loop then it would be
{
int i = 0, j = n; // a in my example above
while (i < n && j < n * 2) // b in my example above
{
continue; // d in my example above
++i, ++j; // c in my example above
}
}
Now it's easy to translate it to the for loop I showed initially.
As noted in a comment, the while loop shown here is a little misleading, as it won't actually do the increment. But then I assume your real loop doesn't have an unconditional continue statement as the only statement in the body. That would make the loop rather meaningless. However the principle is still valid, even if the example isn't.
for(int i=0 ; i<n ; i++ , j=n ; j<n*2 ; j++){
continue;
}
The above code is wrong
but it can be written as
for(int i = 0 ,j = n; i < n ,j < n * 2; i++ ,j++)
The above code is correct
i=0 and j=n is initialization
i<n and j<n*2 is loop condition
i++ and j++ is incrementation
Related
I have 3 nested loops in which the code doesn't in anyway modify the counters, I need the value of the topmost-level loop counter to use later in the code. It looks like this
int i;
for( i = 0; !found && i <f_i.size();i++){
for(unsigned int j = 0; !found && j < f_g.size();j++){
for(unsigned int k = 0; !found && k < f_g.size();k++){
///Do Stuff
found = (/*Condition that's fulfilled after 2 iterations on k*/);
}
}
}
//Stuff that uses i
The condition is fulfilled after 2 iteration of the innermost loop, so i has the value 0 at that point.
Using GDB I saw that the value of i jumps to 1 after the condition is checked in the topmost loop, which gives me a wrong later in my program, or worse an out of bounds access.
Thanks in advance
This is how for loops work. The increment is done before the condition is checked.
The proper way (easier to read, easier to maintain) to do what you want is to add a variable, outside the loop.
int index;
And set it when you find the element:
found = ...
if (found) index = i;
The variable i is incremented due to the third expression of the for loop
int i;
for( i = 0; !found && i <f_i.size();i++){
^^^^
for(unsigned int j = 0; !found && j < f_g.size();j++){
for(unsigned int k = 0; !found && k < f_g.size();k++){
///Do Stuff
found = (/*Condition that's fulfilled after 2 iterations on k*/);
}
}
}
To avoid this you can write for example
int i;
for( i = 0; !found && i <f_i.size();){
for(unsigned int j = 0; !found && j < f_g.size();j++){
for(unsigned int k = 0; !found && k < f_g.size();k++){
///Do Stuff
found = (/*Condition that's fulfilled after 2 iterations on k*/);
}
}
i += !found;
}
Or instead of the expression statement
i += !found;
you can use the if statement like
if ( !found ) ++i;
Also the code will look more readable if the variable i will be initialized before the loops for example like
int i = 0;
while ( !found && i < f_i.size() ){
for(unsigned int j = 0; !found && j < f_g.size();j++){
for(unsigned int k = 0; !found && k < f_g.size();k++){
///Do Stuff
found = (/*Condition that's fulfilled after 2 iterations on k*/);
}
}
i += !found;
}
As others have said (or, at least, implied): once the (outermost) for loop is entered†, the variable, i, will be incremented at the end of that loop, before the condition is tested, to see if another loop should be run ...
... that is, unless you 'jump out' of the loop using a break statement!
So, the following, slightly modified, code will not increment i (at all) if found becomes true during the first iteration of the outermost loop:
int i;
for (i = 0; !found && i < f_i.size(); i++) {
for (unsigned int j = 0; !found && j < f_g.size(); j++) {
for (unsigned int k = 0; !found && k < f_g.size(); k++) {
///Do Stuff
found = (/*Condition that's fulfilled after 2 iterations on k*/);
}
}
// If "found" becomes true, exit the loop immediately, AVOIDING THE INCREMENT:
if (found) break;
}
So, while the other answers are very good, and the code solutions they offer are perfectly valid, the proposal here is a far more 'minimal' adjustment to your code. I hope it helps.
Note: You could, of course, add similar break statements to the inner loops; however, as your j and k variables are declared locally to those loops, it would appear that undesired increments to their values is not relevant. Furthermore, break cannot be used to jump out of multiple, nested loops.
† Also, be aware that if the found variable is true before the outermost for loop is encountered, that loop will not be executed (obviously) and, thus, the i variable will not be incremented in that case.
I have found a piece of code in a C++ program, it seems that it loops two times every for() loop in this program, but why does it need this third for in such preprocessor definition?
#define for for(int z=0;z<2;++z)for
It replaces for with for(int z=0;z<2;++z)for. Obviously, that would turn
for (int i = 0; i < N; ++i) {
// ...
}
into
for (int z=0;z<2;++z) for (int i = 0; i < N; ++i) {
// ...
}
Thus creating two nested loops. Without that extra for it would be
for (int z=0;z<2;++z) (int i = 0; i < N; ++i) {
// ...
}
Which is obviously incorrect.
Note that even though it's “correct” in the form you gave in your question, it doesn't mean it's a “good practice”. This is an example of excessive macro abuse and must be avoided. Here is one of the numerous examples how it could go wrong:
for (int z = 0; z < 5; ++z) {
for (int i = 0; i < 3; ++i) {
std::cout << z << std::endl; // this will never print 2, 3, 4
}
}
This will expand into
for (int z=0;z<2;++z) for (int z = 0; z < 5; ++z) {
for (int z=0;z<2;++z) for (int i = 0; i < 3; ++i) {
std::cout << z << std::endl; // this will never print 2, 3, 4
}
}
Meaning that you now have four nested loops, and that the inner loop will print the “invisible” z instead of the z you have declared in the outer loop (which becomes the second-level loop in the expanded code).
Another reason: as pointed by #stefan, it's a very bad idea to use keywords or other well-known identifiers as macro names. Makes one think of the infamous #define true false. And, as #HolyBlackCat mentions, it's also undefined behavior, meaning that as far as the standard is concerned, anything could happen. Ranging from the code “seemingly working” to a full-blown World War III with Martians (who invaded Earth to cleanse it from ugly code).
Firstly, that macro is the ugliest thing I've ever seen. I don't recommend ever doing something like this.
The top answer from Sergey Tachenov is really great, but it should also be mentioned that this macro really makes every for loop run twice. This means the doubly nested loops shown below will execute 400 times (not 200 times)! This might be unexpected.
for (int i = 0; i < 10; i++) {
for (int j = 0; j < 10; j++) {
// I'll be executed 100 times without the macro
}
}
becomes
for (int z=0;z<2;++z) for (int i = 0; i < 10; i++) {
for (int z=0;z<2;++z) for (int j = 0; j < 10; j++) {
// I'll be executed 400 times with the macro
}
}
It only gets worse from here. Consider an infinte loop like
int some_condition = 0;
for(;;) {
// insert logic here for calculating whether to break out
if (some_condition) {
some_condition = 0; // set back to false for use down the line
break;
}
}
turns into
int some_condition = 0;
for (int z=0;z<2;++z) for (;;) {
// insert logic here for calculating whether to break out
if (some_condition) {
some_condition = 0; // set back to false for use down the line
break; // gets me out of for(;;)...but the outer loop repeats
}
}
which bumps you out of the inner infinite loop if the condition is met....only to go right back in it. Now you might be stuck in an infinite loop.
Unexpected behavior is a good reason to avoid something, and macro shenanigans like this is very dangerous, and could be a real b**ch to debug. Imagine if some include directive had this ported in several header files deep...
Preprocessor substitution occurs in a single pass and does not support recursion. So the second "for" is probably for some zany idea of chaining existing "for" loops, prepending them with the macro "for" loop portion.
#define for for(int z=0;z<2;++z)for
Thus it replaces
for (int i = 0; i < N; ++i)
{
// ...
}
with
for(int z=0;z<2;++z)
for (int i = 0; i < N; ++i)
{
// ...
}
Which is a pretty crazy use of the preprocessor.
1)
i = 0;
while(i < N){
j = i+1;
while(j < N && p[i].first == p[j].first && p[j].second - p[i].second < K) j++;
i = j; res++;
}
2)
for(i=0;i<N;i++){
j = i+1;
while(j < N && p[i].first == p[j].first && p[j].second - p[i].second < K) j++;
i = j; res++;
}
the first code and the second code differs only due to while loop in 1) and for loop in
2). But According to me the outputs due to both of them should be same but it differs.
Both the above codes are only a part of the total code. But I should tell you the output due to 1) is 2 whereas due to 2) is 3.
I don't why the answer is different because everything happening is same.
The for loop increments i twice. Once in the for loop definition itself (i++) and then indirectly via j.
The while loop only does the indirect increment via j. So the two examples are not the same.
I think to make equals the loops you should omit the increment in for:
for(i=0; i<N; ){
In your for loop, the variable i is incremented twice in your code:
First time at
for(i=0;i<N;i++){
and second time at
j = i+1 followed by i = j
Is it a good practice to use ternary operation in for loop condition.
I am asking this because i have come across the situation where in ternary operation will resolve my issue in for loop condition.
For eg:
for( short i = 0 ; i < count ; i++ ){
for( short j = 0 ; j < ( ( x[i] < y[i] ) ? x[i] : y[i] ) ; j++ ){ //Here I am using ternary operation at for loop condition place
//.....
//.....Some Code Here .......
//.....
}
}
I'd go for min(x[i], y[i]), just because it's clearer, but I don't see an immediate problem with your code.
Personally I would go for min(x[i], y[i]). However, your readability issues can be dealt with by pre-calculating the value and using it:
for( short i = 0 ; i < count ; i++ ){
int jCount = ( x[i] < y[i] ) ? x[i] : y[i]; // or min equivalent
for( short j = 0 ; j < jCount ; j++ ){
}
}
This changes the behaviour somewhat, in that it makes the condition blind to changes to x[i] and y[i] inside the j loop. I am not sure if that fits your use-case or not.
I dont see any problem.
My advice.
1. short change to int.
2. #define ternary(optional).
#define cond(n) (( x[n] < y[n] ) ? x[n] : y[n] )
for( int a = 0; a < count; a++)
for( int b = 0; b < cond(a), b++)
{
........code...............
}
If you're okay with using the ternary operator in general, then there is no reason not to use it in your for-loop condition. (I like the ternary operator myself, but I know some people think it's obfuscatory)
I guess there are no issues using ternary operator , other than that it makes code not readable . But condition like this x[i] < y[i] ) ? x[i] : y[i] can sometimes create problem in case you are also modifyiong x[i] and y[i] insdide for loop . So i would suggest not to use unless you really know what you are doing
I have been looking through some code and I have seen several examples where the first element of a for cycle is omitted.
An example:
for ( ; hole*2 <= currentSize; hole = child)
What does this mean?
Thanks.
It just means that the user chose not to set a variable to their own starting value.
for(int i = 0; i < x; i++)
is equivalent to...
int i = 0;
for( ; i < x; i++)
EDIT (in response to comments): These aren't exactly equivalent. the scope of the variable i is different.
Sometimes the latter is used to break up the code. You can also drop out the third statement if your indexing variable is modified within the for loop itself...
int i = 0;
for(; i < x;)
{
...
i++
...
}
And if you drop out the second statement then you have an infinite loop.
for(;;)
{
runs indefinitely
}
The for construct is basically ( pre-loop initialisation; loop termination test; end of loop iteration), so this just means there is no initialisation of anything in this for loop.
You could refactor any for loop thusly:
pre-loop initialisation
while (loop termination test) {
...
end of loop iteration
}
Some people have been getting it wrong so I just wanted to clear it up.
int i = 0;
for (; i < 10; i++)
is not the same as
for (int i = 0; i < 10; i++)
Variables declared inside the for keyword are only valid in that scope.
To put it simply.
Valid ("i" was declared outside of the loops scope)
int i = 0;
for (; i < 10; i++)
{
//Code
}
std::cout << i;
InValid ("i" does not exist outside the loop scope)
for (int i = 0; i < 10; i++)
{
//Code
}
std::cout << i;
It means that the initial value of hole was set before we got to the loop
That means loop control variable is initialized before the for loop .
For C code,
int i=0;
for( ; i <10 ; i++) { } //since it does not allow variable declaration in loop
For C++ code,
for(int i=0 ; i <10 ; i++) { }
You could omit any of the parameters of a for loop.
ie: for(;;) {} is about the same as while(true) {}
It means that the initial value of hole was set before we got to the loop.
Looks like a list traversal of some kind.
Suppose you wanted to
for (hole=1 ; hole*2 <= currentSize; hole = child)
But the value of hole just before the for loop was already 1, then you can slip this initilization part of the loop:
/* value of hole now is 1.*/
for ( ; hole*2 <= currentSize; hole = child)