carraysalgorithmzero

Remove zero entries from an array in C


I have an array of values x = {0,0,1,2,3,0,0,7,8} and I want to remove the zero entries using C.

Attempt:

I am attempting to loop through each value in the array and check if the entry is not equal to zero. If this condition is true, then I am attempting to populate a new array with original array value.

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

int main() {
    int x[] = { 0, 0, 1, 2, 3, 0, 0, 7, 8 };
    int i;
    int x_upd[100];
    for (i = 0; i < 9; i++) {
        if (x[i] != 0) {
            x_upd[i] = x[i]; // if true, populate new array with value
        }
    }
    for (i = 0; i < 9; i++) {
        printf(" Peak updated %d\t", x_upd[i]); //
    }
    return 0;
}

The output is not giving me the values {1,2,3,7,8} as desired. Instead, I am getting garbage values at the location where the zeros used to be.

Any advice on what I am doing wrong here? Do I need an else statement?


Solution

  • There is already such a function in C++. It is named remove_copy. In C such a function can look the following way as it is shown in the demonstrative program below.

    #include <stdio.h>
    
    int * remove_copy(const int *in, size_t n, int *out, int value)
    {
        for (size_t i = 0; i != n; i++)
        {
            if (in[i] != value) *out++ = in[i];
        }
    
        return out;
    }
    
    int main( void )
    {
        int a[] = { 0, 0, 1, 2, 3, 0, 0, 7, 8 };
        int b[sizeof(a) / sizeof(*a)];
        const size_t N = sizeof(a) / sizeof(*a);
    
        int *last = remove_copy(a, N, b, 0);
    
        for (int *first = b; first != last; ++first)
        {
            printf("%d ", *first);
        }
    
        putchar('\n');
    
        return 0;
    }
    

    The program output is

    1 2 3 7 8
    

    Or the function can return the number of the copied values

    size_t remove_copy(const int *in, size_t n, int *out, int value)
    {
        size_t m = 0;
    
        for (size_t i = 0; i != n; i++)
        {
            if (in[i] != value) out[m++] = in[i];
        }
    
        return m;
    }
    

    As for your code then you need to use an additional variable that will keep the index in the destination array. For example

    int m = 0;
    
    for ( i = 0; i < sizeof( x ) / sizeof( *x ); i++ )
    {
        if ( x[i] != 0 )
        {
            x_upd[m++] = x[i]; // if true, populate new array with value
        }
    }
    
    for ( i = 0; i < m; i++ )
    {
        printf(" Peak updated %d\t", x_upd[i] ); //
    }
    

    In fact the first loop corresponds to the second function implementation shown above.