problems with data entry and malloc in C - c

I'm new to C and I'm having a small problem with my code:
int i, n;
int *arr;
while(n != 0) {
scanf("%d", &n);
if(n == 0)
exit(1);
else {
arr = (int*) malloc(sizeof(int) * n);
for(i = 0; i < n; i++)
scanf("%d", &arr[i]);
} //end if
} //end while
What I'm trying to do is to make an array of n size and I want to stop reading when I get a '0' for example if I enter:
3
2
2
5
2
6
7
0
I want an array of size 3 with values 2, 2, 5, an array of 2 with values 6 and 7 and exit because of the 0
* Sorry, I left out an important part I think... In my code a call a calc() where I send arr, right after scanf("%d",&arr[i]) and then i'll return the value and then if the next values e.g. 2 isn't 0 I'll read, create a new array, send arr, print result on console and again if the next value is 0 then it will exit. *
Could you guys tell me where I'm wrong?

You are almost there!
You are creating the new arrays in arr, but this is a single pointer so can only refer to one block of memory. When you call malloc the new memory is stored in arr but the old memory is lost. You are 'leaking memory' because the machine has the old memory reserved but you don't have a variable storing it's address so you have no way to find it again.
If you only need to store the last list you should free the old memory (in arr) before malloc'ing the new space. If you need to store all the arrays you will need an array of pointers in arr.
edit:
You need to call free to 'free' the previously allocated memory before you allocate the new memory. At the first set of data you don't have any existing 'malloc' but it's always safe to free a NULL pointer, so simply set the pointer to NULL at the start.
Hint: It's always a good idea to set all the variables to some safe initial value when you define them.
int *arr=NULL; // Mark this as pointing to no memory
....
free(arr); // first time it does nothing, afterwards it deletes the previous reserved memory
arr = (int*) malloc(sizeof(int) * n); // as before this reserves some memory

The problems which are visible in your code are:
1. Checking uninitialized integer n in while. To fix this either initialize n to non zero or use a do{ ... } while() instead of while().
2. You need to validate the value of n which is read through scanf. malloc takes size_t type as the parameter which is unsigned int. But n being an integer can accept negative values, thus if a negative value is entered it will be passed as unsigned int to malloc, this may lead to undesired results (Also for loop will be executed incorrect number of times). You may also consider changing the type of n from integer to unsigned int type or change the exit condition to if( n < 1 ).
3. There is memory leak in your program. Memory allocated through malloc is not freed through free.
4. Do not assume that malloc will always succeed. Please check for the success of malloc through a NULL check i.e.
if (NULL == arr)
{
//error handling
}
5. exit with non zero value generally indicates abnormal termination. You can use break or return. break might be a better idea as it generally gets difficult to test a function as the exit points in the function increase (though this may not be true in your case, but it is FYI)
6. Optionally, you can check the return value of scanf to make sure that a valid input was entered.
Help this helps!

You're not initializing n so you may or may not enter your while loop. Starting n at -1 would be a reasonable thing to do:
int i, n = -1;
And you should cast the return value of malloc, that can hide problems.
You're also leaking memory because you're not calling free on that you get back from malloc and you're losing track of what you read in every time you assign a new value to arr. Brian Roach and Martin Becket have mentioned these things though.

