Sorting program query - c

I came across a sorting code in quora and I was very confused with some of the lines of code, if someone explains it to me then it will be a big help.
The code is as follows:
#include <stdio.h>
int array[1000001] = {0};
int main(){
int i,j;
scanf("%d",&j);
int x;
for (i=0;i<j;i++){
scanf("%d",&x);
array[x]++;
}
for (i=0;i<1000001;i++){
while(array[i]>0){
printf("%dn",i);
array[i]--;
}
}
return 0;
}
Can someone explain what is happening in
for(i=0;i<j;i++)
{
scanf("%d",&x);
array[x]++;
}
and here
for (i=0;i<1000001;i++)
{
while(array[i]>0)
{
printf("%dn",i);
array[i]--;
}
}
and what does this dn stands for?

This is by far the best reason not to copy anything from quora or other sources without understanding what it is doing.
No matter what, it doesn't ensure if any of the inputs is right or not.
for(i=0;i<j;i++)
{
scanf("%d",&x);
// Are you sure that 'x' is always a valid int value and is less than your array size?
// No, if a monkey enters 200000 here, kabooom!
array[x]++;
}
In this for loop, which will iterate for j times, an input of type int is taken, and value at that index will be incremented, to know what value was entered by marking that index as 1.
for (i=0;i<1000001;i++)
{
while(array[i] > 0)
{
printf("%dn",i);
array[i]--;
}
}
Its bad by design, because if I have entered only 3 numbers to sort, it still iterates for 1000001 times.
But, it works for an expected/deliberately bounded input values.
For example, lets say user entered 6 values: 4, 2, 7, 0, 6, 8
So, j = 6, and contents of array would be all zeroes except for 4th, 2nd, 7th , 0th, 6th and 8th index.
Now this while loop does a job: it checks if ith index is set, i.e. if that index was entered by user not not. So the code inside while loop will only be executed for 4th, 2nd, 7th , 0th, 6th and 8th indexes.
To explain how the value is printed, lets dry run the code, Initially i is 0.
// Is ith index 1?
while (array[i] > 0) // i is 0
{
// Yes it is,
printf("%d ", i);
// See above, Prints 0 - not 1!
// Printing 'i' is the trick, instead of printing array[i]..
array[i]--; // Note, makes it zero!
}
for next iteration, i is 1
// Is ith index 1? - No, so move on to next index
while (array[i] > 0) // i is 1
{
//
}
lets say iteration has reached 7th index,
// Is ith index 1?
while (array[i] > 0) // i is 7
{
// Yes it is,
printf("%d ", i);
// See above, Printing 'i' is the trick,
// instead of printing array[i]..
array[i]--; // Note, makes it zero!
}
This will sort the numbers, without a doubt, but with some predefined constaints.
Additionally, you can/should add some implementation to get the sorted values in an array, based on if your are required to do it or not.
Finally, "%dn" is not a format specifier. It was probably meant to be "%d\n".
If it is kept unchanged the way it is, it will append n as a character after every number it prints, pointless.

