I'm new to programming and currently learning C from The C Programming Language by Brian W Kernighan and Dennis M. Ritchie. I have a difficult at section 1.8. Why when I'm trying to change
for (i = 1; n > 0; --n)
into
for (i = 1; n > 0; ++n)
the output is,
0 1 1
1 2 3
2 2 3
3 2 3
4 2 3
5 2 3
6 2 3
7 2 3
8 2 3
9 2 3
Why this is happen?
Here is the full code,
#include <stdio.h>
int power(int m, int n);
main(){
int i;
for (i = 0; i < 10; ++i)
printf("%d %7d %7d\n", i, power(2,i), power(3,i));
return 0;
}
int power(int base, int n){
int p;
for ( p = 1; n > 0; --n)
p = p * base;
return p;
}
the syntax of for loop is
for (initialization expr; test expr; update expr)
which means, the first expression will be executed once,
the test expression is checked every time for ture or false every time the loop starts, and update expression is evaluated unconditionally on every time loop start.
in this case, n-- is evaluated before checking n > 0, which means the loop will stop when n becomes 0. but if you change it to n++, n will keep on increasing every time of the loop, until the integer is overflowed.
you can change the loop to the following to get output:
for (i = 1; i <= n; ++i)
In the power methods' for-loop you decrement n until in some iteration of the loop n is zero (no longer n > 0). If you now change the loop to increment n every iteration, n will continue growing until you get an integer overflow (Wikipedia: Integer overflow) and n becomes negative at which point your program will terminate.
Related
the following two programs are supposed to produce all three digit combinations of 1, 2, 3 (with repetition). They are identical in every way, other that where the loop counters are being initialized
#include <stdio.h>
int main(void)
{
short i, j, k;
i = j = k = 1;
for (; i <= 3; i++) {
for (; j <= 3; j++) {
for (; k <= 3; k++)
fprintf(stdout, "%hi %hi %hi\n", i, j, k);
}
}
return 0;
}
...This one where the counters for the three loops are being initialized outside them doesn't produce the desired output. It prints.
1 1 1
1 1 2
1 1 3
The second one...
#include <stdio.h>
int main(void)
{
short i, j, k;
for (i = 1; i <= 3; i++) {
for (j = 1; j <= 3; j++) {
for (k = 1; k <= 3; k++)
fprintf(stdout, "%hi %hi %hi\n", i, j, k);
}
}
return 0;
}
...where the counters are being initialized within each loop, produces the desired output
1 1 1
1 1 2
1 1 3
1 2 1
1 2 2
1 2 3
1 3 1
1 3 2
1 3 3
2 1 1
2 1 2
2 1 3
2 2 1
2 2 2
2 2 3
2 3 1
2 3 2
2 3 3
3 1 1
3 1 2
3 1 3
3 2 1
3 2 2
3 2 3
3 3 1
3 3 2
3 3 3
Read in a book that a for loop can be written in several forms--all of which are identical--and that the counter can be initialized, incremented, tested either inside or outside the for statement. Then why the different behavior here?
Because you don't initialize the variables i, j, k inside the loop but define them in the outer scope, their values remain saved.
In particular k remains 4, after the first loop finishes to run, then the condition k<=3 is always false and the print statement is never reached.
To write the code in the equivalent way to your book meant is that way:
#include <stdio.h>
int main(void)
{
short i, j, k;
i = 1;
for (; i <= 3; i++) {
j = 1;
for (; j <= 3; j++) {
k = 1;
for (; k <= 3; k++)
fprintf(stdout, "%hi %hi %hi\n", i, j, k);
}
}
return 0;
}
In the second one, the variables j and k are reinitialised to 1 each time the for loop is encountered.
In the first one, they are always just left with the value that they had - which means that the second time round (when i == 2 or 3), j is left at 4 from the first time round, which immediately fails the j <= 3 condition.
it's not about how you initialize the for loop, but the fact that each time that you start the for loop you don't initialize it.
for (; i <= 3; i++) {
for (; j <= 3; j++) {
for (; k <= 3; k++)
so for the first time it's fine since the values are correct, but after the 2nd and 3rd for loop finished their iterations and the first for loop reached the 2nd index the other for loops are not being initialized so their values remain 4 and the condition isn't being met, so the loops stop there.
you still need to use the initialization inside the nested for loops regardless to fix the issue.
If you initialize your variables just once, outside the for loops, then their values will never get re-initialized in the nested loops (something you need in order to generate every combination starting with 1xx, 2xx and 3xx).
In the case of the outside initialization:
After you've generated all the 11x combinations, your k variable will have the value 4, regardless of what the enclosing loops do.
So when either j or i increments to 2 and 3, your k will already be 4, hence the innermost for loop will not execute anymore.
Needless to say, the second variant of your code, re-initializes k and j every time i increments, which will then make your code reach the printf every time like you intended.
I was trying to figure out how the inner loop works in this below code but I couldn't understand. The part that I really struggle to understand is this condition part (d<n-c-1) // inner for loop//
include <stdio.h>
int main() {
int array[100], n, c, d, swap;
printf("Enter number of elements\n");
scanf("%d", &n);
printf("Enter %d integers\n", n);
for (c = 0; c < n; c++)
scanf("%d", &array[c]);
for (c = 0; c < (n - 1); c++) {
for (d = 0; d < n - c - 1; d++) {
if (array[d] > array[d + 1]) /* For decreasing order use < */
{
swap = array[d];
array[d] = array[d + 1];
array[d + 1] = swap;
}
}
}
printf("Sorted list in ascending order:\n");
for (c = 0; c < n; c++)
printf("%d\n", array[c]);
return 0;
The inner loop is a compare loop for a bubblesort. It makes sure that the last position in the array is the highest one. The next loop for c, it checks all elements but the last one (that one is already sorted).
Example:
0 1 2 3 4 (index of array)
5 3 4 2 1 (start, c=0, d=0)
3 5 4 2 1 (start, c=0, d=1)
3 4 5 2 1 (start, c=0, d=2)
3 4 2 5 1 (start, c=0, d=3)
3 4 2 1 5 (start, c=0, d=4)
The next loop, c will be 1 and d will only increase to 3. This will leave the highest value (5) on the highest index (4).
Well, the outer loop loops c from 0 to n-1;
When c is 0, the inner loop loops d from 0 to n-1
when c is 1, the inner loop loops d from 0 to n-2
when c is 2, the inner loop loops d from 0 to n-3
etc.
Graphically:
*********
********
*******
******
*****
****
***
**
*
As far as I can understand your question, its about the condition part of this for loop:
for (d = 0; d < n - c - 1; d++) {}
Condition is : d < n - c - 1 which is same as d < (n - c - 1)
which means this for loop will execute till d is less than (n - c - 1)
This appears to be a Bubble Sort algorithm. The first loop for (c = 0; c < (n - 1); c++) is the number of main iteration it needs to complete the sort and the second for loop for (d = 0; d < n - c - 1; d++) is to set the limit of how many compare and swap is needed.
For the first iteration it should compare and swap the whole array, the second iteration is to the "end of array - 1" and so forth.
You can see a nice visualization here.
Concerning my determination for output.It's 1 40 1 While using C it displays output as 0 41 1 How's that possible?What wrong step I'm going into?
#include<stdio.h>
#include<conio.h>
void main(void)
{
clrscr();
int n,a,b;
n = 400;
a = n % 100; //remainder operation
b = n / 10; //division operation
n = n % 10; //remainder operation
printf("%d %d %d",n++,++b,++a); //post-,pre-,pre- increment used
getch();
}
What your compiler prints is correct. Here is the program flow:
#include<stdio.h>
#include<conio.h>
void main(void)
{
clrscr();
int n,a,b;
n = 400; // n has value 400
a = n % 100; // a has value 0
b = n / 10; // b has value 40
n = n % 10; // n has value 0
// n++ evaluates to 0, afterwards n has the value 1
// ++b evaluates to 41, afterwards b has the value 41
// ++a evaluates to 1, afterwards a has the value 1
printf("%d %d %d",n++,++b,++a);
// Thus, 0 41 1 is printed.
getch();
}
Notice especially that the postfix-incrememnt operator n++ returns the value of n unchanged and then changes n. That's why 0 is printed in the first column.
Can anyone explain to me how does this loop works? I understand that the first operator counts its remainder, the second counts its division result, but I can't understand how does it sum them using the loop? Here's the code:
// Calculate the sum of the digits of the number N.
int N, S, Z;
S = 0;
printf("Input N\n");
scanf("%d", &N);
while(N != 0) {
Z = N % 10;
N = N / 10;
S = S + Z;
}
printf("Sum = %d\n", S);
This while loop adds all the digit of your number referred in by N. It add's all the digit by taking remainder of number when divided by 10. And everytime, it eliminates the last digit of the number. So if your number is 326, it will work like:
326 != 0
Z = 6
N = 32
S = 6
32 != 0
Z = 2
N = 3
S = 8
3 != 0
Z = 3
N = 0
S = 11
0 == 0 come out of loop
print value of S i.e. 11
It's basically a sum of digits of an integer number.
Example:
input ==> 1234
output ==> 4+ 3+ 2 + 1 = 10
Code Break down:
Initialize S [sum] to 0.
Loop:
Z = N % 10; , store the remainder of N after %10 into Z.
N = N / 10; , divide the contents on N by 10 and store the result back in N.
S = S + Z;, sum the content of S with the value in Z.
after that, check the modified value of N is 0 or not. If not, continue [1,2,3..)
Suggestion:
Always check the success of scanf("%d", &N);. If by any chance, scanf() fails, your code is trying to access uninitialized variable N, which may very well lead to undefined behaviour.
The loop will execute until the n value become zero. For example
N=123
Then the first time values of the variables is
Z:3 : N:12 : S:3
Second time
Z:2 : N:1 : S:5
Third time
Z:1 : N:0 : S:6
Finally the answer of S will be 3+2+1=6.
Let's for a example take 657:
Z = N % 10; // This line will store 7 in Z
N = N / 10; // this line will convert N to 65
S = S + Z; // and finally this line will add 0+7
I want to sort a 2*n matrix, n is given in the input. Make a program to output a matrix. Here is the requirement:
the first column MUST be sorted in ASC, and
the second column in DESC if possible.
For example, let n = 5, and the matrix is
3 4
1 2
3 5
1 6
7 3
The result should be
1 6
1 2
3 5
3 4
7 3
So I write down the code like this. First line input the value n, and the following lines like above.
#include <stdio.h>
#define TWO_16 65536
#define TWO_15 32768
int v[100000][2];
int z[100000];
int vec[100000];
int n;
int main()
{
int i, j;
scanf ("%d", &n); // give the value of n;
for (i = 1; i <= n; i++) // filling the matrix;
{
scanf ("%d%d", &v[i][0], &v[i][1]);
z[i] = TWO_16 * v[i][0] + TWO_15 - v[i][1];
vec[i] = i;
}
for (i = 1; i <= n; i++)
for (j = 1; j <= i; j++)
{
if (z[j] > z[i])
{
int t = vec[i];
vec[i] = vec[j];
vec[j] = t;
}
}
for (i = 1; i <= n; i++) // output the matrix
printf("%d %d\n",v[vec[i]][0],v[vec[i]][1]);
return 0;
}
But in gcc, the output is
1 6
3 5
3 4
1 2
7 3
What's more, when the first line is changed to "1 2" and the second is changed to "3 4" in input, the result also changed.
What's the problem of my code?
Additional information:
I use z[] because I use a function that satisfy the requirement of this problem, so I can simply sort them. And vec[] stores the original index, because moving arrays may cost lots of time. So v[vec[i]][0] means the 'new' array's item i.
Note that v[0] is NOT used. n is less than 100000, not equal.
You are comparing values stored in z[], but swapping elements of vec.
So when in the begginig you have:
i vec z
------------------
1 1 z[1]
2 2 z[2]
3 3 z[3]
...
After for e.g. swapping 2 with 3
i vec z
------------------
1 1 z[1]
2 3 z[2]
3 2 z[3]
...
you will have improper mapping between vec and z.
So in another iteration you will again compare z[2] with z[3] and again you will have to swap elements of vec. That's why you should at least also swap elements of z or index elements of z using elements of vec
i vec z
------------------
1 1 z[vec[1]] = z[1]
2 3 z[vec[2]] = z[3]
3 2 z[vec[3]] = z[2]
...
Adding this should do the trick
...
int t = vec[i];
vec[i] = vec[j];
vec[j] = t;
//Add this also when swapping vec
t = z[i];
z[i] = z[j];
z[j] = t;
...
Array index start with 0, so your for cicles must start from 0
if (z[j] > z[i]): you want to sort v but you are comparing z and sorting vec. By sorting vec and comparing z bubble sort cannot work. You must use the same array.