Presumably you want to be able to access these arrays later.
As it is, you're losing your pointer to the previous array when you malloc the next one (and of course, causing a memory leak if it were a larger application).
You need to allocate a chuck of int * (a set of int pointers) then store each int pointer there.
The trick is ... if you don't know how many arrays you're going to need, you need your code to be dynamic (for example; allocate some amount of space, then allocate more if you run out).
Another option is that you could limit the number of series the user can input and tell them they're done when they reach it.
Here's some help if you wanted to go the latter route:
int i;
int n = 1;
int **myArrayOfArrays = malloc(sizeof(int*) * 5); /* max of 5 arrays */
int *arr;
int arrayCount = 0;
while(n != 0) {
scanf("%d", &n);
if(n == 0)
break;
else {
if (arrayCount == 4) {
printf("Woah there partner! That's enough!\n");
break;
}
else
{
arr = malloc(sizeof(int) * n);
for(i = 0; i < n; i++)
scanf("%d", &arr[i]);
myArrayOfArrays[arrayCount] = arr;
arrayCount++;
}
} //end if
} //end while
HOWEVER ... now you don't know how long each array is. Which is a problem. You'd need to keep track of that, or use a dynamic structure such as a linked list. In the example below, we add the length as the first element of each array:
int main()
{
int i;
int n = 1;
int **myArrayOfArrays = malloc(sizeof(int*) * 5);
int *arr;
int arrayCount = 0;
while(n != 0) {
scanf("%d", &n);
if(n == 0)
break;
else {
if (arrayCount == 4) {
printf("Woah there partner! That's enough!\n");
break;
}
else
{
arr = malloc(sizeof(int) * (n + 1)); /* one more than we need */
arr[0] = n; /* store the array length in the first element */
for(i = 1; i <= n; i++)
scanf("%d", &arr[i]);
myArrayOfArrays[arrayCount] = arr;
arrayCount++;
}
} //end if
} //end while
int j;
for (i = 0; i < arrayCount; i++)
{
int length = myArrayOfArrays[i][0]; /* retrieve the length */
for (j = 1; j <= length; j++)
printf("%d ", myArrayOfArrays[i][j]);
printf("\n");
}
}
Dynamic allocation using arrays / raw memory means you need to keep track of stuff. The better approach really is using a linked list for your data. In this case, you could have a linked list of nodes, each of which contained a link list of integers.

Related

Unexpected output of a growing dynamic array

I am attempting to create a dynamic array that will grow in size if needed, as I don't know how large the array will actually be. My code seems to work until the 8th element of the array where I start to see very large incorrect values that I did not enter. Not sure why this is happening.
#include <stdio.h>
#include <stdlib.h>
int main (int argc, char** argv)
{
int val;
int userInput;
int* arr;
int size = 1;
int arrIndex = 0;
arr = (int*) malloc(sizeof(int) * size);
/* prompt the user for input */
printf ("Enter in a list of numbers to be stored in a dynamic array.\n");
printf ("End the list with the terminal value of -999\n");
/* loop until the user enters -999 */
scanf ("%d", &val);
while (val != -999)
{
if (arrIndex >= size)
{
size++;
}
arr[arrIndex] = val;
arrIndex++;
/* get next value */
scanf("%d", &val);
}
int j = 0;
for(j = 0; j < size ; j++)
{
printf("%d \t", arr[j]);
}
}
The size of the array remains 1 and doesn't increase while incrementing size variable.
Your code worked until 8th element because adjacent memory after the array upto 7th element must be free.
In C array index out of bound is not checked and it is programmers responibility.
if you want to increase or decrease size of array you can use realloc inside while loop:
arr=(int*)realloc(arr,sizeof(int)*size);
Also Correct this if condition in your code initially arrayindex is 0 and size is 1 which results in false.
if (arrIndex >= size)
{
size++;
}

How do i decrease the size of array?

