Manipulating a global array in a recursive function - c

I'm working through an algorithms MOOC and have a small program that takes an array A of ints in arbitrary order, counts the number of inversions (an inversion being the number of pairs (i,j) of array indices with i<j and A[i] > A[j]).
Below is the code I've written. I'm trying to tackle it using a "divide and conquer" approach where we recursively split the input array into two halves, sort each half individually while counting the inversions and then merge the two halves.
The trick is I need to keep track of the number of inversions and sort the arrays, so I pass the original array around the various recursive calls as an argument to the function and pass the count of inversions as a return value.
The code executes correctly through the first set of recursive calls that successively divide and sort [1,5,3], however when I get to the 3rd invocation of mergeAndCountSplitInv it crashes at the line:
sortedArrayLeft = realloc(sortedArrayLeft, sizeof(int)*(rightLen + leftLen));
with the error:
malloc: *** error for object 0x100103abc: pointer being realloc'd was not allocated
I can't see where I'm not using malloc correctly and I've combed through this checking to see I'm doing the pointer arithmetic correctly and can't spot any errors, but clearly error(s) exist.
Any help is appreciated.
// main.c
// inversionInC
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
// function to help with debugging array/pointer arithmetic
void logArrayLenAndContents (char *arrayName, int arrayToPrint[], int arrayLen){
printf("%s\n", arrayName);
printf("len:%d\n", arrayLen);
for (int idx = 0; idx < arrayLen; idx++) {
printf("array[%d]: %d\n", idx, arrayToPrint[idx]);
}
}
int mergeAndCountSplitInv(int sortedArrayLeft[], int leftLen, int sortedArrayRight[], int rightLen)
{
printf("Calling mergeAndCount with sortedArrayLeft:\n");
logArrayLenAndContents("left Array", sortedArrayLeft, leftLen);
printf("...and sortedArrayRight:\n");
logArrayLenAndContents("right Array", sortedArrayRight, rightLen);
int i = 0;
int j = 0;
int k = 0;
int v = 0; // num of split inversions
int* outArray;
outArray = malloc((leftLen + rightLen) * sizeof(int));
while (i < leftLen && j < rightLen) {
if (sortedArrayLeft[i] < sortedArrayRight[j]) {
outArray[k] = sortedArrayLeft[i];
i++;
} else{
outArray[k] = sortedArrayRight[j];
v += leftLen - i;
j++;
}
k++;
}
// if at the end of either array then append the remaining elements
if (i < leftLen) {
while (i < leftLen) {
outArray[k] = sortedArrayLeft[i];
i++;
k++;
}
}
if (j < rightLen) {
while (j < rightLen) {
outArray[k] = sortedArrayRight[j];
j++;
k++;
}
}
printf("Wrapping up mergeAndCount where outArray contains:\n");
logArrayLenAndContents("outArray", outArray, k);
sortedArrayLeft = realloc(sortedArrayLeft, sizeof(int)*(rightLen + leftLen));
return v;
}
int sortAndCount(int inArray[], int inLen){
printf("Calling sortAndCount with:\n");
logArrayLenAndContents("inArray", inArray, inLen);
if (inLen < 2) {
return 0;
}
int inArrayLenPart1 = ceil(inLen/2.0);
int inArrayLenPart2 = inLen - inArrayLenPart1;
int* rightArray = malloc(sizeof(int) * inArrayLenPart2);
rightArray = &inArray[inArrayLenPart1];
int x = sortAndCount(inArray, inArrayLenPart1);
printf("sortAndCount returned x = %d\n\n", x);
int y = sortAndCount(rightArray, inArrayLenPart2);
printf("sortAndCount returned y = %d\n\n", y);
int z = mergeAndCountSplitInv(inArray, inArrayLenPart1, rightArray, inArrayLenPart2);
printf("mergeAndCount returned z = %d\n", z);
return x+y+z;
}
int main(int argc, const char * argv[])
{
static int* testArray;
testArray = malloc(5 * sizeof(int));
for (int i = 0; i<=4; i++) {
testArray[0] = 1;
testArray[1] = 5;
testArray[2] = 3;
testArray[3] = 2;
testArray[4] = 4;
}
int x = sortAndCount(testArray, 5);
printf("x = %d\n", x);
return 0;
}