This attempts to read in a number and ingores that the reading might fail.
scanf("%d",&j);
Afterwards j is therefor potentially uninitialised.
This makes a loop, which will do j steps, i.e. potentially an uninitialised number of loops.
for(i=0;i<j;i++)
This attempts to read a number once per loop, without caring about potential failures.
scanf("%d",&x);
It then uses the potentially uninitialised or non-updated number x to access an array.
array[x]++;
In case x is inconsitently for any reason, the access may well be beyond the array, which introduces potential undefined behaviour.
Should it however succeed, the array entry is increased by one.
Most of the array entries are implicitly initialised by the way, not because of the {0}.
So the array entry at the index which matches the read number is counted up.
In total, the number of occurrences of each number in the hopefully correctly formatted input is counted.
Nothing is sorted.
Yet.
This loops over all entries in the array, starting at the lower indexes, i.e. at the lower values of occurred values in the input.
for (i=0;i<1000001;i++)
If an entries in the array is not 0, the index/value is printed and the count is decreased until the entry is zero.
{
printf("%dn",i);
array[i]--;
}
I.e. the current index/value is printed as often as it has been seen in the input.
Implicitly, any value which did not occur in the input is not printed.
Concerning the "%dn" have a look here:
Is %dn a format string?
The most plausible explanation why the "n" does not occur in output, while the output does contain otherwise unexplained newlines, is that the "n" is actually an "\n" in the code which produced the shown output but got lost when posting the code.
(I agree with #WedaPashi that the code will have trouble with negative numbers in input on top of all the other vulnerabilities. Well spotted.)
I believe that the apparent speed of the solution for low values is sabotaged by looping over many empty entries for high values. It gives misleadingly fast output, while taking a long time doing nothing to reach the end of the array before actually being finished.

Related

my for loop is not working properly in my code it keeps stopping after 1st cycle?

#include<stdio.h>
int main()
{
int i,n;
int arr[10]={};
printf("\n print all the entered elements in array");
printf("\n enter the value of n");
scanf("%d",&n);
for(i=0;i<=n;i++)
{
printf("\n element no %d",n);
scanf("%d",arr[i]);
}
printf("\n the reversed elements are");
for(i=n-1;i<=0;i--)
{
printf("\n the numbers are %d",arr[i]);
}
return 0;
}
hey there this is my c program code and i have first enter the no of elemnts as how many element i want in that array and the have to print it in reverse order and i am facing some problem with this as when my first loop starts after 1 complete cycle or after taking one input on element i=0 it stops. i dont have any idea whats going on here so pls help me..
You want the address of the array element, not its value.
So, change
scanf("%d",arr[i]);
to
scanf("%d",&arr[i]);
(And, for your own sake, learn to not ignore the return value of scanf().)
Also, if you enter N as number of elements, then your code will need N+1 numbers entered, hoping that N+1 is less than 10.
This is because for(i=0;i<=n;i++) will need numbers entered for 0,1,2, ...N, because of the <=, you probably want <. You will then be asked one number less, which should fix the problem you describe. I.e. you should then see the "the reversed elements are" output after entering N elements. Your program currently seems to "stop" because it waits for another number being entered.
When you fixed that the next problem you encounter will be the one described in the comment by Tom Karzes. It prevents the output of "the numbers are".
Your continuation test is backwards. You want i >= 0, not i <= 0, since i is counting down to zero.
This means that, with your code as is, the body of the second loop will never be executed because with any meaningful n value, i<=0 for i==n-1 will already be false for the first check and the loop is immediatly done.

Having trouble understanding the for loop

#include <stdio.h>
int n, a[100001], x, y;
int main() {
scanf("%d", &n);
while (n--) {
scanf("%d.%d", &x, &y);
a[x*1000+y]++;
}
for (int i = 0, c = 0; i <= 100000; i++) {
while (a[i]) {
--a[i], ++c;
printf("%d.%03d\n", i / 1000, i % 1000);
if (c == 7) return 0;
}
}
return 0;
}
This is the code that receives an integer n, then the program is expected to receive n number of double or integer variables.
The program is supposed to print out the smallest 7 variables among the input variables to 3 decimal points.
Now the question is i can't seem to figure out how this code in for loop
while (a[i]) {
--a[i], ++c; // <- specifically this part
printf("%d.%03d\n", i / 1000, i % 1000);
if (c == 7) return 0;
}
generates 7 smallest variables.
Any help would be much appreciated
Suppose 8.3 is an input, then you are storing the 8003rd index of the array to 1. i.e a[8003]=1. if 8.3 is input twice then a[8003] will be equal to 2.
So in the for loop when i=8003, a[8003] is non zero that that means there was an input 8.3. So it is considered in the top 7 smallest input values and the loop exits when count reaches 7.
As hellow mentioned, This is bad code and if you are a student, stay away from such programming style (Not just student, everyone should stay away).
What this code does is it creates sort of "Look-up" table.
Whenever a number is entered, it increases a count at that array instance.
e.g. If I input 3.2, it increments a[3002] th location. Code for this is:
scanf("%d.%d", &x, &y);
a[x*1000+y]++;
x = 3 and y = 2 so a[3*1000+2]++ --> a[3002] = 1
(Note: Code assumes that array a is initialized with 0 - another bad habit)
Now say I entered 1.9, code will increment a[1009]. If I enter 3.2 again, a[3002] will be incremented again.
This was input part.
Now code parses entire array a starting from 0. At first it will encounter 1009, code will print 1.9 and keep on parsing array.
When it finds 7 non=zero locations, loop exits.
When you enter same number again, like 3.2, while(a[i]) executes twice printing same number again.
As smaller number will be at lower location in array and array parsing starts from 0, it prints smallest 7 numbers. If you reverse the for loop, you can print 7 biggest numbers.
The answer here is how the input data is being stored.
User entered values populate array a. It does not store actual entered numbers, but a COUNT how many times the value was entered (code makes lots of assumptions about data sanity, but lets ignore that)
The data is naturally Sorted from smallest to largest, so to find 7 smallest inputs you just take first 7 values (iterations tracked by index i, c tracks how many values we already did print out) where the COUNT is not zero (a[i], non zero value indicates how many times user entered corresponding value)

Wasn't able to figure out why the value of integer changed, even while debugging my program?

code:- to reverse the elements of array by swapping
compiler:- code blocks 13.12
whenever i tried to compile and run this code an unknown value appeared instead of that reversed array, after debugging i realized that code is working just fine upto that swapping section, the real problem begins after that while printing the value of c instead of assigning as zero is automatically assigned into the value i put for n in the start of the program;
and so it prints out the value of arr[n] which has not been assigned by me, as it is a garbage value
i've compiled it online, same issue. please help me i'm very curious to figure out my fault.
#include<stdio.h>
int main()
{
int n,c,t,end,arr[100];
//entering the number of elements
printf("enter the number of elements of array\n");
scanf("%d",&n);
end=n-1;
//printing the array
printf("enter your array\n");
for (c=0;c<n;c++)
scanf("%d",&arr[c]);
//swapping the array's value
for (c=0;c<n/2;c++)
{
t=arr[c];
arr[c]=arr[end];
arr[end]=t;
end--;
}
//printing the new array
printf("reversed array is\n");
for (c= 0;c<n;c++);
/*at this point the value of c becomes equal to the n (i.e, the number of
elements of the array)*/
printf("%d\n",arr[c]);
return 0;
}
The last for loop has on its end ;
Delete them
Are you trying to reversed array, change the for statement loop ends ';' remove the semi colon in printing.
printf("reversed array is\n");
for (c= 0;c<n;c++)
/*at this point the value of c becomes equal to the n (i.e, the number of
elements of the array)*/
printf("%d\n",arr[c]);
Replace
for (c= 0;c<n;c++);
by
for (c= 0;c<n;c++)
Acually your code
for (c= 0;c<n;c++);
printf("%d\n",arr[c]);
is equivalent to
for (c= 0;c<n;c++)
{
}
printf("%d\n",arr[c]);
The error is here:
printf("reversed array is\n");
for (c= 0;c<n;c++); <---------------- ERROR
printf("%d\n",arr[c]);
You see, this semicolon makes the for loop's body to be empty.
So the code is equivalent to this:
printf("reversed array is\n");
for (c= 0;c<n;c++)
; // empty body
printf("%d\n",arr[c]); // c equals n
So, when you try to print your array, c has a value equal to n, thus you are going out of bounds, which leads to Undefined Behavior.
Your index counter c holds the last element of the array which is always '\0'. Arrays are basically pointer to the first element and the end is indicated by '\0' aka terminating character at the end. when you did for(c = 0; c < n; c++);c will increment and become equal to 'n'. I think I understand why you thought this should've retuned c = n-1 since you used c < n not c <= n however the whole condition will be executed up too c++ before its determined whether to execute the coming closure or not (In this case, it doesn't matter since the for loop does not have a closure). so the whole thing ends up giving c = n.
I hope this make it clear but just as an advice, try to put space between operators and practice best indentations while learning programming as it might be hard to get the habit once you're used to it.
I think that yur mistake is this:
for (c= 0;c<n;c++);
n is the number of elements (p.e. 5 elements), but your last element is in arr[n-1].
Try with for (c= 0;c<(n-1);c++); or printf("%d\n",arr[c-1]);