#include<stdio.h>
#include<conio.h>
#include<stdlib.h>
void main()
{
int i=0,pos;
int *ptr;
clrscr();
ptr=(int *)malloc(10*sizeof(int));
printf("Enter 10 Elements:\n");
while(i<10)
{
scanf("%d",&ptr[i]);
i++;
}
printf("Current Array:\n");
for(i=0;i<10;i++)
{
printf("%d\t",ptr[i]);
}
printf("Enter the position to be deleted:");
scanf("%d",&pos);
for(i=pos;i<10;i++)
{
ptr[pos-1]=ptr[pos];
pos++;
}
for(i=0;i<10;i++)
{
printf("%d\t",ptr[i]);
}
getch();
}
Array i enter : 1 2 3 4 5 6 7 8 9 0
Suppose 4th position has been deleted
Array after deletion: 1 2 3 5 6 7 8 9 0 0
How can i make the program to print only 9 integers but without decresing the times the loop run.
i.e. without using
for(i=0;i<9;i++)
C doesn't allow you to do that. So, alternative is to dynamically allocate an array, put what you want in it, then when you get the size you want, transfer that data to a newly allocated array of the appropriate size and delete the old one.
Use a variable to keep track of how many elements of the array are being used.
When you start:
unsigned num_elements = 10;
int *ptr = malloc(num_elements * sizeof(int));
When you delete, do the following as well:
--num_elements;
When you print:
for (unsigned i=0; i<num_elements; ++i) {
...
}
Since you print the array in multiple places in the code, it would be nice to create a small function to do it.
void print_array(int *a, unsigned size) {
if (size == 0) {
printf("[empty]\n");
return;
}
printf("%d", a[0]);
for (unsigned i=1; i<size; ++i) {
printf("\t%d", a[i]);
}
printf("\n");
}
print_array(ptr, num_elements);
Your questions refers to 2 issues here:
Deleting an element of an dynamically allocated array
Printing values of an dynamically allocated array without adjusting for loop parameters
1)
for(i=pos;i<10;i++)
{
ptr[pos-1]=ptr[pos];
pos++;
}
Does not decrease the array at all - you just overwrite the particalur position with another element but you still have memory allocated for 10 int
One way to reach that would be using realloc after you moved the values by to the left beginning at the target element:
for (i = pos; i < array_size - 1; i++)
{
ptr[i] = ptr[i+1];
}
ptr = realloc(ptr, --array_size)
To 2)
Simple answer: This wont be possible. When you decrease the size of your array and dont adjust the loop's paramter you will access memory which doesnt belong to the array anymore.
Of course you dont want to adjust every for-loop by hand but you can simplify life if you always remember the array's size, preferably in immediate reference to it within a struct:
typedef struct
{
size_t size;
int *array;
} my_array_t;
If you ensure that size is properly adjusted everytime you allocate the array's memory (functions are your friend), you can always print the values with:
my_array_t a;
a.size = 10;
a.array = malloc(a.size * sizeof(int));
for (i=0; i < a.size; i++)
// ...

Weird behaviour of function with malloc() and realloc() resulting in Segmentation Fault

