user2252004
user2252004

Reputation: 49

Copy elements from C array into a different array

I am finishing up working on a circular buffer that needs to double it size when it becomes full. However, I am having trouble figuring out how to copy the elements from the old buffer into the new buffer. My code is as follows:

#define startSize 10
#define fiveMin 300

cbuf* cbuf_init(){

    cbuf *buffer = malloc(sizeof(cbuf) + 9 * sizeof(quote));
    buffer->currSize = 0;
    buffer->maxSize = startSize;
    //buffer->startAt = 0;
    buffer->start = 0;
    buffer->end = 0;
    buffer->freeSlots = startSize;
    //buffer->currIndex = 0;
    return buffer;
}

void cbuf_update(cbuf *cb_ptr, unsigned int time, double rate){


    if(cb_ptr->freeSlots == 0){
        printf("EXPANDING CIRCULAR BUFFER!\n");
        cbuf *newBuffer = malloc(sizeof(cbuf) + 19 * sizeof(quote));
        newBuffer->maxSize = cb_ptr->maxSize * 2;
        newBuffer->start = cb_ptr->start;
        newBuffer->end = cb_ptr->end;
        newBuffer->freeSlots = newBuffer->maxSize - cb_ptr->maxSize;
        int x;
        for(x = 0; x < cb_ptr->maxSize; x ++){
            printf("Copying from slot %d\n", x);
            printf("Currently Copying time: %d\t Rate: %f\n", cb_ptr->quoteBuffer[x].time, cb_ptr->quoteBuffer[x].rate);
            newBuffer->quoteBuffer[x].time = cb_ptr->quoteBuffer[x].time;
            newBuffer->quoteBuffer[x].rate = cb_ptr->quoteBuffer[x].rate;
        }
        cb_ptr = newBuffer;

    }

    //If the start pointer has reached the end of the array and there are still free slots back at the beginning of the array, loop back.   
    if(cb_ptr->start == cb_ptr->maxSize && cb_ptr->freeSlots > 0){
        cb_ptr->start = 0;
    };

    cb_ptr->quoteBuffer[cb_ptr->start].time = time;
    cb_ptr->quoteBuffer[cb_ptr->start].rate = rate;
    cb_ptr->start = cb_ptr->start +1;
    cb_ptr->freeSlots = cb_ptr->freeSlots -1;

    //If any quote in the array is older than 5 minutes when compared to the current quote, flag it as null and move the end pointer up one.
    //Also, clear up a freeSlot.
    int x;
    for(x = cb_ptr->end; x < (cb_ptr->start); x ++){

        if((time) - (cb_ptr->quoteBuffer[x].time) >= fiveMin){
            cb_ptr->end = cb_ptr->end + 1;
            cb_ptr->quoteBuffer[x].time = -1;
            cb_ptr->quoteBuffer[x].rate = -1.00;
            cb_ptr->freeSlots = cb_ptr->freeSlots +1;
        }
    }



}


void cbuf_dump(cbuf *cb_ptr){
    printf("*****\t DUMPING \t*****\n");

    if(cb_ptr->start > cb_ptr->end){
        int x;
        for(x = cb_ptr->end; x<(cb_ptr->start); x++){
            printf("%d.) time = %d, \t rate = %f\n",x,(cb_ptr->quoteBuffer[x].time),(cb_ptr->quoteBuffer[x].rate));
        }
    }

    /*
    If the start pointer has been wrapped back around to the beginning of the circular buffer, then the end pointer must be at an index that is         greater than the start index. For this, we need to print out the data ranging from the end pointer to the end of the array, and then the        data from the start pointer to the end pointer provided the data isn't flagged as null (having -1 for both entries in the quote struct).
    */
    if(cb_ptr->end > cb_ptr->start){
        int x;
        for(x=cb_ptr->end; x < cb_ptr->maxSize; x ++){
            printf("%d.) time = %d, \t rate = %f\n",x,(cb_ptr->quoteBuffer[x].time),(cb_ptr->quoteBuffer[x].rate));
        }
        int y;
        for(y = 0; y < cb_ptr->start; y ++){
            if(cb_ptr->quoteBuffer[y].time != -1){
                printf("%d.) time = %d, \t rate = %f\n",y,(cb_ptr->quoteBuffer[y].time),(cb_ptr->quoteBuffer[y].rate));
            }
        }
    }

    printf("freeslots = %d\n", cb_ptr->freeSlots);
}

