Program is working on code block but not in hacker rank - c

This piece of code works returns correct output in codeblock but not on hacker rank. I am not getting the issue?
#include <stdio.h>
int main()
{
int num,i;
long long unsigned int *num_alloc, FinalSum = 0;
num_alloc=(int*)malloc(sizeof(int)*num);
scanf("%d",&num);
for ( i=0;i<num;i++)
{
scanf("%llu",&num_alloc[num]);
FinalSum =FinalSum + num_alloc[num];
}
printf("%llu",FinalSum);
return 0;
}

let's walk through your code:
malloc(sizeof(int) * num), what is the value of num ?
scanf("%d",num), check the return value of scanf ( number of element successfully parsed by scanf )
for( i = 0 ; i < num; i++ ), loop with i from 0 to num
scanf("%llu",&num_alloc[num]), read number and store it in num_alloc[num] ( indices of array in C start from 0 )
FinalSum = FinalSum + num_alloc[num], add num_alloc[num] to FinalSum ( see #4 )
end loop
I provided some advice to fix your code. But additionally do you need to store each values that are read until the end of the program ?
Also, 'malloc' is a function of 'stdlib.h' and you didn't include that header file.

Before allocating memory for num_alloc, you must initialize the num variable. If not, memory for num_alloc will be allocated with a trash size, so you've got undefined behavior.

A number of things are jumping out at me about your code. You are allocating memory for num integers, when num is uninitialized. It is given an undefined trash value. See undefined behavior. You must put your scanf statement before your malloc, because as it stands right now your code does not make sense.
for ( i=0;i<num;i++)
{
scanf("%llu",&num_alloc[num]);
FinalSum =FinalSum + num_alloc[num];
}
For each loop iteration, you are accessing the numth element of your array. This is not possible as num_alloc should be an array of num ints, and array indexes in C start at 0. But what I'm pretty sure what you meant to do is this. With your code, you would have been assigning the same value over and over again.
for (i = 0; i < num; i++) {
scanf("%llu", &num_alloc[i]);
FinalSum += num_alloc[i];
}
You must also free() any memory you allocate on the heap with malloc().
free(num_alloc);

Related

Why this code works when i is smaller but gives a segmentation fault when i is larger?

#include <stdio.h>
int main(void) {
int *x, *y;
x = malloc(sizeof(int));
for (int i = 0; i < 4; i++)
x[i] = i + 1;
y = x;
for (int i = 0; i < 4; i++)
printf("%d ", y[i]);
}
This works correct and outputs 1 2 3 4.
But when i < 1000000 it gives segmentation fault.
Can someone explain this?
You need to allocate a large enough buffer. You only allocate sizeof(int) which is 4 bytes typically and large enough to hold only one integer. Can't store 1000000 elements in that. It worked for 4 elements out of pure chance, probably because although you were overwriting memory, you didn't clobber anything important. Something like this is what you should use.
#include <stdio.h>
int main(void)
{
int count = 1000000;
int *x, *y;
x = malloc(sizeof(int) * count);
for (int i=0; i < count; i++)
x[i] = i+1;
y = x;
for (int i=0; i < count; i++)
printf("%d ", y[i]);
}
Undefined behaviour is undefined, you cannot justify any outcome whatsoever.
You have memory allocated for one integer, the moment you try to dereference the memory outside that range (i.e., i == 1), you're invoking UB. The only valid access is x[0] and x[0] only.
You only allocated memory for one int:
x = malloc(sizeof(int)); // malloc allocates a memory chunk to only hold one int object.
Indexing x at x[i] = i+1; or y at printf("%d ", y[i]); in the loops with anything other than a value of 0 for i (like x[0] or y[0]) invokes undefined behavior because you would attempt to write to and read from not allocated memory.
"then this means if I don't have any enough buffer, it also will give a segmentation fault for i < 4?"
Exactly. You know that is the bad thing on undefined behavior. It does not need to provide wrong results or errors. So, the i < 4 code is broken, too.
Since you written to "only" 12 bytes after the allocated memory (since sizeof(int) common is 4), it might have worked because there was no other necessary information in memory thereafter, but your code is absolutely broken nonetheless.
you defined less memory than the memory you used causing your program to write after that memory zone and alterate the stack fo the program, this is also the case of the buffer overflow vulnerability in C and C++, increment the buffer size

int LA[] = {1,2,3,4,5} memory allocation confusion in c

I have observed that memory allocated for array seems to be dynamic.
Here is the sample code I found in this tutorial:
#include <stdio.h>
main() {
int LA[] = {1,3,5,7,8};
int item = 10, k = 3, n = 5;
int i = 0, j = n;
printf("The original array elements are :\n");
for(i = 0; i<n; i++) {
printf("LA[%d] = %d \n", i, LA[i]);
}
n = n + 1;
while( j >= k){
LA[j+1] = LA[j];
j = j - 1;
}
LA[k] = item;
printf("The array elements after insertion :\n");
for(i = 0; i<n; i++) {
printf("LA[%d] = %d \n", i, LA[i]);
}
}
and sample output:
The original array elements are :
LA[0]=1
LA[1]=3
LA[2]=5
LA[3]=7
LA[4]=8
The array elements after insertion :
LA[0]=1
LA[1]=3
LA[2]=5
LA[3]=10
LA[4]=7
LA[5]=8
How its working I did not get.
First, a general statement, for an array defined without explicit size and initialized using brace-enclosed initializer, the size will depend o the elements in the initializer list. So, for your array
int LA[] = {1,3,5,7,8};
size will be 5, as you have 5 elements.
C uses 0-based array indexing, so the valid access will be 0 to 4.
In your code
LA[j+1] = LA[j];
trying to access index 6, (5+1) which is out of bound access. This invokes undefined behavior.
Output of a code having UB cannot be justified in any way.
That said, main() is technically an invalid signature as per latest C standards. You need to use at least int main(void) to make the code conforming for a hosted environment.
The code has a buffer overflow bug! Arrays in C cannot be extended! You need to allocate enough space when you declare/define it.
You can declare additional space by supplying a size in the declaration:
int LA[10] = {1,3,5,7,8};
LA will now have room for 10 elements with index 0 through 9.
If you want more flexibility you should use a pointer and malloc/calloc/realloc to allocate memory.
Note:
There is a second bug in the copying. The loop starts one step too far out.
With j starting at 5 and assigning index j+1 the code assigns LA[6], which is the 7th element. After the insertion there are only 6 elements.
My conclusion from these 2 bugs is that the tutorial was neither written nor reviewed by an experienced C programmer.
To add on to the other answers, C/C++ do not do any bounds checking for arrays.
In this case you have a stack allocated array, so as long as your index does not leave stack space, there will be no "errors" during runtime. However, since you are leaving the bounds of your array, it is possible that you may end up changing the values of other variables that are also allocated in the stack if it's memory location happens to be immediately after the allocated array. This is one of the dangers of buffer overflows and can cause very bad things to happen in more complex programs.

Summing an Array of Numbers but Receiving Error when Run [closed]

Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 6 years ago.
Improve this question
I am trying to sum an array of numbers. The array has a length determined by an input and then the user gives the array. There were no compilation errors and I am able to run other programs. On the immediate start of running the program I am given a message that program has stopped working and that windows is searching for solution.
#include <stdio.h>
int main()
{
int sum, length, count;
int array[length];
sum=0;
scanf("%d",&length);
scanf("%d",&sum);
for(count=0; count<length-1; count++)
{
sum = sum + array[count];
}
printf("%d", sum);
return 0;
}
When you declare your array it depends on length but you ask the user for length after.
A solution could be to ask the user for length (scanf("%d",&length);) before declaring your actual array (int array[length];).
you should move int array[length] to after scanf("%d", &length). But it is not allowed in C to declare variables after the first non-declaration (it is however possible if you compile this program as C++).
In fact, in standard C you can't have a non-const length definition for an array variable. gcc on the other hand for example allows this nevertheless.
In your case, the problem is that length has an undefined value at the declaration of int array[length];. If you are lucky, your data segment has been initialized to zero (there is no guarantee for that) but otherwise, it may be any value, including a value which leads the program to exceed your physical memory.
A more standard way of doing this is:
int *array = NULL;
scanf("%d",&length);
...
array = (int*) malloc(sizeof(int) * length);
...
free(array);
By the way, even after fixing that, you will most likely get random numbers because you never actually assign the contents of the elements of array.
Local variable are initialized to 0. Hence value of length is 0. So you array is of length. You are then reading length, say 10, from stdin and expect the array to be of length 10. This can't be. Since this is a stack variable, the size is determined in time of pre-processing and not in run time. If you want to define the array length in run time then use malloc.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main()
{
int sum, length, count;
int *array;
sum=0;
scanf("%d", &length);
scanf("%d",&sum);
array = (int *)malloc(sizeof(int) * length);
if (array == NULL) return 0;
memset(array, length, 0);
for(count=0; count<length-1; count++)
{
sum = sum + array[count];
}
printf("%d", sum);
return 0;
}
Thanks.
first problem:
the length variable is being used to set the number of entries in the array[], before the variable length is set. Therefore, length will contain what ever trash happens to be on the stack when the program starts so the number of entries defined in array[] is an unknown.
This results in undefined behaviour and could lead to a seg fault event, depending on what was on the stack and what the user entered for length.
second problem:
The array array[] is never initialized so will contain what ever trash is on the stack at program startup. This means the value being printed could be anything. And the 'sum' could overflow, depending on the trash values in array[]
OP program lacks the part of data input, it's asking for sum instead of the values to sum, which is weird. The only inputs requested are also never checked (the return value of scanf must always be checked).
In C (at least C99 and optionally C11) Variable Length Arrays, like the one defined by int array[length], can be used, but the variable length here is used uninitialized and before it is even asked to the user.
Moreover, the loop where the sum is calculated stops before the last element of the array (not really a big deal in this case, considering that all those variables are uninitialized...).
A better way to perform this task could be this:
#include <stdio.h>
// helper function to read an integer from stdin
int read_int( int *value ) {
int ret = 0;
while ( (ret = scanf("%d", value)) != 1 ) {
if ( ret == EOF ) {
printf("Error: Unexpected end of input.\n");
break;
}
scanf("%*[^\n]"); // ignore the rest of the line
printf("Please, enter a number!\n");
}
return ret;
}
int main(void) {
int sum = 0,
length = 0,
count,
i;
printf("Please, enter the number of values you want to add: ");
if ( read_int(&length) == EOF )
return -1;
// Use a VLA to store the numbers
int array[length];
// input the values
for ( count = 0; count < length; ++count ) {
// please, note ^^^^^^^^ the range check
printf("Value n° %2d: ", count + 1);
if ( read_int(&array[count]) == EOF ) {
printf("Warning: You entered only %d values out of %d.\n",
count, length);
break;
}
// you can sum the values right here, without using an array...
}
// sum the values in the array
for ( i = 0; i < count; ++i ) {
// ^^^^^^^^^ sum only the inputted values
sum += array[i];
}
printf("The sum of the values is:\n%d\n", sum);
return 0;
}

rand() returns nothing but zeroes

I am trying to write a program that will assign 5 random integers to an array but so far it is filling the array with zeroes. Also, the first number can't be a zero. What am I doing wrong?
#include <stdio.h>
#include <stdlib.h>
int number[5];
int main() {
int i;
int t=0;
for (int t=0;t<5;t++) {
if (i=0)
{number[i] = rand()%8+1;}
else
{number[i] = rand()%10;}
i++;
printf("%d", number[i]);
}
return (0);
}
if (i=0)
That's assignment, not equality comparison.
int i;
Also, i is uninitialized, so accessing its value is undefined behavior. Since you accidentally assigned to it instead of comparing to it, if (i=0) doesn't invoke undefined behavior, but it would if you fixed the first bug.
i++;
printf("%d", number[i]);
Incrementing i before the print means you always print the cell right after the one you were working on.
You don't actually need i; t does everything you want i to do. We'll remove i and rename t to i:
for (int i = 0; i < 5; i++) {
if (i == 0) {
number[i] = rand() % 8 + 1;
} else {
number[i] = rand() % 10;
}
printf("%d", number[i]);
}
Several things are wrong in your code ...
1)
You didn't initialize the variable i
2)
if(i=0)
should be
if( i == 0 )
3)
You can use variable t instead of i -- means variable i is unnecessary
4)
You should have a function call for randomize() function before rand() function call, so that you can get the real random numbers
5)
If you just want to show the random numbers, you don't even need to use array
You will get the same sequence of 'pseudo-random' values by calling rand() in your program. To change this sequence the Random Number generator has to be 'seeded'. This is done by calling srand() function once with a seed value at the beginning of your program.
Ideally the value used for seed should change with each run of the program. Things that you could use as the seed are the process id, time, date or any other system provided value that is guaranteed to be different for each run of the program.
void srand(unsigned int seed);
Apart from that there are logical flaws in your program as others have highlighted, of which the if conditional assignment error is the most serious.