(C) Allow infinite of numbers to be entered, reverse the order of entered numbers & end program when 0 is entered

I'm working on a project at the moment where I have to allow a user to enter an infinite amount of numbers and reverse the order of those entered numbers and end the program if 0 is entered. I did something similar, except the one I did set the amount of numbers the user could enter, so for example in the code below, I allowed the user to enter only three numbers, reverse the order and end when -1 is entered.
#include <stdio.h>
#define MAX 3 // Defining max amount of numbers to be entered to 3
main()
{
int numbers[MAX], i, end;
printf ("Please enter %d integers:\n", MAX);
for (i = 0; i < MAX; i++){
scanf("%d", &numbers[i]);
if (numbers[i]==-1){ // Loop ends when -1 is entered
for (end=i; end<MAX; end++)
numbers[end]='\0'; // Nulls the value of blank locations in the array
i=MAX;
}
}
printf ("\nThe values in reverse order are:\n");
for (i = MAX-1; i >= 0; i--)
{
if(numbers[i]!='\0') // Will not print null values in the array
printf("\n%d ", numbers[i]);
}
return 0;
}
How can I go about achieving this? I'm guessing I won't be able to use an array, and I'm pretty new to this so...
No, arrays can't be grown dynamically (not without some extra tinkering, see comment below) so they can't hold an infinite amount of items.
You'll need some structure you can grow, C doesn't provide one so you'll have to use a third party implementation or write your own. A stack fits your problem the best.
Also, your loop will have to go on until -1 is entered. Either an infinite loop with a break statement, or a do-while loop that checks the entered number.
EDIT: The original question targeted C++, my original answer, below, is no longer relevant.
You want to look into C++'s STL. std::vector, std::deque or std::stack for example, would be useful in your case.
You can use a std::vector to do this.
Here's the declaration of your std::vector. Where the tells the vector you want it to be a vector of type int
std::vector<int> numbers;
Then to add to the end of the std::vector you use push_back(), which puts the integer onto the back of the array. The size of the vector will dynamically increase as you push more elements on to the back.
int input;
numbers.push_back(input);
Then to iterator through it you can use a reverse iterator or just iterate the same way you have been doing it using numbers.size() to find out how many elements are in the vector.

