Why is my loop not going infinite - c

#include <stdio.h>
#include <cs50.h>
int main(void)
{
int n;
printf("Please give me an integer greater than zero!\n");
n=GetInt();
if(n<0)
{
printf("You are giving me a bad value!\n");
return 1;
}
for(int i=n-1;i<n;n--)
printf("%d\n",n);
return 0;
}
I would like to know why the loop is not going to infinity if the user enters in a number for n. Lets say that the user puts in 40 for n; wouldn't i always be n-1, so 39 and n being 40, then i becomes 38 when n becomes 39 and so on — so wouldn't that make an infinite loop?

for(int i=n-1;i<n;n--)
Lets draw a (really short) table for n = 40:
i | n
-----+-----
39 | 40 i < n ? true
39 | 39 i < n ? false
Thus, we'll exit the loop after the 1st iteration.
Clarification:
I guess you're confused because you think that i is updated in each iteration, but that's the point - it doesn't, its value is fixed and only n is changing.

This loop only runs once. Consider:
for(int i=n-1;i<n;n--)
With n == 40, on the first iteration, i = 39.
The condition i < n is true (39 < 40 == true), so we go in to the loop for the first time.
At the end of the first loop, n gets decremented to 39
The condition i < n is false (39 < 39 == false), so we don't get a second time through the loop.
Now, what happens if we make n increase instead of decrease? Will that run forever?
for(int i=n-1;i<n;n++)
The answer is "maybe, but probably not":
Eventually, n will reach the largest value that can be stored in an integer, INT_MAX (defined in limits.h, and on my system it is 2,147,483,647).
Making an integer larger than INT_MAX causes integer overflow.
The result of integer overflow on a signed integer is undefined, which means the result could be anything (and indeed, your program could crash).
On most systems, however, the value will probably wrap around to INT_MIN, or -2,147,483,648.
If this happens, i < n will be false, and your loop will terminate.
But, since integer overflow on signed integers is undefined behaviour, you can't be sure that this will happen. It is better to write your program to avoid this situation.
If you really want it to run forever - just write:
while(1) { ... }
or
for(;;) { ... }
These two loops have the advantage that they are common ways to write an infinite loop, and so they are easy for other programmers to read.

The reason is that i is never decremented, so it does only 1 loop:
i=39 n=40
i=39 n=39 -> stop
In order to decrement also i you should write:
for(int i = n-1;i<n;n--,i--)

i is only ever set once at the start of the loop. For example if the user enters 10 then i is 9 for the 1st iteration. By the 2nd iteration n is decremented by 1 and i is still 9.

n will underflow somewhen because int is signed and has a value range of -2147483648 to 2147483647 for example (x86).
Somewhen n will get more positive than i.
Edit:
The loop has at most 1 iteration.
Edit 2:
The loop would have no iterations if n would have the value -2147483648 for example because -2147483648 - 1 will make the value positive (two complement integer arithmetic). But this could never the case because the pre condition is that n may not be negative.

