#include <stdio.h>
int main(void) {
int i= 1, j = 1;
for (; j; printf("%d %d",i, j))
j = i++ <= 5;
return 0;
}
output-
2 13 14 15 16 17 0
Can anyone explain what is happening inside the loop? This question was asked in the interview process.
The code is equivalent to:
int main(void) {
int i=1,j=1;
while (j != 0) {
j = (i<=5);
i = i+1;
printf("%d %d",i,j);
}
return 0;
}
I think that its meaning and the output is evident now. Note that printf does not print any separator after the second number. It means that the two digit "numbers" in the output are printed by two successive invocations of printf each. If you use printf("%d %d; ",i,j); instead of printf("%d %d",i,j); the output will be:
2 1; 3 1; 4 1; 5 1; 6 1; 7 0;
Your code is the same as
#include <stdio.h>
int main() {
int i = 1, j = 1;
while (j > 0) {
if (i <= 5) {
j = 1;
} else {
j = 0;
}
i = i + 1;
printf("%d %d",i, j);
}
}
It should now be easy to understand.
De-obfuscated, the code is equivalent to this:
for(int i=1; i<7; i++)
{
printf("%d\t%d\n", i+1, (i+1) < 7);
}
What such a loop would be needed for, I have no idea.
Initially, i and j are 1 so condition for loop will be true and it will enter into the loop.
At j = i++<=5; statement first it will execute conditional operation and assign result of conditional operation (true = 1, or, false = 0) to j and increment i by one. After this, it will execute print statement from the loop which will print value for i (which is now incremented by one is 2) and j (will be 1 as the condition is true). This will continue until the i<=5 condition is true. Whenever i becomes greater than 5 j will be 0, breaking the loop.
To make the code and its output more clear rewrite the program the following way
#include <stdio.h>
int main(void)
{
for ( int i = 1, j = 1; j != 0; )
{
j = i++ <= 5;
printf("%d %d\n", i, j );
}
return 0;
}
The program output is
2 1
3 1
4 1
5 1
6 1
7 0
As the variable j is calculated as a result of this condtion
i++ <= 5
then it will be always equal to 1 except when i will be equal to 6 because for this value of i the condition is evaluted to false that is to 0 and this value is assigned to j.
So the last iteration of the loop is when i is equal to 6. In this case after this statement
j = i++ <= 5;
i will be equal to 7 and j will be equal to 0. These values are outputted in the last iteration of the loop.
7 0
Related
Apologies for the title, but I could not find a similar question that has already been posed. As implied, my question is how to implement a counter which starts at an initial value and increments upwards until a specific point is reached, then decrements back down to the original value. Allow me to provide an example to better suggest showcase what I mean
#include <stdio.h>
int main(void) {
int i = 0;
for(i = 0; i <= 10; i++) {
printf("i = %d\n", i);
if(i == 5) {
int j = i;
for(j = i; j >= 0; j--) {
printf("j = %d\n", j);
}
}
}
return 0;
}
When run, the program will print values 0-5 for i, then print 5-0 for j and then finish printing 6-10 for i. Instead of this, I just want to have the program print 0-5 for i and then 5-0 for i (or j if another variable is needed).
You could use two separate loops like Rafalon in the comments suggested.
If you want one loop you can do something like this (modified it with the information from OPs comment):
int ctr_dir = 80;
int upper_value = 500;
for(int i = 0; i >= 0; i += ctr_dir)
{
printf("%d", i);
if (i > upper_value)
ctr_dir = -80;
}
You are making this needlessly complicated.
for(int i=0; i<6; i++) // print 0 to 5
{
printf("%d\n", i);
}
for(int i=0; i<6; i++) // print 5 to 0
{
printf("%d\n", 5-i);
}
Whilst I don't fully understand the reasons behind the way you've written the code, the missing ingredient from it is a break inside the if statement which will exit the loop rather than continuing on and printing out 6 to 10.
for(i = 0; i <= 10; i++) {
printf("i = %d\n", i);
if(i == 5) {
int j = i;
for(j = i; j >= 0; j--) {
printf("j = %d\n", j);
}
break; // Exit the loop
}
}
I think simple is best, but you said "my problem is more complex" (I don't know how much more !?), I wrote a more "complex" version...
You can do this something like this,
But the problem with this code is overshoots. i.e. if step is more than 1, you can pass maximum value. :)
#include <stdio.h>
void WaveGenerator(int start, int step, int max, int times)
{
int value = start;
times *= 2;
printf("%d", value);
while(times)
{
value += step;
if ((value <= start) || (value >= max))
{
step *= -1;
times--;
}
printf("%d", value);
}
}
int main()
{
int i;
WaveGenerator(1, 1, 5, 2);
return 0;
}
There have been many different solutions here, including the one I already posted as a comment.
Let me add another one here, similar to #izlin's but yet different:
int i=0;
int j=0;
int max=10;
for(i=0;i<=max;i++)
{
printf("%d\n", j);
if(i<max/2)
j++;
else
j--;
}
// max=10 > 0 1 2 3 4 5 4 3 2 1 0
// max=11 > 0 1 2 3 4 5 4 3 2 1 0 -1
Note that depending on the parity of max, this will go down to either 0 or -1.
This can be tweaked this way:
int i=0;
int j=0;
int max=10;
for(i=0;i<=max;i++)
{
Console.WriteLine(j);
if(i<max/2)
j++;
else if(i>(max-1)/2)
j--;
}
// max=10 > 0 1 2 3 4 5 4 3 2 1 0
// max=11 > 0 1 2 3 4 5 5 4 3 2 1 0
so it writes the top number twice if max is odd, and once if it is even, but always starts and ends with 0.
I would however still use 2 loops instead, as I suggested in my comment:
int i=0;
int max=5;
for(i=0;i<=max;i++)
{
printf("%d\n", i);
}
// 0 1 2 3 4 5
for(i=max;i>=0;i--)
{
printf("%d\n", i);
}
// 5 4 3 2 1 0
Since the work you want to perform is the same whether you are going up or down, you don't want to use separate loops as you'd be repeating yourself.
You can do this in a single loop by using a flag that indicates whether you've hit the upper limit. If the flag isn't set you increment, if it is you decrement.
int increment = 5, limit = 50;
int i = 0, go_back = 0;
while (i>=0) {
printf("%d\n", i);
if (i >= limit) {
go_back = 1;
}
if (go_back) {
i -= increment;
} else {
i += increment;
}
}
#include <stdio.h>
int main() {
int i, j;
for (i = 2; i < 20; i++) {
for (j = 2; j <= (i/j); j++) {
if (!(i%j)) break;
}
if (j > (i/j)) printf("%d\n", i);
}
return 0;
}
I am a Beginner at C and trying to understand how the for loop works. My question is at the 4th iteration, the condition in the nested loop will return TRUE
(j < (i/j)) // 2 <= 4/2
and the first if statement will also return TRUE because of NOT operator
(!(i%j)); // 4/2 = !(0)
so now the value of j = 3 because of incrementation, but why the second if statement did not print the output if it is TRUE?
(j > (i/j)); // 3 > 4/3
You're breaking out of the loop before j is incremented, so j is still 2, not 3
A break statement ends its nearest enclosing loop prematurely. Everything after it (and that includes the third statement of the for loop), will not occur.
So j is still 2 when the condition for printing is checked, like Mark answered.
I have this code for prime numbers..it gives me the prime numbers up to 103.Maybe my first break statement is wrong? I did it this way because i want to skip as much numbers as possible.i want only the primes that have at least two digits(that is why i started from 11)
#include <stdio.h>
#define MAXNUMB 100000000
int main (void)
{
int i, j;
for (i = 11 ; i < MAXNUMB ; i += 2)
{
if ((i % 3 == 0) && (i % 5 == 0) && (i % 7 == 0))
break;
for (j = 3 ; j * j <= i ; j += 2)
{
if (i % j == 0)
break;
}
if (j * j > i)
printf ("%d \n", i);
}
}
Use continue rather then break; Here you want to skip much number ( As if there are many ways to find the prime numbers in small complexity like much popular Sieve of Eratosthenes) but it breaks. So change a little..
if((i%3==0)&& ( i%5==0) && (i%7==0))
continue;// here
it works..
#include <stdio.h>
#include <string.h>
#define MAXNUMB 100000000
int main (void)
{
int i, j, P[MAXNUMB];
memset(P, 0, sizeof(P));
for(i = 2; i < MAXNUMB; ++i)
{
if(P[i] == 0){
printf("%d\n", i);
if(i < MAXNUMB / i)
for(j = i*i; j < MAXNUMB; j += i)
P[j] = 1;
}
}
return 0;
}
As it would be obvious using a debugger, that statement is wrong. First, you check for numbers that are divisible by 3 and 5 and 7. 105 is divisible by all. Then you break, which means "exit this for loop", so the program will end. You need to just continue the looping and not report this number as a prime.
You want to change the loop to use or instead of and. Also the next for loop doesn't need to start from 3 then, since you already tried 3, 5, 7. But is there a reason for that since you could just use the for loop?
My suggestion would be to just forget the first if altogether since it will not make it any faster.
#include <stdio.h>
#define MAXNUMB 100000000
int main (void)
{
int i, j, f;
for (i = 11; i < MAXNUMB; i += 2)
{
for (j = 2, f = 1; f && j * j < i; ++j)
{
f = (i % j != 0);
}
if (f) printf("%d\n", i);
}
return 0;
}
I don't understand what exactly does the continue statement inside this for loop do. How is code any different if I remove it? Which lines does it skip if it's placed at the end of for loop?
int sum = 0, i, j, stop = 0;
for( i = 1; i <= 5 && !stop; i++)
{
for( j = 1; j <= 5 ; j++)
{
if (j%4 == 0)
{
stop = 1;
continue;
}
sum += i+j;
}
}
printf("%d\n", sum);
If you run this program the sum is going to be 15, and if you comment out countinue line then it's going to be 20.
It would be more clear if you would format the code. Let's consider the inner loop
for( j = 1; j <= 5 ; j++)
{
if ( j % 4 == 0)
{
stop = 1;
continue;
}
sum += i+j;
}
Thus as you see if j % 4 == 0 then statement
sum += i+j;
is skipped.
As for the code in whole then it has no any sense.:) It is a silly code.
In fact your code is equivalent to the following
int sum = 0, j;
for( j = 1; j <= 5 ; j++ )
{
if ( j != 4 ) sum += j + 1
}
printf("%d\n", sum);
So you will get sum 2 + 3 + 4 + 6 that is equal to 15.:)
The continue statement skips the remainder of the current loop. In the case of nested loops, it skips to the next iteration of the innermost loop.
In this case, if you didn't continue, you would execute sum += i+j; in every iteration, where it appears you only want it sometimes.
That being said, this is a very awkward loop to begin with. The whole stop variable is rather ill conceived from the get-go anyway.
The continue statement is used to start the next iteration of a loop,skipping everything in the loop,after the continue. In your case,once the execution of the program reaches the continue statement,then the next iteration of your inner loop starts,skipping whatever there was after the continue. It skips sum += i+j; as it is after the continue and the sum will not be added when j is 4 as j%4 will be 0. This is why you get 20 when you comment the continue and 15 when you uncomment it.
P.S: Your outer loop will execute only once as stop will be changed inside the if in your inner loop.
continue causes the enclosing for loop to begin the next iteration. As a more basic example, take the following code:
for(int i = 0; i < 50; i++)
{
if(i % 2 == 1) // If it's odd
continue;
printf("%d\n", i);
}
In this case, the continue statement will cause the for loop to immediately begin the next iteration if i is odd, hence this code will print the even numbers between 0 and 50.
int sum = 0, i, j, stop = 0;
for( i = 1; i <= 5 && !stop; i++)
{
for( j = 1; j <= 5 ; j++)
{
if (j%4 == 0) <===== is j divisible by 4 ?
{
stop = 1; <=== set stop flag, will continue for J loop
but stop next I loop and end the routine
continue; <==== skip the rest of the J loop for this itteration
}
sum += i+j;
}
}
printf("%d\n", sum);
http://msdn.microsoft.com/en-us/library/0ceyyskb.aspx explains the continue statement
I encountred this function without any comment. I wonder what is this function doing? Any help?
int flr(int n, char a[])
{
#define A(i) a[((i) + k) % n]
int l[n], ls = n, z[n], min = 0;
for (int i = 0; i < n; i++)
{
l[i] = i;
z[i] = 1;
}
for (int k = 0; ls >= 2; k++)
{
min = l[0];
for (int i=0; i<ls; i++) min = A(l[i])<A(min) ? l[i] : min;
for (int i=0; i<ls; i++) z[A(l[i])!=A(min) ? l[i] : (l[i]+k+1)%n] = 0;
for (int ls_=ls, i=ls=0; i<ls_; i++) if (z[l[i]]) l[ls++] = l[i];
}
return ls == 1 ? l[0] : min;
}
What a fun problem!
Other posters are correct that it returns the index of a minimum, but it's actually more interesting than that.
If you treat the array as being circular (i.e. when you get past the end, go back to the beginning), the function returns the starting index of the minimum lexicographic subsequence.
If only one element is minimal, that element is returned. If multiple elements are minimal, we compare the next element along from each minimal element.
E.g. with an input of 10 and {0, 1, 2, 1, 1, 1, 0, 0, 1, 0}:
There are four minimal elements of 0, at indices 0, 6, 7 and 9
Of these two are followed by a 1 (the 0 and 7 elements), and two are followed by a 0 (the 6 and 9 elements). Remember that the array is circular.
0 is smaller than 1, so we only consider the 0s at 6 and 9.
Of these the sequence of 3 elements starting at 6 is '001' and the sequence from 9 is also '001', so they're still both equally minimal
Looking at the sequence of 4 elements, we have '0010' from element 6 onwards and '0012' from element 9 onwards. The sequence from 6 onwards is therefore smaller and 6 is returned. (I've checked that this is the case).
Refactored and commented code follows:
int findStartOfMinimumSubsequence(int length, char circular_array[])
{
#define AccessWithOffset(index) circular_array[(index + offset) % length]
int indicesStillConsidered[length], count_left = length, indicator[length], minIndex = 0;
for (int index = 0; index < length; index++)
{
indicesStillConsidered[index] = index;
indicator[index] = 1;
}
// Keep increasing the offset between pairs of minima, until we have eliminated all of
// them or only have one left.
for (int offset = 0; count_left >= 2; offset++)
{
// Find the index of the minimal value for the next term in the sequence,
// starting at each of the starting indicesStillConsidered
minIndex = indicesStillConsidered[0];
for (int i=0; i<count_left; i++)
minIndex = AccessWithOffset(indicesStillConsidered[i])<AccessWithOffset(minIndex) ?
indicesStillConsidered[i] :
minIndex;
// Ensure that indicator is 0 for indices that have a non-minimal next in sequence
// For minimal indicesStillConsidered[i], we make indicator 0 1+offset away from the index.
// This prevents a subsequence of the current sequence being considered, which is just an efficiency saving.
for (int i=0; i<count_left; i++){
offsetIndexToSet = AccessWithOffset(indicesStillConsidered[i])!=AccessWithOffset(minIndex) ?
indicesStillConsidered[i] :
(indicesStillConsidered[i]+offset+1)%length;
indicator[offsetIndexToSet] = 0;
}
// Copy the indices where indicator is true down to the start of the l array.
// Indicator being true means the index is a minimum and hasn't yet been eliminated.
for (int count_before=count_left, i=count_left=0; i<count_before; i++)
if (indicator[indicesStillConsidered[i]])
indicesStillConsidered[count_left++] = indicesStillConsidered[i];
}
return count_left == 1 ? indicesStillConsidered[0] : minIndex;
}
Sample uses
Hard to say, really. Contrived example: from a circular list of letters, this would return the index of the shortest subsequence that appears earlier in a dictionary than any other subsequence of the same length (assuming all the letters are lower case).
It returns the position of the smallest element within the substring of a ranging from element 0..n-1.
Test code
#include <stdio.h>
int flr(int n, char a[])
{
#define A(i) a[((i) + k) % n]
int l[n], ls = n, z[n], min = 0;
for (int i = 0; i < n; i++)
{
l[i] = i;
z[i] = 1;
}
for (int k = 0; ls >= 2; k++)
{
min = l[0];
for (int i=0; i<ls; i++) min = A(l[i])<A(min) ? l[i] : min;
for (int i=0; i<ls; i++) z[A(l[i])!=A(min) ? l[i] : (l[i]+k+1)%n] = 0;
for (int ls_=ls, i=ls=0; i<ls_; i++) if (z[l[i]]) l[ls++] = l[i];
}
return ls == 1 ? l[0] : min;
}
int main() {
printf(" test 1: %d\n", flr(4, "abcd"));
printf(" test 3: %d\n", flr(6, "10e-10"));
printf(" test 3: %d\n", flr(3, "zxyghab");
printf(" test 4: %d\n", flr(5, "bcaaa"));
printf(" test 5: %d\n", flr(7, "abcd"));
return 0;
}
This code gives following output:
[root#s1 sf]# ./a.out
test 1: 0
test 2: 3
test 3: 1
test 4: 2
test 5: 4
1. 0 is the position of `a` in the first case
2. 3 is the position of `-` in second case.
3. 1 is the position of `x` in third case.
4. 2 is the position of the second `a`.
5. 4 is the position of the `\0`
So the function returns the position of smallest element of a character pointer pointed by a and it will consider n elements. (Thats why it returned the position of x in the third case).
But when multiple smallest element available, it does not seems to be work in a predictable way, as it does not return the first occurrence, nor the last.
It should do a error checking for out of bound cases. Which may lead to problem in future.
so i'm running tests on this.
int flr(int n, char a[])
{
#define A(i) a[((i) + k) % n]
int l[n], ls = n, z[n], min = 0;
for (int i = 0; i < n; i++)
{
l[i] = i;
z[i] = 1;
}
for (int k = 0; ls >= 2; k++)
{
min = l[0];
for (int i=0; i<ls; i++) min = A(l[i])<A(min) ? l[i] : min;
for (int i=0; i<ls; i++) z[A(l[i])!=A(min) ? l[i] : (l[i]+k+1)%n] = 0;
for (int ls_=ls, i=ls=0; i<ls_; i++) if (z[l[i]]) l[ls++] = l[i];
}
return ls == 1 ? l[0] : min;
}
int main()
{
int in = 10;
char array[] = {0, 1, 1, 1, 1, 1, 0, 1, 1, 0};
int res = flr(in, array);
printf("expecting res to be 6;\tres = %d\n", res);
system("pause");
return 0;
}
output was res=9;