Does making the iterator a pointer speed up a C loop?

I ran the following:
#include <stdio.h>
typedef unsigned short boolean;
#define false 0
#define true (!false)
int main()
{
int STATUS = 0;
int i = 0;
boolean ret = true;
for(i = 0; i < 99999; i++)
{
ret = ret && printf("Hello, World.");
}
if(!ret)
{
STATUS = -1;
}
return STATUS;
}
It completes in just under a second. Typically 0.9 - 0.92.
Then I changed int i = 0; to int *i = 0; and now I am getting execution times under 0.2 seconds. Why the speed change?
Your runtime is dominated by the time required to print to the console. i++ on an int* will increment the pointer by the size of a pointer. That will be either 4 or 8 depending on your computer and compiler settings. Based on the numbers you report, presumably it would be 4. So printf is executed only a quarter as many times.
Typically, printing to a console will be several orders of magnitude larger than any gain with micro optimization you could do to such a loop.
Are you really sure your second version prints hello world 99999 times as well ?
When you're doing for(int *i = 0; i++ ; i < 99999 ) , you're cheking if the pointer value(an address) is less than 99999, which doesn't normally make a lot of sense. Incrementing a pointer means you step it up to point at the next element, and since you have an int*, you'll increment the pointer by sizeof(int) bytes.
You're just iterating 99999/sizeof(int) times.
Your comment on nos's answer confirmed my suspicion: it's pointer arithmetic. When you increment an int pointer using ++, it doesn't just add one to the number, but it actually jumps up by the size of an integer, which is usually 4 (bytes). So i++ is actually adding 4 to the numeric value of i.
Similarly, if you use += on a pointer, like i += 5, it won't just add 5 (or whatever) to the numeric value of i, it'll advance i by the size of that many integers, so 5*4 = 20 bytes in that case.
The reasoning behind this is that if you have a chunk of memory that you're treating as an array,
int array[100]; // for example
you can iterate over the elements in the array by incrementing a pointer.
int* i = array;
int* end = array + 100;
for (i = array; i < end; i++) { /* do whatever */ }
and you won't have to rewrite the loop if you use a data type of a different size.
The reason is because the increment operates differently on pointers.
On ints, i++ increments i by 1.
For pointers, i++ increments by the size of the pointed-to object, which will be 4 or 8 depending on your architecture.
So your loop runs for only 1/4 or 1/8 of the iteration count when i is a pointer vs when i is an int.
The correct way to do this test with a pointer would be something like:
int i;
int *i_ptr = &i;
for (*i_ptr = 0; *i_ptr < 99999; *i_ptr++) {
...

Resources