What am I doing wrong (C arrays)?

I'm just a beginner at C.
I'm trying to make a simple program to arrange the user-entered digits in ascending order. I have figured out the solution but can't understand why my other code wouldn't work :(
-------------------------------------------------------------------------
working code:
-------------------------------------------------------------------------
#include <stdio.h>
int main()
{
int i,j,num[10];
printf("Enter 10 numbers\n");
for (i=0;i<10;i++)
{scanf("%d",&num[i]);}
for (i=0;i<9;i++)
{
for (j=i+1;j<10;j++)
{
if (num[i]>num[j])
{
num[i]+=num[j];
num[j]=num[i]-num[j];
num[i]=num[i]-num[j];
}
}
}
printf("The numbers in ascending order are:");
for (i=0;i<10;i++)
{
printf(" %d",num[i]);
}
return 0;
}
-------------------------------------------------------------------------
code that won't work:
-------------------------------------------------------------------------
#include <stdio.h>
int main()
{
int i,j,num[10];
printf("Enter 10 numbers\n");
for (i=1;i<=10;i++)
{scanf("%d",&num[i]);}
for (i=1;i<10;i++)
{
for (j=i+1;j<=10;j++)
{
if (num[i]>num[j])
{
num[i]+=num[j];
num[j]=num[i]-num[j];
num[i]=num[i]-num[j];
}
}
}
printf("The numbers in ascending order are:");
for (i=1;i<=10;i++)
{
printf(" %d",num[i]);
}
return 0;
}
In the latter program, numbers appear out of order, and there even are numbers that haven't been entered.
My question is, isn't it basically the same code? Just that in the latter program numbers would be stored from num[1] to num[10] instead of num[0] through num[9]?
Does it have something to do with array definitions?
It seems I have serious misconceptions, please help me out!
In C, when you have int num[10];, your indexes need to go from 0 to 9, never to 10. So look over your code, if any i or j ends up with a value of 10 any time during the program run, that's bad news.
Indexes in C go start from 0. so when you declare an array of size 10, and you try to get element at index 10, you're actually getting the 11th element. Since you haven't defined the 11th element, the array will most likely get some random numbers from memory, which is why you are noticing numbers you have note entered.
Since you are new to programming, I would suggest taking the time now to really learn about how C manages memory, and how different data structures access the memory. It might be a little boring now, but you'll save yourself some headaches in the future, and you will start to build good habits and good practices, which will lead to writing good, optimal code
for(i=0;i<9;i++) //**i<9**
for (j=i+1 ...)
If i=8 then j=9 , everything is OK.
In second code snippet:
for(i=0;i<10;i++) //**i<10**
for (j=i+1 ...)
If i=9 then j=10, so you try to access num[10] and it gives you error.
If you want to access num[10] then you must declare array int num[11] and then you can access num[10].
Array Basics
int num[10]
Capacity of array = 10
Every element of this array are integer.
First element index is 0. So If you want to access first element , num[0]
Last element index is 9. So If you want to access last element, index must be length of array - 1 , so num[9]
There are 10 elements in the array and they are :
num[0] , num[1] , num[2] , num[3] , num[4] , num[5] , num[6] , num[7] , num[8] and num[9]
You can learn further at http://www.cplusplus.com/doc/tutorial/arrays/
In your non-working example, you have invalid memory accesses. For example, when i = 9 and j = 10, you access num[10], which is invalid memory.
Welcome to programming! I believe you are a bit confused about how arrays are indexed in C.
Arrays in most languages (including C) are known as zero-indexed arrays. This means the start of an array is always at position 0. So if you make int num[10], trying to access num[10] isn't actually a valid call at all, because the start is num[0]. Hence you can only access from num[0] to num[9].
It's an easy mistake to make, even though I've been programming for years sometimes when it's been a long night I'll still make silly array indexing issues.
In your other code example, you were doing this:
int num[10];
for(int i = 1; i <= 10; i++) {
//...
}
That means you have an array with ten spaces [0-9], and for the last part of your for loop, you were trying to access num[10] which doesn't exist.
Your working example goes from 0-9 and never tries to read num[10], so it works.
Arrays in C, as in most languages, start with position 0 and count that as position one. So the last element of your array would be the size you entered when you declared the variable, minus one.

Resources