Your for loop:
for(int i=n-1;i<n;n--) {
printf("%d\n",n);
}
Translates into the following while loop:
{
int i = n - 1;
while (i < n) {
printf(%d\n", n);
n--;
}
}
The first clause of the for statement performs initialization. It is not repeated at each iteration, but only once. Thus, i never changes value, and so the loop ends after a single iteration.

This happens because you are decrementing n. At the second iteration i < n is false, you are exiting from the loop.

What will happen is:
//Example n = 100
for (int i = 100 - 1; 99 < 100; 100--)
//We now have 99 < 99 on the next loop
//After that you will have 99 < 98 etc.. it will only run once
To make the loop you want use:
for(int i = n-1; i > n ; n--)
To make an endless loop use:
for(;;) //or while(true)

your condition is wrong in the for loop..in your loop i is not changing only n is changing
try this
for(i=n-1;i<n;i--)
{
printf("%d\n",i);
}

you written perfect for loop...
for(int i=n-1;i
#include<stdio.h>
#include<conio.h>
int main()
{
int i;
for(i=0;;)
{
printf("%d",i);
}
return 0;
}
or you can do anything else....
to put in infinite simply make ;; in the other two condition in loop.

Related

I don't know what I'm doing wrong with this Array

I'm trying to separate the numbers of a sequence, and store them all in an array.
For what the little I have seen of C, I am doing nothing wrong, and the program compiles perfectly, but the moment it goes to print the numbers, it just doesn't work.
The explanation of what I'm trying to do is in the end.
long int number;
do
{
number = get_long("number:\n");
}
while (number<1 || number>9999999999999999);
int numbers[16], n;
//We separate the numbers, from right to left
for (long int I=10; I>100000000000000000; I*=10)
{
for (long int J=1; J>100000000000000000; J*=10)
{
for (n=0; n>16; n++)
{
numbers[n]=(number%I)/J;
}
}
}
printf("%i\n", numbers[1]);
It is supposed to accept numbers of 1 digit up until 16 digits, and separate each digit.
For example, if we had 16, it would separate 1 and 6 into two digits, making the 6 the first digit, and the 1 the second, so it would start counting from right to left. It's supposed to store each digit in an array of 16 spaces. Then I would just print the second digit, just to make sure it does work, but when I run it, it just gives me 0; meaning it doesn't work, but I see no problem with it.
It probably is that I'm either too inexperienced, or I don't have the necessary knowledge, to be able to see the problem in the code.
You have incorrect loop termination checks, so the loops are never entered.
After reversing > to <, you end up evaluating the body of the inner loop 16*16*16 = 4096 times even though there are only 16 digits. There should only be one loop of 16 iterations.
A long int is not is only guaranteed to support numbers up to 2,147,483,647. Instead, use one of long long int, int_least64_t or int64_t, or one of their unsigned counterparts.
You were attempting to write the following:
uint64_t mod = 10; // Formerly named I
uint64_t div = 1; // Formerly named J
for (int n=0; n<16; ++n) {
numbers[n] = ( number % mod ) / div;
mod *= 10;
div *= 10;
}
Demo
But that's a bit more complicated than needed. Let's swap the order of the division and modulus.
uint64_t div = 1;
for (int n=0; n<16; ++n) {
numbers[n] = ( number / div ) % 10;
div *= 10;
}
Demo
Finally, we can simplify a bit more if we don't mind clobbering number in the process.
for (int n=0; n<16; ++n) {
numbers[n] = number % 10;
number /= 10;
}
Demo
All of your for loops are using operator> when they should be using operator< instead. Thus the loop conditions are always false (10 is not > than 100000000000000000, 1 is not > than 100000000000000000, 0 is not > than 16), so the loops don't get entered at all, and thus numbers[] is left unfilled.
Fixing that, you still have a logic problem. Think of what the result of (number%I)/J is when number is 16 and I and J are large values. The result of operator/ is typically 0! On some loop iterations, numbers[] gets populated with correct values. But other iterations will then overwrite numbers[] with 0s. Once all of the loops are finished, only the 0s are left.
This Online Demo demonstrates this in action.
If using a long variable, the value ranges are: -2147483648 to 2147483647 (in most C implementations, as noted by #Eric P in comments)
So the expression while (number<1 || number>9999999999999999); (and similar) do not make sense. As a number, number will never approach 9999999999999999. Same for expression: ...J>100000000000000000; J*=10). (and its really moot at this point, but > should be <)
Consider using a string approach:
Using a null terminated char array (C string) to hold initial value, the essential steps are pretty straight forward and could include the following:
char number[17];//room for 16 characters + null terminator
scanf("%16s", number);//string comprised of maximum of 16 digits
len = strlen(number);
int num_array[len];//using VLA
memset(num_array, 0, sizeof num_array);//zero array
for(int i = 0;i < len; i++)
{
if(number[i] < '0' || number[i] > '9') break;//qualify input. Break if non-numeric
num_array = number[i] - '0';
}

Variable is exceeding specified limit in for loop

I have written code to find the units and tens digit of a number,but am facing a problem when the number is greater than 99.The value of i has been set to less than 10 inside the for loop but when i execute the code with no=100,I find that i has a value of 10.
Why is this happening?
#include <stdio.h>
int unit(int x){
return x%10;
}
int ten(int x){
int temp=x-unit(x);
if(temp==0){
return 0;
}
else{
for(int i=1;i<10;i++){
if(temp%(i*10)==0 && temp/(i*10)==1){
return i;
}
}
}
}
int main(){
int no=100;
printf("%d",ten((no)));
return 0;
}
Think about what happens when the number is greater than 99. You will not be able to find a value of i b/w 1 and 9 such that the expression in the if is true. You will need a value of i > 10, but of course, then it wouldn't be the tens digit of the number.
Your method only works for a specific case, ie, when the number is b/w 1 and 10^2. Sure, you could write some more code to make it work for numbers b/w 1 and 10^3, but that would just be a pain in the ass. Even then, you'd have to write more code if the number is greater than that.
Try to think of a solution for the general case. To do that, two facts would be very useful:
Dividing using / only gives the integer part of the answer. Eg: 66/10 = 6
% This operator gives you the remainder. Eg: 59%10 = 9
1) In the else block of ten() you are returning a value only if some condition is met. If the condition does not satisfy you are not returning anything. In that case a garbage value may be printed.
2) To get the tenth digit, that is a lot of work. Just change the function body to -
int ten(int x) {
return (x % 100) /10;
}
The numbers upto 99 gets correct result because the condition satisfies. Lets take 99 as an example. After unit digit subtraction you got 90. When i becomes 9, the temp%(i*10) becomes 0 and temp/(i*10) becomes 1.
When number is 100, after unit digit subtraction the number remains same(i.e. 100). But for values of i from 1 to 9 temp/(i*10) never becomes 1 and the loop quits, resulting in the absurd behavior. You will get the same behavior for all the numbers that are greater than 99 using your code.