This happens because the value of sortedArrayLeft gets lost as soon as the function returns. The realocated value does not make it to the caller, so inArray of the sortAndCount may be pointing to freed memory if realloc needs to reallocate and copy.
In order to fix this, pass a pointer to the pointer, letting sortedArrayLeft to propagate back to inArray of sortAndCount:
int mergeAndCountSplitInv(int **sortedArrayLeft, int leftLen, int sortedArrayRight[], int rightLen) {
...
*sortedArrayLeft = realloc(*sortedArrayLeft, sizeof(int)*(rightLen + leftLen));
return v;
}
...
int sortAndCount(int **inArray, int inLen) {
...
int z = mergeAndCountSplitInv(inArray, inArrayLenPart1, rightArray, inArrayLenPart2);
}
...
int x = sortAndCount(&testArray, 5);

Related

Why is this below code giving heap overflow Error by just changing the comparison operator from &&(AND) to ||(OR)?

I was trying to solve below problem:
Given two integer arrays nums1 and nums2, return an array of their intersection. Each element in the result must appear as many times as it shows in both arrays and you may return the result in any order.
Example 1:
Input: nums1 = [1,2,2,1], nums2 = [2,2]
Output: [2,2]
Here is my code:
/**
* Note: The returned array must be malloced, assume caller calls free().
*/
int* intersect(int* nums1, int nums1Size, int* nums2, int nums2Size, int* returnSize){
for(int i=0; i<nums1Size-1; i++){
if(nums1[i]>nums1[i+1]){
int temp = nums1[i];
nums1[i] = nums1[i+1];
nums1[i+1] = temp;
i = -1;
}
}
for(int i=0; i<nums2Size-1; i++){
if(nums2[i]>nums2[i+1]){
int temp = nums2[i];
nums2[i] = nums2[i+1];
nums2[i+1] = temp;
i = -1;
}
}
int i = 0;
int j = 0;
int* res = (int*)malloc(10* sizeof(int));
int k = 0;
if(!(nums1Size > nums2Size)){
int * temp = nums1;
nums1 = nums2;
nums2 = temp;
int tempint = nums1Size;
nums1Size = nums2Size;
nums2Size = tempint;
}
while(i<nums1Size && j<nums2Size){
if(nums1[i] > nums2[j]){
j++;
}
else if(nums1[i] < nums2[j]){
i++;
}
else{
res[k++] = nums1[i];
i++; j++;
}
}
*returnSize = sizeof(res)/sizeof(res[0]);
return res;
}
To simplify the problem you have to solve, let's first write a helper function that counts the number of occurrences of a particular element inside an array:
int count_elem(int* arr, int n, int elem) {
int count = 0;
for (int i = 0; i < n; i += 1) {
if (arr[i] == elem) {
count += 1;
}
}
return count;
}
Now, let's try to solve the problem following the problem description:
int* intersect(int* nums1, int nums1Size, int* nums2, int nums2Size, int* returnSize) {
// here we allocate `res` with size of the biggest array, because that's the worst case we'll have
int* res = malloc(sizeof(int) * ((nums1Size > nums2Size) ? nums1Size : nums2Size));
// just to be sure `malloc()` did not return an error
if (res == NULL) {
return NULL;
}
// we'll keep track of how many elements we actually put inside `res`
*returnSize = 0;
// let's loop through all elements of `nums1`
for (int i = 0; i < nums1Size; i += 1) {
int elem = nums1[i];
// if we already put the element inside `res`, we skip this cycle
int count_res = count_elem(res, *returnSize, elem);
if (count_res > 0) {
continue;
}
// let's count the occurrences in both arrays
int count1 = count_elem(nums1, nums1Size, elem);
int count2 = count_elem(nums2, nums2Size, elem);
// let's calculate how many times the element must be present inside `res`
// i.e.: the same number of times of the array with the fewer occurrences of it
// NOTE: if `nums1` or `nums2` do not include the element, we also don't include it inside `res`
int count_min = (count1 < count2) ? count1 : count2;
// now let's put inside `res` as many times as we previously calculated
for (int i = 0; i < count_min; i += 1) {
res[*returnSize] = elem;
*returnSize += 1;
}
}
return res;
}
Let's try if it works:
int main(void) {
int arr1[] = {1, 2, 2, 1};
int arr2[] = {2, 2};
int res_size;
int* res = intersect(arr1, sizeof(arr1) / sizeof(arr1[0]), arr2, sizeof(arr2) / sizeof(arr2[0]), &res_size);
// let's print the result of `intersect()`
for (int i = 0; i < res_size; i += 1) {
printf("%d\n", res[i]);
}
return 0;
}
Output:
2
2
NOTE: the function is not optimized for speed nor for memory efficiency. This will be left as an exercise for the reader.
UPDATE
The previous version of the answer was wrong (sorry again). Now it should be correct.