I have a function named num_to_binary, which is used to convert a decimal number stored in the form of array. The prototype for this function num_to_binary is as below:
void num_to_binary(int *number_b, int size_of_number);
Here:
number_b is pointer to array which stores my number. For example, if I would like to convert the number 12345 to binary, then I will be storing 12345 in number_b as follows:
number_b[0] = 1
number_b[1] = 2
number_b[2] = 3
number_b[3] = 4
number_b[4] = 5
Also, size_of_number is the number of digits in the number (or it is the number of elements in the array number_b). So for the number 12345, size_of_number has the value 5.
Below is the full declaration of the function num_to_binary:
void num_to_binary(int *number_b, int size_of_number)
{
int *tmp_pointer = malloc(1 * sizeof(int));
int curr_size = 1;
int i = 0;
while(!is_zero(number_b,size_of_number))
{
if(i != 0)
{
curr_size += 1;
tmp_pointer = realloc(tmp_pointer, curr_size * sizeof(int));
}
if(number_b[size_of_number - 1] % 2 == 1)
{
tmp_pointer[i] = 1;
divide_by_2(number_b,size_of_number);
i = i + 1;
}
else
{
tmp_pointer[i] = 0;
divide_by_2(number_b,size_of_number);
i = i + 1;
}
}
int *fin_ans;
fin_ans = malloc(curr_size * sizeof(int));
for(int j = 0 ; j < curr_size; j++)
{
fin_ans[curr_size-1-j] = tmp_pointer[j];
}
}
In the above function:
tmp_pointer: It is initially allocated some memory using malloc(), and is used to store the reverse of the binary representation of the number stored in number_b
curr_size: It stores the current size of tmp_pointer. It is initially set to 1.
i: It is used to keep track of the while loop. It is also used to reallocation purpose, which I have explained a bit later.
is_zero(number_b, size_of_number): It is a function, which returns 1 if the number stored in number_b is 0, else it returns 1.
divide_by_2(number_b, size_of_number): It divides the number stored in number_b by 2. It does NOT change the size of the array number_b.
fin_ans: It is an integer pointer. Since the binary representation stored in the array tmp_pointer will be the reverse of the actual binary representation of the number, so fin_ans will store the correct binary representation of number by reversing the content of tmp_pointer.
Below is the how this function works :
First of all, tmp_pointer is allocated a memory equal to the
size of 1 int. So, now tmp_pointer can store an integer.
We now go into the while loop. The loop will terminate only
when the number stored in number_b equals 0.
Now, we check if i is equal to 0 or not. If it is not equal to
zero, then this means than the loops has been run atleast once, and
in order to store the next binary digit, we resize the memory
allocated to tmp_pointer so that it can store the next bit.
If the last digit of the number is odd, then that implies that the
corresponding binary digit will be 1, else it will be 0. The
if and else condition do this task. They also increment
i each time one of them is executed, and also divide the number by 2.
Now, we are out of the loop. It's time to reverse the binary number
stored in tmp_pointer to get the final answer.
For this, we create a new pointer called fin_ans, and allocate
it the memory which will be used for storing the correct binary
representation of the number.
The last for loop is used to reverse the binary representation
and store the correct binary representation in fin_ans.
The problem:
The code runs for small numbers such as 123, but for large numbers such as 1234567891, it gives a segmentation fault error. This can be checked by trying to print the digits stored in fin_ans.
I tried using GDB Debugger, and got to know that the reason for Segmentation Fault lies in the while loop. I am sure that the functions divide_by_2 and is_zero are not the reason for Segmentation Fault, since I have tested them thoroughly.
I also used DrMemory, which indicated that I am trying to access (read or write) a memory location which has not been allocated. Unfortunately, I am not able to figure out where the error lies.
I suspect realloc() to be the cause of Segmentation Fault, but I am not sure.
Apologies for such a long question, however, I would highly appreciate any help provided to me for this code.
Thanks in advance for helping me out !
There are multiple problems in the code:
you do not check for memory allocation failure
you forget to free tmp_pointer before leaving the function.
you allocate a new array fin_ans to reserve the array tmp_pointer and perform the reverse operation but you do not return this array to the caller, nor do you have a way to return its size. You should change the prototype to return this information.
if the number of zero, the converted number should probably have 1 digit initialized as 0, but you use malloc which does not initialize the array it allocates so tmp_pointer[0] is uninitialized.
you did not provide the code for is_zero() nor divide_by_two(). It is possible that bugs in these functions cause the segmentation fault, especially if the loop does not reach zero and memory is eventually exhausted during this infinite loop.
Here is a modified version:
int *num_to_binary(int *number_b, int size_of_number, int *binary_size) {
int i, j, curr_size;
int *p, *newp;
curr_size = 1;
p = malloc(1 * sizeof(int));
if (p == NULL)
return NULL;
p[0] = 0;
for (i = 0; !is_zero(number_b, size_of_number); i++) {
if (i != 0) {
curr_size += 1;
newp = realloc(p, curr_size * sizeof(int));
if (newp == NULL) {
free(p);
return NULL;
}
p = newp;
}
p[i] = number_b[size_of_number - 1] % 2;
divide_by_2(number_b, size_of_number);
}
for (i = 0, j = curr_size; i < j; i++)
int digit = p[--j];
p[j] = p[i];
p[i] = digit;
}
*binary_size = curr_size;
return p;
}
There is no need for multiple memory reallocations. Result memory buffer size could be easily evaluated as binary logarithm of the decimal input value. Calculation of the number binary representation could also be simplified:
//Transform binary array to actual number
int arr2int(int* pIntArray, unsigned int nSizeIn) {
if (!pIntArray || !nSizeIn)
return 0;
int nResult = 0;
for (unsigned int i = 0; i < nSizeIn; ++i)
nResult += pIntArray[i] * (int)pow(10, nSizeIn - i - 1);
return nResult;
}
int* int2bin(int* pIntArray, unsigned int nSizeIn, unsigned int* nSizeOut){
//0) Converting int array to the actual value
int nVal = arr2int(pIntArray, nSizeIn);
//1)Evaluating size of result array and allocating memory
if(!nVal)
*nSizeOut = 1;
else
*nSizeOut = (int)floor(log2(nVal)) + 1;
//2)Allocate and init memory
int* pResult = malloc(*nSizeOut);
memset(pResult, 0, *nSizeOut * sizeof(int));
//3) Evaluate binary representation
for (unsigned int i = 0; i < *nSizeOut; ++i){
int nBinDigit = (int)pow(2, i);
if (nBinDigit == (nVal & nBinDigit))
pResult[*nSizeOut - i - 1] = 1;
}
return pResult;
}
Testing:
#include <stdio.h>
#include <math.h>
#include <stdlib.h>
#include <string.h>
#define _DC 9
int main()
{
int test[_DC];
for (int i = 0; i < _DC; ++i)
test[i] = i;
unsigned int nRes = 0;
int* pRes = int2bin(test, _DC, &nRes);
for (unsigned int i = 0; i < nRes; ++i)
printf("%d", pRes[i]);
free(pRes);
return 0;
}