int main(){

    cbuf *cb1 ;

    cb1 = cbuf_init() ;
    cbuf_update(cb1, 60, 1.291) ;
    cbuf_update(cb1, 63, 1.287) ;
    cbuf_update(cb1, 63, 1.231) ;
    cbuf_update(cb1, 69, 1.229) ;
    cbuf_update(cb1, 72, 1.247) ;
    //cbuf_dump(cb1);
    cbuf_update(cb1,361,1.291);
    //cbuf_dump(cb1);

    cbuf_update(cb1, 411, 1.291) ;
    //cbuf_dump(cb1);
    cbuf_update(cb1, 412, 1.281) ;
    cbuf_update(cb1, 413, 1.292) ;
    cbuf_update(cb1, 414, 1.284) ;
    //cbuf_dump(cb1);
    cbuf_update(cb1, 414, 1.290) ;
    //cbuf_dump(cb1);
    //cbuf_update(cb1, 415, 1.290) ;
    //cbuf_dump(cb1);

    cbuf_update(cb1, 511, 1.241) ;
    cbuf_update(cb1, 512, 1.251) ;
    cbuf_update(cb1, 513, 1.232) ;
    cbuf_update(cb1, 514, 1.202) ;
    cbuf_update(cb1, 517, 1.119) ;
    cbuf_dump(cb1);
    return 0;

}

The issue is in main when it tries to insert the last quote and needs to expand (the last quote being:

cbuf_update(cb1, 517, 1.119)

My confusion is how to assign the newBuffer cbuf struct to the cb_ptr buffer. They are both pointers to cbufs, but how do I assign cb_ptr to the newBuffer?

My output is currently:

EXPANDING CIRCULAR BUFFER!
Copying from slot 0
Currently Copying time: 414  Rate: 1.290000
Copying from slot 1
Currently Copying time: 511  Rate: 1.241000
Copying from slot 2
Currently Copying time: 512  Rate: 1.251000
Copying from slot 3
Currently Copying time: 513  Rate: 1.232000
Copying from slot 4
Currently Copying time: 514  Rate: 1.202000
Copying from slot 5
Currently Copying time: 361  Rate: 1.291000
Copying from slot 6
Currently Copying time: 411  Rate: 1.291000
Copying from slot 7
Currently Copying time: 412  Rate: 1.281000
Copying from slot 8
Currently Copying time: 413  Rate: 1.292000
Copying from slot 9
Currently Copying time: 414  Rate: 1.284000
*****    DUMPING    *****
freeslots = 0

Upvotes: 1

Views: 291

Answers (1)

WhozCraig
WhozCraig

Reputation: 66194

Save for arrays (which decay to a pointer to their base), everything in C must be passed by address if you want to modify it, including pointers. Like anything else, declare the parameter to be a pointer to the type you want to modify (in this case it will be a pointer to a pointer-to-cbuf), then pass the address of the pointer on the caller side

The most minimal change I can think of for your code would be:

void cbuf_update(cbuf **cb_pptr, unsigned int time, double rate)
{
    // extract pointer value stored in in/out parameter
    cbuf *cb_ptr = *cb_pptr;

    if(cb_ptr->freeSlots == 0)
    {
        printf("EXPANDING CIRCULAR BUFFER!\n");
        cbuf *newBuffer = malloc(sizeof(cbuf) + 19 * sizeof(quote));
        newBuffer->maxSize = cb_ptr->maxSize * 2;
        newBuffer->start = cb_ptr->start;
        newBuffer->end = cb_ptr->end;
        newBuffer->freeSlots = newBuffer->maxSize - cb_ptr->maxSize;
        int x;
        for(x = 0; x < cb_ptr->maxSize; x ++){
            printf("Copying from slot %d\n", x);
            printf("Currently Copying time: %d\t Rate: %f\n", cb_ptr->quoteBuffer[x].time, cb_ptr->quoteBuffer[x].rate);
            newBuffer->quoteBuffer[x].time = cb_ptr->quoteBuffer[x].time;
            newBuffer->quoteBuffer[x].rate = cb_ptr->quoteBuffer[x].rate;
        }
        free(cb_ptr);
        *cb_pptr = cb_ptr = newBuffer;
    }

    //If the start pointer has reached the end of the array and there are still free slots back at the beginning of the array, loop back.
    if(cb_ptr->start == cb_ptr->maxSize && cb_ptr->freeSlots > 0){
        cb_ptr->start = 0;
    };

    cb_ptr->quoteBuffer[cb_ptr->start].time = time;
    cb_ptr->quoteBuffer[cb_ptr->start].rate = rate;
    cb_ptr->start = cb_ptr->start +1;
    cb_ptr->freeSlots = cb_ptr->freeSlots -1;

    //If any quote in the array is older than 5 minutes when compared to the current quote, flag it as null and move the end pointer up one.
    //Also, clear up a freeSlot.
    int x;
    for(x = cb_ptr->end; x < (cb_ptr->start); x ++){

        if((time) - (cb_ptr->quoteBuffer[x].time) >= fiveMin){
            cb_ptr->end = cb_ptr->end + 1;
            cb_ptr->quoteBuffer[x].time = -1;
            cb_ptr->quoteBuffer[x].rate = -1.00;
            cb_ptr->freeSlots = cb_ptr->freeSlots +1;
        }
    }
}

Believe me, it won't get much more minimal-change than that. Unfortunately you will have to change all the update calls. No getting around that. They will take this form:

cbuf_update(&cb1, 60, 1.291);

If you free this thing back on the caller side, free as normal:

free(cb1);

Hope that makes sense. Definitely explore the virtues of memcpy() for your actual data-copy. It will make it considerably less cluttered.

Upvotes: 2

Related Questions