Sum elements of array structure with a pointer to that structure

I have a problem where I have this structure
typedef struct _COMPLEX {
double real, imag;
}COMPLEX;
and I need to declare an array of this structure and sum the elements of the array. Here is my code.
#include <stdio.h>
#include <stdlib.h>
void* xmalloc(size_t nrOcteti);
int main()
{
COMPLEX* v = 0, *s = 0;
int n, i;
printf("\n n = ");
scanf("%d", &n);
v = (COMPLEX*)xmalloc((n)*sizeof(COMPLEX));
s = (COMPLEX*)xmalloc(sizeof(COMPLEX));
for(i = 0; i < n; i++)
{
printf("\n v[%d].real and imag:", i);
scanf("%lf %lf", &v[i].real, &v[i].imag);
}
for(i = 0; i < n; i++)
printf("V%d after scan=%.2lf + %.2lf * i\n", i, v[i].real, v[i].imag);
s->real = 0; s->imag = 0;
for(i = 0; i < n; i++)
{
s->real = s->real + v[i].real;
s->imag = s->imag + v[i].imag;
}
for(i = 0; i < n; i++)
printf("V%d after sum=%.2lf + %.2lf * i\n", i, v[i].real, v[i].imag);
printf("\nS=%lf + %lf\n", s->real, s->imag);
if(s) free(s);
s = 0;
if(v) free(v);
v = 0;
return 0;
}
void* xmalloc(size_t nrOcteti)
{
void *p = 0;
p = malloc(sizeof(nrOcteti));
if(!p)
{
fprintf(stderr, "Allocation failed!");
exit(EXIT_FAILURE);
}
return p;
}
After I give the elements of the array I print them everything is alright, but just before the sum the elements of the array are changed(and for multiple test, apparently the element with the index 2 is modified) and the sum at the end is incorrect. And sometimes(I think because of different inputs) it gives me at the end Segmentation fault because of the free().
The array and sum needs to be pointers to that struct and need to be dynamically allocated.
I tried many times and I can't manage to make it work properly.
If somebody can help me solve this it will be a blessing =))
The line
p = malloc(sizeof(nrOcteti));
in the function xmalloc() is wrong. This line is ignoring what is passed as the argument and just allocating for one size_t.
It should be
p = malloc(nrOcteti);
to allocate specified size.

Why do I get a segmentation fault by declaring a 2d array in c?

