-2

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:

enter image description here

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);
    }
}
Ahmed Akhtar
  • 1,444
  • 1
  • 16
  • 28
Amarildo
  • 268
  • 4
  • 19
  • 4
    Possible duplicate of [stack & realloc question C++](http://stackoverflow.com/questions/650708/stack-realloc-question-c) – 2501 Feb 11 '16 at 09:57
  • 2
    I believe that it is not possible to reallocate a statically defined array; the array to be reallocated would have to be allocated at runtime using the `malloc` function. – Codor Feb 11 '16 at 09:59
  • and what can I do to reduce the size of the array? – Amarildo Feb 11 '16 at 10:01
  • 1
    Start by reading about data allocated *on the stack* and *on the heap*. The continue by reading about [`realloc`](http://en.cppreference.com/w/c/memory/realloc) and [`malloc`](http://en.cppreference.com/w/c/memory/malloc). Then search for and read about *passing arguments by reference in C*. – Some programmer dude Feb 11 '16 at 10:01
  • 1
    But also: `for (int i = y; i < x; i++) ` should be `for (int i = y; i < x-1; i++) ` as you address `arr[i+1]` so you go beyond the array bound. – Paul Ogilvie Feb 11 '16 at 10:03
  • 3
    You can't change the size of a compile-time array. Mainly because the array is allocated on the stack by the compiler, and will have a fixed size that can't be changed. There are workarounds for that, like marking "removed" elements some way, for example set it to some value that is considered "removed" (`0.0` or `-1.0` or something else). You could also use a second array which contains boolean values to tell if an element is removed or not. Or you could allocated it dynamically on the heap, in which you *can* reallocate it and actually change its size. – Some programmer dude Feb 11 '16 at 10:05
  • 1
    The amount of memory allocated for an array and the number of items in the array are two different things. You don't actually have to reduce the memory of the array when you remove a value. Moving the values to fill the gap and reducing `*pn` is sufficient in this case. – Klas Lindbäck Feb 11 '16 at 11:09

3 Answers3

3

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

Davide Spataro
  • 7,319
  • 1
  • 24
  • 36
  • having a void function, I can not create another array to consider moving around them, so how can I solve the problem of reducing the size? – Amarildo Feb 11 '16 at 10:04
  • Not sure why this is down voted, it answers the question. Maybe add a bit of explanation, I guess. – Lundin Feb 11 '16 at 10:12
  • 4
    @AmarildoAliaj The whole reason dynamically allocated arrays exist, is because they, unlike statically allocated arrays, can be allocated with a variable size. If statically allocated arrays could be resized, there would be no use for dynamic arrays, now would there? – Lundin Feb 11 '16 at 10:13
  • 1
    [Do I cast malloc return?](http://stackoverflow.com/questions/605845/do-i-cast-the-result-of-malloc) – LPs Feb 11 '16 at 10:23
  • I always compile using g++ that requires cast. – Davide Spataro Feb 11 '16 at 10:27
  • @2501 Edit history. There was no code at all when I made that comment. – Lundin Feb 11 '16 at 10:41
  • @Lundin Yes I knew that. Also check the other answer. How is this upvoted? A fluke of is C tag quality declining. – 2501 Feb 11 '16 at 10:43
  • @DavideSpataro ok thanks, but there is no way to delete the space arr [4]? – Amarildo Feb 11 '16 at 10:59
  • @AmarildoAliaj that should work fine even for the last position. I have not compiled that, but I'm quite confident it works. – Davide Spataro Feb 11 '16 at 11:05
  • 1
    Scope of `arr` is local in `array_remove` function. Your `realloc` does not take affect to `arr` pointer inside main. – LPs Feb 11 '16 at 11:22
2

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.

LPs
  • 16,045
  • 8
  • 30
  • 61
  • but in this way remains an empty space (arr [4] = 0), it is not possible to remove it entirely, without the need to decrease the pn? – Amarildo Feb 11 '16 at 10:31
  • `realloc` return pointer is lost if not assigned back to arr and memory is not deleted at the end of main. – Davide Spataro Feb 11 '16 at 10:51
0

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.

Pandrei
  • 4,843
  • 3
  • 27
  • 44
  • I am obliged to pass a pointer because I can't change the parameters of the function – Amarildo Feb 11 '16 at 10:15
  • the exercise asks me to move back a value of the remaining, so I decided to use the for loop, and then remove a space (that i don't know how to do, being a void function, I can't even create another array) – Amarildo Feb 11 '16 at 10:19
  • the for loop approach is ok, you can do the operation in place; the problem is you go one step too far; the for loop should be: for (int i = y; i < x-1; i++) – Pandrei Feb 11 '16 at 10:21