Modifying *int[] passed as a parameter

My problem has to do with passing an array of integers to a function by passing the array's address. The integer array functions properly outside the function, but not inside. Most of what I've written up is just to give some extra details that may or may not be useful. To get the real gist of the problem you can skip to TL;DR at the bottom.
There are two structs:
lineType is a struct consisting of two integer values (valid and tag)
typedef struct
{
int valid;
int tag;
} lineType;
setType is a struct consisting of a pointer to a grouping of lines and a pointer to a grouping of integers.
typedef struct
{
lineType * lines;
int * iruQueue;
}
I have a pointer to a grouping of setTypes called cache (for anyone familiar with computer systems, this object is used to represent a cache system. A cache has a number of sets, each with a number of lines containing a tag, a bit indicating whether or not the line holds valid information, and a byte offset for the actual information the line holds. None of this is really required for my main question, but I thought this might clarify what I am attempting to do).
So we have setType * cache.
I have created a function that will allocate the proper space for the cache called initCache. Again, not sure if this information is necessary, but I want to throw out all the detail I can.
setType * initCache(int NoSets, int NoLines)
int i, j;
setType * cache;
//allocates the appropriate space for the sets
cache = malloc(sizeof(setType) * NoSets);
for(i = 0; i < NoSets; i++)
{
//allocates the space for the lines and the integer array
cache[i].lines = malloc(sizeof(lineType) * NoLines);
cache[i].iruQueue = malloc(sizeof(int) * NoLines);
}
//initializes all valid bits to 0 and the iruQueue entries to -1
for(i = 0; i < NoSets; i++)
for(j = 0; j < NoLines; j++)
{
cache[i].lines[j].valid = 0;
cache[i].iruQueue[j] = -1;
}
return cache;
}
So that is essentially the cache constructor. No problems there. There's a ton more code that I've written, but it all functions correctly after thorough testing.
A little more background: the iruQueue integer array is used to keep track of the least recently accessed line of a set. Ex: I have four lines, the array is initialized as an int * that looks like (-1, -1, -1, -1). Line 0 is accessed. (0, -1, -1, -1). Line 1 is accessed. (0, 1, -1, -1). Line 2 is accessed (0, 1, 2, -1). Line 0 is accessed again. (1, 2, 0, -1)
Here's my problem: at some point I want to pass the integer array to a function that will modify it within the cache. I have two functions for this purpose, enqueue and dequeue. Here's the enqueue function.
void enqueue(int ** iruQueue, int noLines, int lineNo)
{
int cached = 0;
int i;
for(i = 0; i < noLines; i++) {
if(*iruQueue[i] == -1 && cached == 0) {
*iruQueue[i] = lineNo;
cached = 1;
}
}
}
In the above function, I pass a pointer to the specific iruQueue array I want to modify as well as the number of lines in a set and the number of the line just used. It searches through the iruQueue, finds the first index with a value of -1 (indicating that the index is unused) and replaces it with the line number. I pass a specific iruQueue to this function like this.
cache(&(cache[setIndex].iruQueue), noLines, lineNo);
So here's where I really have a problem. I noticed that that it would work on the first call of enqueue, but wouldn't work properly on subsequent enqueues/dequeues.
Printing the specific queue like this prior to enqueues/dequeues (with NoSets being the number of setTypes in the cache array and NoLines being the number of lines in the set array)
int i, j;
for(i = 0; i < NoSets; i++) {
for(j = 0; i < NoLines; j++)
printf("%d, ", cache[i].iruQueue[j])
}
yields the following: "-1, -1, -1, -1, " when there are four lines and 1 set. After one enqueue with a lineNo of 0, it yields "0, -1, -1, -1, ". Proper functioning ends there.
I was curious, so within my enqueue function I added some code to print the iruQueue array before and after modification.
void enqueue(int ** iruQueue, int noLines, int lineNo)
{
int cached = 0;
int i;
//checks the iruQueue array prior to modification
printf("Before: \n");
for(i = 0; i < noLines; i++) {
printf("%d : %d\n", i, iruQueue[i]);
}
for(i = 0; i < noLines; i++) {
if(*iruQueue[i] == -1 && cached == 0) {
*iruQueue[i] = lineNo;
cached = 1;
}
}
//checks the iruQueue array after modification
printf("After: \n");
for(i = 0; i < noLines; i++) {
printf("%d: %d\n", i, iruQueue[i]);
}
}
Here's what it prints when we start with the unmodified iruQueue array (meaning all values should be -1), the number of lines being 4, and the line number being 0.
Before:
0 : -1
1 : 0
2 : -1
3 : 0
After:
0 : 0
1 : 0
2 : -1
3 : 0
It appears as though the iruQueue being modified has changed in that there are zeroes between each proper value. If I changed the print function to print through noLines * 2, the pattern would continue as such. That's my problem. When the iruQueue isn't passed to the enqueue/dequeue functions and I print its contents the same exact way, it will print correctly with no extra indices containing zeroes. Why would passing it as such change it like that, and is there anything I can do to fix it?
TL;DR
I pass an integer array (int * iruQueue) to a function by passing the address of the int array to the function ( &(cashe[setIndex].iruQueue) ). Outside the function it operates as it should, but when passed to the function it creates extra indices with 0 values inbetween each of the correct indices. How do I correct this problem?
If any more code/clarification is needed I will happily provide it. Also, if I'm doing this whole thing wrong (writing up waaaaayyyyy too much or something) just let me know- while I read a lot of things on this website to help my issues, I don't really ever post here, so I just wanted to be as thorough as possible.
Thanks!
Actually, your double pointer isn't needed here and complicates matters. You dereference it when accessing, but don't when printing (which is wrong; I wonder why it doesn't crash or produce more "random" output…). Simply reduce it to a single pointer:
void enqueue(int * iruQueue, int noLines, int lineNo)
{
int cached = 0;
int i;
for(i = 0; i < noLines; i++) {
if(iruQueue[i] == -1 && cached == 0) {
iruQueue[i] = lineNo;
cached = 1;
}
}
}
void foo()
{
enqueue(cache[setIndex].iruQueue, noLines, lineNo);
}

program in C is crashing when more memory is used

I have to do as a school assigment small program in C that will read standart input and prints some standart output. To be more specific, it's about reading numbers and sorting them.
(you can skip this, it's just for understanding the code)
First line of the input should determine how many lines of numbers there will be. Second line is ammount of numbers in next line. Third line are to concrete numbers. Fourth line is ammount of numbers in next line and so on until it reaches K number of lines. Restrictions are 0 < K <= 10 (max 10 sequences), each sequence can contain max 10.000.000 numbers and each number's value is max 10.000.000
Example
Input:
2 //which means that there will be 2 sequences (lines) of numbers and their corresponding ammount
3 //in the first sequence there will be 3 numbers
5 99912 45 //first sequence
6 //in the second sequence there will be 6 numbers
9489498 22131 0 521313 7988956 5 //second sequence
Ouptup:
0 5 5 45 22131 99912 521313 7988956 9489498
So I have done a working program but it seems to be unstable with higher values. However I can't determine when and where exactly the program fails. On my computer, I have tested all possible max values and it returned correct output in reasonable time, but on a school server where tests are done it just can't handle high values and fails.
There is one thing, that the program should only use C, not C++, but I am not very sure of differences between them and as I was using C++ compiler, it's possible that my code isn't just raw C.
I am a C beginner and this is something like "Hello world" for me, so please, can you just quick look through the code and say what can cause the unstability? Thanks
#include <stdio.h>
#include <stdlib.h>
int main(void) {
int k, n, i, y, x, index = 0;
int *numbers = (int*) malloc(100000000 * sizeof(int));
if(numbers == NULL){
exit(1);
}
scanf("%d", &k);
for (x = 0; x < k; x++) {
y = 0;
scanf("%d", &n);
while(scanf("%d", &i) > 0){
numbers[index++] = i;
if(++y == n){
break;
}
}
}
for(y = 0;y < index;y++){ //find and print all 0's, because later I will use 0 as a
//already used (printed) element in array and ignore it
if(numbers[y] == 0){
if(y == index-1){
printf("0");
}else{
printf("0 ");
}
}
}
int smallest, smallestIndex;
for(x = 0;x < index;x++){ //print all other numbers in ascending order
smallest = 0;
for(y = 0;y < index;y++){ //find current smallest number
if((numbers[y] < smallest || smallest == 0) && numbers[y] != 0){
smallest = numbers[y];
smallestIndex = y;
}
}
numbers[smallestIndex] = 0;
if(smallest > 0){
if(x == index-1){
printf("%d", smallest);
}else{
printf("%d ", smallest);
}
}
}
free(numbers);
numbers = NULL;
return 0;
}
Based on the information you give, I think this is simply a resource limitation on the server. The server simply runs out of memory and your malloc() fails. I suggest you debug or do this:
if(numbers == NULL){
printf("malloc() failed\n");
exit(1);
}
The code for printing the initial zeros is suspicious:
for(y = 0;y < index;y++){ //find and print all 0's, because later I will use 0 as a
//already used (printed) element in array and ignore it
if(numbers[y] == 0){
if(y == index-1){
printf("0");
}else{
printf("0 ");
}
}
Suppose you have a sequence with 0 as the last element (e.g. 1 2 3 4 5 0); i guess this code will print just 0 with no space after it, and the subsequent code will print 1 2 3 4 5, so you will get something like 01 2 3 4 5.
I understand that you want the output to be as beautiful as possible, that is, without a space at the end. Please also note that a newline (\n) at the end of output might be good.
I rewrote beginning parts of your program to get you on the right path. This should help you but I can't be sure since I don't really know what is causing your program to crash.
This implements the realloc function which should make your program drastically more efficient than it is now. If you don't know what realloc is you can read about it here, and here.
#include <stdio.h>
#include <stdlib.h>
#define BUFFER 256 //for memory management
int main(void)
{
int k, n, i, y , x, index = 0, bff; //declare integer 'bff' and set it to BUFFER
int *numbers = NULL, *tmp; //declare a pointer (numbers) for allocated memory, and a pointer (tmp) for the realloc function
if(!(numbers = malloc(BUFFER * sizeof(int)))) //allocate space for 'bff' integers
{
exit(1); //allocation failed
}
scanf("%d", &k);
for (x = 0; x < k; x++)
{
scanf("%d", &n);
while(scanf("%d", &i) > 0)
{
if(bff <= index) //if the size of index grows larger than the amount of space we allocated
{
bff += BUFFER; //increase the size of bff by BUFFER
if(!(tmp = realloc(numbers, bff * sizeof(int)))) //resize our allocated memory block using the tmp pointer
{
free(numbers); //allocation failed so free already allocated memory
exit(1); //and terminate the program
}
numbers = tmp; //make numbers point to the same location as tmp
numbers[index++] = i;
if(++y == n) break;
}
}
}
.
.
.
free(numbers);
return 0;
}
Keep in mind there are more efficient ways to use realloc. I just posted this here to get you on the right track. Good luck!
You are allocating the wrong amount of memory. The specification states that each sequence can contain 10 million values whereas you allocate a fixed amount. There may be up to k*10 million values of input, and you cannot know that the amount you allocate is enough.
As pointed out by m0skit0, the problem may also be due to over-allocation.
To fix the problem you should allocate the needed amount of memory, no more, no less.
Use the sequence length provided for each sequence to do that.
Also, you need to check the return value of malloc and realloc. If the return value is NULL then the allocation failed and you should print an error message and exit.

Resources