I have a piece of code:
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
int main()
{
for (int i = 0; i < 3; i++)
{
int j = 3;
while (j)
{
do
{
printf("%d %d\n", i, j);
j--;
} while (j == 2);
printf("Bang\n");
}
printf("Pop\n");
}
}
I am a new programming student, and this was one of the pieces of code the professor put on the board to see if we could walk through it. I understand the how this would compile, or so I thought.
Apparently the output for the code an endless loop, but forms a pattern as such:
i j
0 3
0 2
0 1
Bang
0 1
Bang
Pop
1 3
1 2
1 1
Bang
1 1
Bang
Pop
The part that is confusing to me is that, the do while loop claims to only do the loop if while(j ==2), yet at no point does the value of j seem to matter regarding the output of the loop. I am confused as to why j would go to from 1, before the bang, be subtracted with the j--; output Bang, then go back to 1. Also I dont understand why at one point it prints just Bang, but at another points Bang and Pop, i understand its exiting different scopes of loops, but I dont understand why it does that.
I input the code into visual studio 2013 and got a alternative output:
i j
0 3
0 2
bang
0 1
bang pop
1 3
1 2
bang
1 1
This makes more sense as printing Bang is adhering to the while(j == 2) loop, yet it still do not know why it prints bang and pop when j gets to 1.
I am confused as to why j would go to from 1, before the bang, be subtracted with the j--; output Bang, then go back to 1.
You're right when you say that j is 1 before the bang, and being 1 allows it to print "bang". But then it goes back into the while loop, prints 1 again (because it is still 1) goes down to zero (which you don't see because it doesn't print) and then prints "bang" again. Because j is 0 (which you never saw) it gets to exit the while loop and print "pop". The pattern repeats, but now i is 1.
You first need to understand that there is a fundamental difference between while and do-while.
The former checks the condition before entering the loop body so the loop body may execute zero or more times.
The latter checks after the loop body so is guaranteed to execute that body at least once. Hence the code snippet:
int j = 99;
do {
puts ("Hello");
while (j == 42);
will output Hello despite the fact j is nowhere near 42.
One thing I find very helpful to starters is to actually get a pen and paper and track every single line of code, evaluating it in your head, and keeping records of the current variable values:
i j Output
===== ===== ======
This will greatly assist your learning process.
In addition, you can (temporarily) change your bang/pop lines to provide more information:
printf("Bang %d %d\n", i, j);
printf("Pop %d %d\n", i, j);
and this will also make it clearer as to why you're seeing them together.
Taking all that information above into account, the reason you're seeing your particular output is because, whenever you exit the inner loop with j == 0 (having just banged), you also exit the middle loop because j being zero is equivalent to j being false. That will cause you to pop as well.
This can only happen if j started the inner loop at 1 - being do-while, it will execute at least once and j will drop to zero.
The situations where you bang without popping are limited to those situations where you exit the inner loop when j is not zero.
Has j started the inner loop at any other value than 1, it would have exited at 1 and you would have banged but not popped.
Related
Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 5 years ago.
Improve this question
I am unable to understand how is it working. Can somebody explain me this code?
#include <stdio.h>
int main () {
/* local variable definition */
int i, j;
for(i = 2; i<100; i++) {
for(j = 2; j <= (i/j); j++) {
if(!(i%j)) break; // if factor found, not prime
}
if(j > (i/j)) printf("%d is prime", i);
}
return 0;
}
1.#include <stdio.h> is a header that defines three variable types, several macros, and various functions for performing input and output. In other words, it's basically a C-Library being referenced to add some other externally defined logic, besides the code below, like the size_t variable, which is the result of the sizeof keyword for example. That's just one example of what the the stdio.h header does but you can see more info here: https://www.tutorialspoint.com/c_standard_library/stdio_h.htm
2.int main() is an integer function (int) that uses a deprecated declaration style main(), meaning you shouldn't it anymore because it's outdated by other functions, and the main() function in particular is a function that takes an unspecified number of arguments (integers in this case) and then runs some operations with those integers.
Next, the curly braces are what contain all the logic inside of the int main() function. Then inside of it, on the line int i, j; , two local variables are declared (i and j) to be later used as placeholders for some integers that will be plugged into the function.
Below that, for(i = 2; i<100; i++) indicates there is a loop that sets the i variable to 2, then after the semi-colon i<100 means that the loop will continue to execute again and again as long as the variable i is less than 100. After yet another semi-colon, i++ means that each time that the loop runs, the variable i will increment by 1. So it starts at 2, then 3, then 4, etc, until i reaches 100 and the loop stops executing.
Next, for(j = 2; j <= (i/j); j++) is another loop inside of the first loop, but this time the loop is using the variable j as a placeholder/counter instead of the variable i (the variable used by the previous loop), which surrounds this loop starting with "for(j..." . This loop also setsj to 2 (the same way the surrounding loop set i to 2); as long as j is less than or equal to (i divided by j) the loop will continue to execute; and j will increment (increase) by one each time that the loop is run, the same way that i does in the loop that surrounds this one.
if(!(i%j)) break; // if factor found, not prime this line means that the loop will also stop executing (break) if the remainder of i divided by j does not equal zero.
if(j > (i/j)) printf("%d is prime", i); This line means that if j is greater than i divided by j that the loop will write/output the text to stdout (std out is the standard output device, a pointer to a FILE stream that represents the default output device for the application).
Lastly, the last return 0; line indicates a return from the function and the final curly brace encloses the functions logic/code. The main function also should return 0(also EXIT_SUCCESS) to identify that the program has executed successfully and -1 otherwise (also EXIT_FAILURE).
Additional Note - Loops in every programming language I've seen personally tend to have a few things in common:
i. An init counter, a value where the loop will initialize (start counting), inside the loop's parentheses and before the first semi-colon.
ii. A test counter, which will be evaluated each time that the loop continues, and if it evaluates to TRUE the loop will continue usually but if it evaluates to false then the loop will end. This is the part of the loop after the first semi-colon but before the second semi-colon.
iii. An increment/decrement counter, which increases or decreases the loop by some value each time that the loop is run. This is the part of the loop inside the parentheses, after the second semi-colon. If there is no increment counter or test counter that causes the loop to exit/break at some point, then this is known as an infinite loop. This is a very bad thing in programming because it will cause just about any computer program to crash since it will execute and consume computing resources indefinitely. Not good :)
Disclaimer: I don't actually code in C but the language has so many similarities with programming languages I do use, that I'm guessing this answer is very close if not 100% correct. Curious to hear some input from an expert C programmer though!
Your code is looping over all integers from 2 to 99, holding the actual number in i.
for(i = 2; i<100; i++)
Then, for every number i, the code is looping again over all integers from 2 to (i/j).
for(j = 2; j <= (i/j); j++)
Your loop's finishing condition is mathematically equivalent to j being smaller than the square root of i, since any larger integer j would already contain itself a smaller factor of i.
(To check this, get a paper and rewrite the inequality so hat i is the sole part of the right hand side of your condition.)
Then it checks whether or not j divides i.
(i%j)
If j is a factor of i, then i modulo j is zero and hence
if (!(i%j))
evaluates to true (since 0 is evualted as false and ! negotiates this) and you can break out of the loop since i has a divisor not being 1 or i, hence i is not a prime.
On the other hand, if the inner loop is finished, you have found a prime since it has only 1 and i as divisor.
Needles to say that this bruteforce approach is very slow for large integers (you won't crack RSA with that), but does this clarify your questions?
#include <stdio.h>
int main () {
/* local variable definition */
int i, j;
// Loop from 2 to 99; i will hold the number we are checking to
// see if it is prime
for(i = 2; i<100; i++) {
// now loop through the numbers checking each one to see if
// it is a factor of i (if it is, then i isn't prime). This
// loop stops when j^2 is greater than or equal to the number
// we are checking
for(j = 2; j <= (i/j); j++) {
// i % j (i modulus j) is 0 iff j is a factor of i. This
// if test relies on the fact that 0 is false in C (and
// all nonzero values are true)
if(!(i%j)) break; // if factor found, not prime
}
// this tests to see if we exited the above loop by failing
// the test in the for() statement, or whether we exited the
// loop via the break statement. If we made it through all
// iterations of the loop, then we found no factors, and the
// number is prime.
//
// note that a \n is missing at the end of the printf format
// string. The output will be "2 is prime3 is prime5..."
if(j > (i/j)) printf("%d is prime", i);
}
// returns from main() with a value of 0, which will result in
// the program exiting with an exit code of 0. An explicit
// exit(0) is better form here, but this is not incorrect.
return 0;
}
I have been going through some exercises from a recommended book I found on this website. I came across this following basic piece of code, which I could not fully understand.
#include <stdio.h>
int main(void)
{
int i;
for (i = 10; i >= 1; i /= 2)
printf("%d ", i++);
return 0;
}
This is my reasoning behind this program fragment:
Variable i is initialised to 10.
i is tested to see if greater or equal to 1, (which is always the case).
The third expression reads: i = i / 2, thus i is divided by 2 and its value stored in i.
In the printf statement i is incremented after each printf statement.
I simply cannot understand why the output of this program is:
1 1 1 1 1 1 1 1 ...
I get that the condition statement is always true, however shouldn't the first values be:
5 3 2 1 1 1 1 1?
Basically I cannot seem to understand why the value of i is straight away being stored as 1. Any corrections regarding my reasoning and/or insight on the matter will be appreciated. Please do excuse the basic nature of this question.
As #abelenky pointed out, the correct output is 10 5 3 2 1 1 1 .... The only mistake you made in your reasoning is that the statement i /= 2 gets evaluated after the body of the for loop, before testing the condition again. Another way to write the same loop would therefore be
for(i = 10; i >= 1; i = (i + 1) / 2)
printf ("%d ", i);
If you are running on Windows, try paging the output through more: myprog | more. This should allow you to see the beginning of the output of this infinite loop. On a linux machine, you could acheive the same result using more or less: myprog | less. Thanks to #EugeneSh for making the suggestion that this could be the issue.
Another way that I have found to view the initial output for programs like this is to hit Ctrl+C immediately after starting the program with Enter. This is not a "standard" method and may require very quick reflexes to get any results for a quick loop like yours.
A final suggestion is to limit the output you produce from the program directly:
int i, count;
for(i = 10, count = 0; i >= 1 && count < 100; i /= 2, count++)
printf("%d ", i++);
This will add a counter that will stop your output after 100 numbers have been printed and allow you to see the first numbers.
On the second line, you have 'i++'.
Thus at each iteration of the loop, it will also increment i by 1.
So supposing i = 1 when you start the loop. First it will be divided by 2 (i /= 2). Since i is an integer, it will become 0. Then, on the second line, you have 'i++', thus incrementing i.
So by the end of the loop iteration, i will be back to being equal to 1 (thus making this loop infinite).
Apropos the question "Why does using the same count variable name in nested FOR loops work?" already posted in this forum,a count variable "i" defined in each nested loop should be considered a new variable whose scope is limited to that loop only.And we should expect that variable's value to be erased and overridden by the value of "i" which was in the outer loop (before control passed to inner loop).But in my following code, when the control comes out of the inner loop,instead of the variable "i" having the value 0 (which was it's value in the first iteration of outer loop,before control passed to inner loop),it continues to have the value 10 instead (which it got in last iteration of inner loop).Then this 10 is incremented to 11 and hence the condition of the outer loop in not satisfied and the outer loop exits.
I had expected my program to print the numbers 0 to 9 horizontally 10 times, in 10 different lines.But it prints just for one line and exits.
And here's another thing to it--If I use any number greater than 10 in the outer loop condition (i<=10),then it creates an infinite loop.According to my reasoning, it happens because i gets a value of 11 after the first iteration of outer loop and hence if condition is <=11 or more then the outer loop comes to another iteration.Whereupon i is again initialized to 0 in inner loop and the cycle continues.
Sorry if I couldn't put my question very clearly.All I want to ask is, isn't the inner i supposed to be a different variable if we are to assume the linked question on this forum is correct?Why then the value of i continues to hold on after we exit inner loop,instead of reverting to the value of i that was there when we entered the inner loop?
#include <stdio.h>
int main()
{
int i;
//for (i = 0; i <= 11; i++) Creates infinite loop if this condition is used instead
for (i = 0; i <= 9; i++)
{
for (i = 0; i <= 9; i++)
{
printf("%d ", i);
}
printf("\n");
}
}
OUTPUT : 0 1 2 3 4 5 6 7 8 9
PS: As a secondary question, is it impossible to print the number 0 to 9 horizontally, in 10 different lines, using nested for loop if we use the same count variable in each loop,as I have done here? (Ignore this secondary question if it's not relevant to main question)
The answer you linked to is using different variables with the same name, you're simply using the same variable.
Compare:
for(int i = 0; ...
to:
for(i = 0; ...
The former declares a new variable called i, which is how you nest loops like the linked-to answer. Not that I would ever (ever!) recommend doing so.
As you've noticed, support for the former syntax wasn't added to C until C99.
If i were defined in each loop then the behaviour would be as your linked question. In your example you only define i once, outside any loop, then reuse it
int i;
for(i=0; i<=9; i++)
{
for(i=0; i<=9; i++)
{
is not the same as
for(int i=0; i<=9; i++)
{
for(int i=0; i<=9; i++)
{
If you want each for loop to have its own i, you need to create i individually for each. As-is, you have exactly one i that's defined outside both loops, so the modifications done by one loop affect the value seen by the other.
int i;
for (i=0; i<10; i++) {
int i; /* define another i for the inner loop */
for (i=0; i<10; i++)
printf("%d\t", i);
printf("\n");
}
Note that I'd generally recommend against this -- while the compiler has no problem at all with having two variables with the same name at different scopes, code like this where it's not immediately obvious what i is being referred to when may well confuse people reading the code.
All I want to ask is, isn't the inner i supposed to be a different
variable
no, there is only one declaration, so only one variable
Sorry - late response, but couldn't help but notice:
The reason it "works" is that the inner loop resets i to zero, prints & increments i, and returns to the outer loop - at which point i>9 so the outer loop exits.
There is only one iteration of the outer loop and the values printed are entirely determined by the inner loop. It's not a question of scope, it's the fact you reassign new values to i in the inner loop.
PS: As a secondary question, is it impossible to print the number 0 to 9 horizontally, in 10 different lines, using nested for loop if we use the same count variable in each loop, as I have done here? (Ignore this secondary question if it's not relevant to main question)
Of course you can, but you need a more complex format string for your printf.
printf("%d ",i);
The above statement works by printing I, immediately followed by a space, and leaving the carriage where the print stops.
The effect that I think you have in mind is something like the following.
0
1
2
3
4
5
6
7
8
9
To make that happen, you need a couple of changes to your printf statement, as illustrated in the following complete program.
// MarchingDigits.cpp : Defines the entry point for the console application.
//
#include <stdlib.h>
#include <stdio.h>
int main(int argc, char* argv[])
{
for ( int i = 0 ; i < 10 ; i++ )
{
printf ( "%*d\n", ( i > 0 ? i + 1 : i ) , i ) ;
} // for ( int i = 0 ; i < 10 ; i++ )
return 0;
} // int main
The output generated by this program is as follows.
0
1
2
3
4
5
6
7
8
9
There are three fundamental differences between your printf statement and the one that generated this output.
Between the opening % and the closing d, I inserted an asterisk where the width goes.
I replaced the trailing space with a newline.
Between the format string and your integer argument i, I inserted another argument, in the form of a ternary expression, i > 0 ? i + 1 : i, which says, in effect, if I is greater than zero, set the width to i + 1, otherwise set the width to i. Although the else block sets the width to i, which happens to be zero, this works because printf guarantees never to truncate the output.
I've learned Heap Sort with a visual representation of it with the infamous tree diagram (here), so I set out to find a way to print one out and I've progressed very well so far. My only problem seems to be that if, there aren't any more values to fill up on the line, my program seems to print zeros for some reason.
I'm certain it's probably an error in my code, or an extra line that needs to be added but I'm also looking for advice if this was the best approach. Code below.
#include <stdio.h>
int HeapArray[] = {165, 245, 398, 426, 575, 661, 775, 895, 901, 1028, 1184, 1283, 1350,1427, 1598, 1698};
int main()
{
int i = 0, numL = 1;
int j, k;
for(k = 0; k < 6; k++)
{
if(HeapArray[i] == 0)
break;
for(j = 0; j < numL;j++)
{
printf("%d ", HeapArray[i]);
i++;
}
printf("\n");
numL *= 2;
}
return 0;
}
Things to mention:
In the other most for-loop, I've using the value 6 as the maximum lines to print, however the program stops printing on the line with the last array values in it.
I haven't implemented any alignment to make the diagram 100% accurate since it seemed easy enough to leave for last (i.e. no extra code to confuse me).
Your index i is probably going past the bound of the array
You have 16 elements, so the first time you print 1, then you print 2, then 3, etc
In total you would print 1 + 2 + 4 + 8 = 15 on the fourth line.
When you get to the last line (fifth line), you only have one element to print. However, your inner loop goes from 0 to 16, going past the bounds of the array (and so it prints 0s)
You should add a check in the inner loop to make sure you still have enough elements.
Note that I also highly recommend you actually add a 0 element to the end of the array, so you are not relying on memory outside of its bounds
This program outputs 1. I could not understand how it outputs 1 as the for loop will fail at a[2][3] which contains the value 12. So 12 will get assigned to k and the output will have to be 12.
#include<stdio.h>
int main()
{
int a[3][4]={1,2,3,4,5,6,7,8,9,10,11,12};
int i,j,k=99;
for(i=0;i<3;i++)
{
for(j=0;j<4;j++)
{
if(a[i][j]<k)
{
k=a[i][j];
printf("%d\n",k);
}
}
}
printf("Res:%d\n",k);
return 0;
}
The first time through the loop the if is evaluated as a[0][0] < k which is 1 < 99 which is true.
The second time through he loop if the if is a[1][0] < k which is 2 < 1 which evaluates as false thus the value of k is not updated
k is never reassigned another value, thus at the end k=1.
In this line you are changing the K value
k=a[i][j];
And the first itteration you run would change k to 1, that's why the second itteration would fail. On every itteration your k would be one unit less than it should be for if statement to work
Some comments:
Calling a variable k tells us nothing about what you are using it for. Had you called it arrayMin then it would have been clearer to us. Using i and j for loop indexes is fine, that is expected.
Assigning k=99 makes assumptions about the contents of the array and hence makes for fragile code. Better not to make assumptions and to start by assigning arrayMin = a[0][0]
Your program is small and simple enough that you could run through it yourself on paper. Doing that would have helped you see what was going on. Using a debugger to single-step through it would have helped as well.