I am new to threads and I have a program that uses threads to find the minimum number out of a 2d array and later on, it finds the distance that the other elements of the array have from the minimum number and stores them in another array.
The user should enter the size of the array and the number of threads he wants to use.
I tried the program below for 1d array and it worked just fine. When I converted it to work for a 2d array it started crashing and throwing a segmentation fault. I, however, cannot find which part of the 2d declaration is wrong.
Any help is really appreciated.
Here is my code:
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/wait.h>
#include <string.h>
#include <pthread.h>
struct Parameters
{
// input
int s,p; //n is size of array, p is number of threads
int** array; //array with elements
int start;
int end;
// output
int smallest;
int pos; //position if minimum
int** B; //array that holds the distances
};
void* min(void* args)
{
struct Parameters* p = (struct Parameters*)args;
int **array = p->array;
int **B1 = p->B;
int start = p->start;
int end = p->end;
int smallest = array[start][start];
int pos = p->pos;
int distance;
//find the smallest
for (int i = start; i < end; i++)
{
for(int j = start; j < end; j++)
{
if (array[i][j] < smallest)
{
smallest = array[i][j];
pos = i;
}
}
}
//find the distances
for(int i = 0; i < ((struct Parameters*)args) -> s; i++)
{
for(int j = 0; j < ((struct Parameters*)args) -> s; j++)
{
distance = abs(pos - i);
B1[i][j] = distance;
}
}
params->smallest = smallest;
params->B = B1;
return NULL;
}
int main()
{
int smallest,pos;
int s,p;
struct Parameters *ptr = (struct Parameters *)malloc(sizeof(struct Parameters));
if(ptr == NULL)
{
printf("Not enough. Try again \n");
exit(0);
}
printf("Type s\n");
scanf("%d",&(ptr->s));
printf("Type p\n");
scanf("%d", &(ptr->p));
// declare an array of threads and associated parameter instances
pthread_t threads[(ptr->p)];
struct Parameters thread_parameters[(ptr->p)] ;
int arr[ptr->s][ptr->s];
int B2[ptr->s][ptr->s];
// intialize the array
for(int i=0; i< ptr->s; i++)
{
for(int j=0; j< ptr->s; j++)
{
printf("Type a \n");
scanf("%d",&arr[i][j]);
}
}
// smallest needs to be set to something
smallest = arr[0][0];
// start all the threads
for (int i = 0; i < ptr->p; i++)
{
memcpy(arr, thread_parameters[i].array, sizeof(arr));
thread_parameters[i].s = ptr->s;
memcpy(Bb, thread_parameters[i].B, sizeof(B2));
thread_parameters[i].start = i * (ptr->s / ptr->p);
thread_parameters[i].end = (i+1) * (ptr->s / ptr->p);
pthread_create(&threads[i], NULL, min, &thread_parameters[i]);
}
// wait for all the threads to complete
for (int i = 0; i < ptr->p; i++)
{
pthread_join(threads[i], NULL);
}
// Now aggregate the "smallest" and "largest" results from all thread runs
for (int i = 0; i < ptr->p; i++)
{
if (thread_parameters[i].smallest < smallest)
{
smallest = thread_parameters[i].smallest;
}
}
printf("Smallest is %d\n", smallest);
thread_parameters[ptr->p].B[ptr->s][ptr->s];
for (int i = 0; i < 1; i++)
{
for(int j = 0; j < ptr->s;j++)
{
for(int k = 0; k < ptr->s; k++)
{
printf("Element %d is %d away from min\n",j,thread_parameters[i].B[j][k]);
}
}
}
return 0;
}
Thank you!!
The issue with your code might also come from :
memcpy(arr, thread_parameters[i].array, sizeof(arr));
...
memcpy(Bb, thread_parameters[i].B, sizeof(B2));
as thread_parameters[i].array and thread_parameters[i].B are not allocated, if you are only reading the array it might b fine to only pass them by address
thread_parameters[i].array = arr
but for thread_parameters[i].B you would need to allocate the arrays and perform a deep copy (memcpy would not work)
The below text does not answer the question but does provide some insight on VLA usage
One reason for causing the segmentation with a declaration of a Variable Length Array is that the value is to large to allocate the array on the stack (some compiler choose this option, this choice might have performance reason).
The is not much option to recover cleanly from failure to allocate memory on the stack as there is little way to clean up stack memory during runtime within the same stack context.
You can mitigate the issue by allocating your 2D arrays on the heap instead, some of the strategies are available here(thanks #Lundin) and here.
int** alloc_2d_int_array(size_t rows, size_t cols) {
int **result = malloc(rows * sizeof(int *));
if(result == NULL) {
// could not allocate more memory
return NULL;
}
size_t row_size = cols * sizeof(int);
for(int i=0; i < rows; ++i) {
result[i] = malloc(row_size);
if(result[i] == NULL) {
// could not allocate more memory
// cleanup
return NULL;
}
}
return result;
}
the above implementation have not been tested, but does compile, there are still risk of integer overflow.
Then use the above define function as following:
int **arr = alloc_2d_int_array(ptr->s, ptr->s);
int **B2 = alloc_2d_int_array(ptr->s, ptr->s);
easier implementation (see here(thanks #Lundin))
int **arr = malloc(sizeof(int[ptr->s][ptr->s]);
int **B2 = malloc(sizeof(int[ptr->s][ptr->s]);

How to solve this error when trying to compute the twoSums coding question in C

Given an array of integers, return indices of the two numbers such that they add up to a specific target.
Given nums = [2, 7, 11, 15], target = 9,
Because nums[0] + nums[1] = 2 + 7 = 9,
return [0, 1].
#include<stdio.h>
int* twoSum(int* nums, int numsSize, int target);
int main(){
int*array;
int arraySize;
scanf("%d",&arraySize);
for (int i=0;i<arraySize;i++){
scanf("%d",&array[i]);
}
int target;
scanf("%d",&target);
int* positions=twoSum(array, arraySize, target);
printf("The positions are: %p",positions);
return 0;
}
int* twoSum(int* nums, int numsSize, int target){
int *returnSize = NULL;
for(int i=0,sum=0;i<numsSize;i++){
for(int j=0;j<numsSize;j++){
sum =sum+nums[i]+nums[j];
if(sum==target){
returnSize[0]=nums[i];
returnSize[1]=nums[j];
}
else
returnSize[0]= -1;
returnSize[1]= -1;
}
}
return returnSize;
}
The error I am getting makes reference to a line that is empty in my code. Please help
there are mistakes in this code.First you should allocate memory for int*array; after taking int arraySize; as input , you can do it like this
array = malloc(sizeof(int) * arraySize);
then here %p is not appropriate , instead use %d. Take look here for more information about %p %p format specifier and also since you want to print 2 positions you need to call two arguments in printf like this printf("The positions are: %d %d", positions[0], positions[1]);
In your twoSum function , you need to allocate memory for int* returnSize ; like this returnSize = malloc(sizeof(int) * 2);
and here you are not returning positions of found elements , you are returning elements themselfs.
if(sum==target){
returnSize[0]=nums[i];
returnSize[1]=nums[j];
}
also you need to add return in this if-statement other wise , you will traverse array completely and returnSize elements will become -1 again(unless answer is too last element of array)
so this if should be like this:
if (sum == target) {
returnSize[0] = i;//num[i] is not position. it is element of array
returnSize[1] = j;//num[j] is not position .it is element of array
return returnSize;//otherwise it will traverse array compeltely and they -1 again
}
also only if you code one line for if,else,while,for,... (conditional statements) ,you can avoid using braces ,otherwise only one line of your code will executed ,if that condition become true ,so you have to add a block for this else:
else
{
returnSize[0] = -1;
returnSize[1] = -1;
}//coding more than one line so your else should be in a block
and also here sum=sum+num[i]+num[j]; is wrong you should change this to sum=num[i]+num[j]; because you only want to check sum of two current number ,or better way don't use sum at all only check equality of target with num[i]+num[j]
here is complete code:
int* twoSum(int* nums, int numsSize, int target);
int main() {
int* array;
int arraySize;
scanf("%d", &arraySize);
array = malloc(sizeof(int) * arraySize);//allocate memory for array
for (int i = 0; i < arraySize; i++) {
scanf("%d", &array[i]);
}
int target;
scanf("%d", &target);
int* positions = twoSum(array, arraySize, target);
printf("The positions are: %d %d", positions[0], positions[1]);//%p is for not for content of array
return 0;
}
int* twoSum(int* nums, int numsSize, int target) {
int* returnSize ;
returnSize = malloc(sizeof(int) * 2);
for (int i = 0; i < numsSize; i++) {
for (int j = 0; j < numsSize; j++) {
if (nums[i] + nums[j] == target) {
returnSize[0] = i;//num[i] is not position. it is element of array
returnSize[1] = j;//num[j] is not position .it is element of array
return returnSize;//otherwise it will traverse array compeltely and they -1 again
}
else
{
returnSize[0] = -1;
returnSize[1] = -1;
}//coding more than one line so your else should be in a block
}
}
return returnSize;
}
There is some mistakes in your code:
memory allocation
You declare pointers on int to store data to process and result, but you do not allocate memory: malloc is for Memory ALLOCation:
array = malloc(sizeof *array * arraySize);
and
int *returnSize = malloc(sizeof *returnSize * 2);
Sum calculation logic
sum value
In twoSum function, the sum variable is getting bigger and bigger: sum =sum+nums[i]+nums[j];
Instead, a simple if (target == nums[i] + nums[j]) will perform the test you wanted.
sum test
In your code, each time sum is not equal to target, you reset returnSize[0] to -1
You do not have to have an else clause: you can initialize the returnSize before the for loop.
missing {...}
Look at your first code: for any value of sum and target, returnSize[1] is set to -1 because you've forgotten to put accolades after the else (but, as written before, you do not even need an else)
gcc can warn you about such issue (-Wmisleading-indentation, or better -Wall)
for(int j=0;j<numsSize;j++){
sum =sum+nums[i]+nums[j];
if(sum==target){
returnSize[0]=nums[i];
returnSize[1]=nums[j];
}
else
returnSize[0]= -1;
returnSize[1]= -1;
}
Considering this, you can write a code that do what you wanted.
Be careful, you should test the scanf and malloc return values too...
#include <stdio.h>
#include <stdlib.h>
int *twoSum(int *nums, int numsSize, int target);
int main()
{
int *array;
int arraySize;
// TODO: test that scanf returned 1
scanf("%d", &arraySize);
// TODO: test that arraysize is at least 2
/* allocate array to store the numbers*/
array = malloc(sizeof *array * arraySize);
for (int i = 0; i < arraySize; i++) {
// TODO: test that scanf returned 1
scanf("%d", &array[i]);
}
int target;
// TODO: test that scanf returned 1
scanf("%d", &target);
int *positions = twoSum(array, arraySize, target);
printf("The positions are: %d(%d) %d(%d)\n", positions[0], array[positions[0]], positions[1], array[positions[1]]);
/* memory has been allocated? free it */
free(positions)
free(array)
return 0;
}
int *twoSum(int *nums, int numsSize, int target)
{
int *returnSize = malloc(sizeof *returnSize * 2);
returnSize[0] = returnSize[1] = -1;
for (int i = 0; i < numsSize; i++) {
for (int j = 0; j < numsSize; j++) {
if (target ==nums[i] + nums[j] ) {
returnSize[0] = i;
returnSize[1] = j;
return returnSize;
}
}
}
return returnSize;
}
Here your code:
#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
int* twoSum(int* nums, int numsSize, int target);
void print_pos(int * arr, int i) {
printf("test %d\n", i);
if (arr != NULL) {
printf("position 1 = %d, position 2 = %d\n", arr[0], arr[1]);
} else
printf("Not found\n");
}
int main(){
int array[5] = {5, 6, 2 ,1 ,3} ;
int target1 = 11, target2 = 9, target3 = 15;
int * positions1=twoSum(array, 5, target1);
int * positions2=twoSum(array, 5, target2);
int * positions3=twoSum(array, 5, target3);
print_pos(positions1, 1);
print_pos(positions2, 2);
print_pos(positions3, 3);
return 0;
}
int* twoSum(int* nums, int numsSize, int target){
int *return_arr = malloc(sizeof(int) * 2);
bool found = false;
for(int i=0;i<numsSize;i++){
for(int j=0;j<numsSize;j++){
if((nums[i]+nums[j])==target){
return_arr[0]= i;
return_arr[1]= j;
found = true;
}
}
}
if (found)
return return_arr;
else {
free(return_arr);
return NULL;
}
}

Realloc an array of double

The exercise, that I have to complete says:
That array_remove function must remove from the array arr the value, that is in the position pos, and scale of a position successive values of pos, and eventually change the array size for no gaps.
If this value is not included in the array (if pos is greater than pn (array size)), then you should not do anything.
My problem is:
Probably very wrong to use the malloc function, because when it is performed, it shows the following error:
MAIN.C:
#include "array.h"
int main(void)
{
double arr[] = { 1.0,2.0,3.0,4.0,5.0 };
size_t pn = 5;/*array length*/
size_t pos = 2;/*position of the number to be deleted*/
array_remove(arr, &pn, pos);
}
ARRAY.C:
#include "array.h"
void array_remove(double *arr, size_t *pn, size_t pos)
{
int x = *pn;
int y = pos;
if (x > y)
{
for (int i = y; i < x; i++)
{
arr[i] = arr[i + 1];
}
realloc(&arr, sizeof(double) * 4);
}
}
According to the C docs:
realloc Reallocates the given area of memory that must be previously allocated
by malloc(), calloc() or realloc() and not yet freed with free,
otherwise, the results are undefined.
You have an out of bound problem as well at the following lines when i=x-1 you try to access at arr[i+1] = arr[x=pn]:
for (int i = y; i < ; i++) {
arr[i] = arr[i + 1];
Check the following code out *(live: https://ideone.com/mbSzjL
#include<stdlib.h>
void array_remove(double **arr, int *pn, int pos) {
int x = *pn;
int y = pos;
if (x > y) {
//check if after deletion size is zero!
if (x > y) {
for (int i = y; i < x-1; i++) {
(*arr)[i] = (*arr)[i + 1];
}
*arr=realloc(*arr, sizeof(double) * x-1);
*pn=*pn-1;
}
}
}
int main(void) {
int pn = 20;/*array length*/
int pos = 5;/*position of the number to be deleted*/
double *arr = malloc(sizeof(double)*pn);
printf("%p\n",arr);
for(int i=0;i<pn;i++){
arr[i] = i;
}
for(int i=0;i<pn;i++){
printf("%.f ",arr[i]);
}
printf("\n");
printf("%i\n",pn);
array_remove(&arr, &pn, pos);
printf("%p\n",arr);
for(int i=0;i<pn;i++){
printf("%.f ",arr[i]);
}
printf("\n");
printf("%i",pn);
free(arr);
}
Don't forget to realloc using the right size (not using an hardcoded 4) and check for the edge case in which size is zero after deletion!
In addition,
free the memory at the end and to update the size variable.
http://en.cppreference.com/w/c/memory/realloc
arr array is stack allocated. You cannot realloc something that wasn't mallocated.
You probably want something like this:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdbool.h>
bool array_remove(double **arr, size_t *pn, size_t pos)
{
int x = *pn - 1;
int y = pos;
int i;
double *temp;
if (x > y) {
for (i = y; i < x; i++) {
(*arr)[i] = (*arr)[i + 1];
}
temp = realloc(*arr, sizeof(double) * x);
}
if (arr != NULL)
{
*arr = temp;
*pn -=1;
return true;
}
else
{
return false;
}
}
int main(void)
{
size_t pn = 5; // array length
size_t pos = 2; // position of the number to be deleted
int i;
double *arr = malloc(pn*sizeof(double));
if (arr != NULL)
{
for (i=0; i<pn; i++)
{
arr[i] = (double)(i+1);
}
if (array_remove(&arr, &pn, pos) == false)
{
printf("Failed to remove element %zu\n", pos);
}
for (i=0; i<pn; i++)
printf ("arr[%d]: %f\n", i, arr[i]);
free(arr);
}
else
{
printf("Failed to alloc array\n");
}
return 0;
}
As you can see I changed the loop of array_remove. In your code you are addressing the array out of bound on the last loop, because of i=4 and then:
arr[i] = arr[i + 1]; is arr[4] = arr[5]
Indexes of a 5 elements array start from 0 to 4.
actually you have a different problem here:
int x = *pn; //x=5
int y = pos; //y=2
if (x > y) {
for (int i = y; i < x; i++) {
arr[i] = arr[i + 1];
}
On the last iteration, you do
arr[4] = arr[5]
This is out of range addressig and that's probably your problem, or at least your first one.
Also, even though it's not technically wrong it's conceptually wrong:
array_remove(arr, &pn, pos);
Never pass a value by pointer unless you plan on modifying it. Not the case here, so you can pass it by value.

Resources