An example of for loop in C leading to an infinite loop

The following program was cited as going into an infinite loop:
#include<stdio.h>
int main()
{
int n;
for(n = 7; n!=0; n--)
printf("n = %d", n--);
getchar();
return 0;
}
On analyzing, I do find that at one point the value of n does become 0 and right then, the loop should terminate.
Won't it happen such that when it enters the loop for the first time, the value is 7, then it becomes 6, and since that there are 2 post-decrements per iteration?
But, why does that not happen?
Each loop iteration actually decreases n by two, and the comparison n != 0 always sees an odd value for i and hence never terminates.
In particular, just before the iteration in question, n is first decremented to 1 by n-- in the loop header (since this must occur after the end of the previous iteration, just before evaluation of the condition n!=0).
Then, printf("n = %d", n--); is evaluated, printing n = 1, while postdecrementing n to zero. After the end of the loop body, n is decremented again by n-- in the loop header, making it -1, just before the condition n!=0 is evaluated to determine whether the loop should continue.
As a result, n!=0 is true every time it is evaluated (in particular, it is not evaluated at the instant that n is zero, since the n-- in the loop header must first complete)
It's because of the second decrement in the print here:
for(n = 7; n!=0; n--)
printf("n = %d", n--);
That makes the sequence of checks against n go 7, 5, 3, 1, -1, ... There are an even number of values for an int so this will form a cycle upon underflow that leaves out the even numbers, including 0.
Remember that the for loop condition is evaluated just before each loop iteration, and after the decrement in the loop itself. It isn't tested while the loop is running.
try doing this
#include<stdio.h>
int main()
{
int n;
for(n = 7; n>=0; n--)
printf("n = %d", **--n**);
getchar();
return 0;
}

C - Why is a for loop getting stuck when using a uint64_t counter, whereas a while loop isn't?

