user152573
user152573

Reputation: 103

How should I approach the implementation of this C if statement given the requirements?

I am currently attempting to create a source code that meets these following requirements:

Requirements:

// Get a deep copy of a portion of array from index first to index last

// inclusive. If successful, return a pointer to a newly-allocated intarr_t containing a copy of the specfied section.

// If an error occurs, i.e. array is null, first or last are out of bounds, last < first, or memory allocation fails, return a null pointer.

I have completed the first two requirements, but it seems that my logic for the third one is faulty, and no matter how much I test it, I can't seem to find the corner case that occurs.

My code:

intarr_t* intarr_copy_subarray( intarr_t* array, 
                unsigned int first, 
                unsigned int last )
{
    intarr_t *tmp;
    tmp = malloc((last-first)*sizeof(intarr_t));
    // it seems that my if statement is not meeting the requirement in bold.
    if(first>=0 && last<= array->len && array != NULL && first > last && tmp != NULL)
    {
        //perform copying here
        return tmp; // pointer to new array containing the copied stuff
    }
    else
    {
        return NULL;
    }
}

typedef struct {
  int* data;
  unsigned int len;
} intarr_t;

There seems to be a case where it returns NULL when it is not supposed to and it has to do with my if statement. Note that I am passing my function a typedef structure that contains a pointer to an array and the length, but that isn't the problem. Should I be using OR statements rather than AND statements?

Upvotes: 2

Views: 258

Answers (2)

Vlad from Moscow
Vlad from Moscow

Reputation: 310910

The function can look like

intarr_t* intarr_copy_subarray( const intarr_t *array, 
                                unsigned int first, 
                                unsigned int last )
{
    if ( array == NULL || array->data == NULL || last < first || array->len <= last )
    {
        return NULL;
    }    

    intarr_t *tmp = malloc( sizeof( intarr_t ) );

    if ( tmp )
    {
        tmp->data = malloc( ( last - first + 1 ) * sizeof( int ) );
        if ( tmp->data == NULL )
        {
            free( tmp );
            tmp = NULL;
        }
        else
        {
            tmp->len = last - first + 1;
            for ( unsigned int i = 0; i < tmp->len; i++ ) 
            {
                tmp->data[i] = array->data[first + i];
            }
        }
    }

    return tmp;
} 

Upvotes: 0

2501
2501

Reputation: 25752

First of all check for NULL first:

if( !array  )
    return NULL ;

Then don't allocate just yet, but check if you arguments are in bounds:

if( first>=0 && last< array->len && first <= last )
{

Then allocate memory and if successful copy the array to the new subarray.

Your example allocation isn't correct given that intarr_t ( _t is a reserved identifier by the way ), holds a pointer to the int array. You should allocate one intarr_t and then the array it points to:

intarr_t tmp = malloc(sizeof(intarr_t)) ;
if( tmp )
{
     tmp->data = malloc( sizeof( int ) * ( last - first + 1 ) ) ;
     //check if malloc succeeded again
     tmp->len = last - first + 1 ;
     ...

Upvotes: 1

Related Questions