Home > Mobile >  how to filter an array and overwrite that
how to filter an array and overwrite that

Time:04-13

I need to filter some specific elements from an array. I write the code which work perfectly:

#include <stdio.h>
#define NELEMS(x)  (sizeof(x) / sizeof((x)[0]))
int main (int argc, char *argv[]) {
    // our initial array
    int x[] = {1,2,-3,4,5};
    // initialize filtered_array with pointer
    int *filtered;
    int upper_bound = 4, lower_bound = 1, i, j=0, total = -1,result;
    size_t n = NELEMS(x);
    printf("size of the main array: %d\n",n);

    // check which element satisfy the condition and count them
    for (i=0;i<n;  i)
    {
        total = ((x[i] >= lower_bound) && (x[i] <= upper_bound)) ? total 1 : total;
    };

    // allocate array size for filtered array
    filtered = (int*) calloc(total,sizeof(int));
    for (i=0;i<n;  i)
    {
        // filter element from main array and store them in filtered array
        result = ((x[i] >= lower_bound) && (x[i] <= upper_bound)) ? 1 : 0;
        if(result) {
            filtered[j] = x[i];
              j;
        };
    };
    for (i = 0; i<total 1;   i){
        printf("%d ",filtered[i]);
    };
    return 0;
}

But can I avoid to create a new array like I used filtered and dynamically do this for the main array by some overwrite trick?

CodePudding user response:

That*s even pretty simple:

int* filter(int* begin, int* end)
{
    int* pos = begin;
    for(; begin != end;   begin)
    {
         if(*begin != 0) // your appropriate condition!
                         // this one filters out all zero values...
         {
             *pos   = *begin;
         }
    }
    return pos;
}

The return value is important to know how many elements remained.

If you prefer, you can instead write an index-based variant avoiding pointer arithmetics...

CodePudding user response:

For starters your program is incorrect.

Firstly you need to include the header <stdlib.h>

#include <stdlib.h>

Secondly, initially total is set to -1

total = -1

So if the original array contains only one element that satisfies the condition then total will be equal to 0 due to this statement

 total = ((x[i] >= lower_bound) && (x[i] <= upper_bound)) ? total 1 : total;

As a result this statement

filtered = (int*) calloc(total,sizeof(int));

is trying to allocate a memory with the size equal to 0. If the memory will be allocated (it is implementation defined) then you may not write anything in this memory. Otherwise the program will have undefined behavior.

In any case you are counting elements that satisfy the condition incorrectly and hence allocating a block of memory of an incorrect size.

Also there is no sense to insert a null statement after compound statements as you are doing

for (i=0;i<n;  i)
{
    //...
};

^^^

Remove such redundant semicolons.

And you are using an incorrect conversion specifier in this call of printf.

printf("size of the main array: %d\n",n);
                                ^^^

You have to write

printf("size of the main array: %zu\n",n);
                                ^^^

As for your question

But can I avoid to create a new array like I used filtered and dynamically do this for the main array by some overwrite trick?

then what you need is to change the array in place and to track the number of actual elements that satisfy the condition.

For example

int x[] = {1,2,-3,4,5};
// initialize filtered_array with pointer
size_t n = NELEMS(x);

int upper_bound = 4, lower_bound = 1;

printf( "size of the main array: %zu\n", n );

size_t m = 0;

for ( size_t i = 0; i < n;   i )
{
    if ( x[i] >= lower_bound) && x[i] <= upper_bound )
    {
        if ( m != i )
        {
            x[m] = x[i];
        }
          m;
    }
}

for ( size_t i = 0; i < m;   i )
{
    printf( "%d ", x[i] );
}

putchar( '\n' );

If you need to reallocate the original array according to the number of elements that satisfy the condition then the code can look for example the following way

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

//...

size_t n = 5;
int *x = malloc( n * sizeof( int ) );

memcpy( x, ( int[] ){ 1, 2, -3, 4, 5 }, n * sizeof( int ) );

int upper_bound = 4, lower_bound = 1;

printf( "size of the main array: %zu\n", n );

size_t m = 0;

for ( size_t i = 0; i < n;   i )
{
    if ( x[i] >= lower_bound) && x[i] <= upper_bound )
    {
        if ( m != i )
        {
            x[m] = x[i];
        }
          m;
    }
}

if ( m != n )
{
    int *tmp = realloc( x, m * sizeof( int ) );

    if ( tmp != NULL ) 
    {
        x = tmp;

        for ( size_t i = 0; i < m;   i )
        {
            printf( "%d ", x[i] );
        }

        putchar( '\n' );
    }
}

free( x );
  • Related