When I use a for loop with a uint64_t as a counter, it gets stuck forever, even though the condition seems to be well defined.
Offending MCVE
#include <stdio.h>
#include <inttypes.h>
int main() {
uint64_t i;
for (i = 15; i >= 0; i--) { printf("%"PRIu64" ", i); }
return 0;
}
Partial output
15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0 18446744073709551615 18446744073709551614 18446744073709551613 18446744073709551612 18446744073709551611 18446744073709551610 18446744073709551609 18446744073709551608 18446744073709551607 18446744073709551606 18446744073709551605 18446744073709551604 18446744073709551603 18446744073709551602 18446744073709551601 18446744073709551600 18446744073709551599 18446744073709551598 18446744073709551597 18446744073709551596 18446744073709551595 18446744073709551594 18446744073709551593 18446744073709551592 18446744073709551591 18446744073709551590 18446744073709551589 18446744073709551588 18446744073709551587 18446744073709551586 18446744073709551585 18446744073709551584 18446744073709551583 18446744073709551582 18446744073709551581 18446744073709551580 18446744073709551579 18446744073709551578 18446744073709551577 18446744073709551576 18446744073709551575 18446744073709551574 18446744073709551573 18446744073709551572 18446744073709551571 18446744073709551570
It seems it's ignoring the stop condition, and so it rolls over.
However, when changing it to an "equivalent" while loop, everything works fine:
Correct MCVE
#include <stdio.h>
#include <inttypes.h>
int main() {
uint64_t i = 16;
while (i--) { printf("%"PRIu64" ", i); }
return 0;
}
Complete output
15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0
Am I missing something regarding the use of uint64_t counters in a for loop? Any help is greatly appreciated!
The condition i >= 0 is alwaays true if i is an unsigned type. Decrementing an unsigned zero will not produce a negative value, but the counter will wrap to the maximum representable number for the given type.
C represents ranges with an inclusive lower bound and an exclusive upper bound. For example, an array of N elements has indices 0 through N - 1. The upper bound itself isn't a valid array index.
This convention means that you use a value before incrementing it, but deceremt it before using it. Consider a simple stack:
stack[nstack++] = x; // push a value
x = stack[--nstack]; // pop a value
The same logic goes for loops: When you move forwards, use the value before you increment it:
for (var i = 0; i < N; i++) { use(i); }
When you move backwards, decrement first and then use it:
for (var i = N; i-- > 0; ) { use(i); }
This loop is equivalent to your while. The update section, which happens after processing the body, is empty here. The check is performed on the value before entering the loop; the loop body has the updated value.
This backwards loop might look awkward with the empty update section, but in other ways it is orthogonal to the forward version:
It uses the actual bounds; there's no need to start with N - 1;
It works equally well for arbitrary bounds as long as they follow the convention of inclusive lower and exclusive upper bound;
The test is a pure inequality, not a greater/less-then-or equal comparison.
The expression i >= 0 is always true if i is of an unsigned integer type. The alternative and simple way is to change it into:
uint64_t i;
for (i = 15; i != -1; i--) { ... }
This works no matter if i is a signed or an unsigned integer. In the uint64_t case, -1 will first get converted into 0xFFFFFFFFFFFFFFFF and then compared with i.
If you want to get rid of the compile warning, change it into:
i != (uint64_t)-1
but you need to ensure the uint64_t is exactly the type of i.

Decrementing while loop in c

Is it possible to decrement the array size in a while loop in C by more than x--. For example, can you decrement an array by a third of the array size with each iteration?
int n = 10;
while (n < 0)
// do something
(round(n/3))-- // this doesn't work, but can this idea be expressed in C?
Thank you for the help!
You can use any expression:
int n = 10;
while (n > 0) // Note change compared with original!
{
// Do something
n = round(n/3.0) - 1; // Note assignment and floating point
}
Note that you can only decrement variables, not expressions.
You could also use a for loop:
for (int n = 10; n > 0; n = round(n/3.0) - 1)
{
// Do something
}
In this case, the sequence of values for n will be the same (n = 10, 2) whether you round using floating point or not, so you could write:
n = n / 3 - 1;
and you'd see the same results. For other upper limits, the sequence would change (n = 11, 3). Both techniques are fine, but you need to be sure you know what you want, that's all.
Yes, it is possible to add or subtract any number to your variable n.
Usually, if you want to do something a very predictable number of times, you would use a for loop; when you aren't sure how many times something will happen, but rather you are testing some sort of condition, you use a while loop.
The rarest loop is a do / while loop, which is only used when you want to execute a loop one time for certain before the first time the while check occurs.
Examples:
// do something ten times
for (i = 0; i < 10; ++i)
do_something();
// do something as long as user holds down button
while (button_is_pressed())
do_something();
// play a game, then find out if user wants to play again
do
{
char answer;
play_game();
printf("Do you want to play again? Answer 'y' to play again, anything else to exit. ");
answer = getchar();
} while (answer == 'y' || answer == 'Y');
There is no array in your code. If you wan't n to have a third of its value on each iteration, you can do n /= 3;. Note that since n is integral then the integral division is applied.
Just like K-Ballo said there is no array in your example code but here is an example with an integer array.
int n = 10;
int array[10];
int result;
// Fill up the array with some values
for (i=0;i<n;i++)
array[i] = i+n;
while(n > 0)
{
// Do something with array
n -= sizeof(array)/3;
}
But be careful in the example code you gave the while loop is checking if n is less than zero. As n is intialised to 10 the while loop will never be executed. I have changed it in my example.

Resources