Yannis Dran
Yannis Dran

Reputation: 1529

How copy an array's contents into two smaller arrays of unequal size

I am trying to copy contents of a larger array to two smaller arrays of an unequal size each (of which size may change according to the program). I have four arrays at the simplified code below:

#define size 20
double bigArray[size]={14.553,13.653,9.555,8.564..and so on...9.324,11.123};
/*IndicatorArray is associated to bigArray as follows:
 if bigArray[i]<10 then indicatorArray[i]=10 else =20 */
int indicatorArray[size]={20,20,10,10,..and so on..};
double array10[count10], array20[count20]; /*count10 and count20 are 
counters from indicatorArray passed as a size of each array 
in earlier function not shown here*/
for (i=0;i<size;i++){
        if (indicatorArray[i]==10) {
            arr10[i]=bigArray[i];
        //  printf("%lf ",arr10[i]); /*this shows me correct results*/
        }
        else {
            arr20[i]=bigArray[i];
        }
    }
    for (i=0;i<count10;i++){
        printf("%lf ",arr10[i]);
    }
    printf("\n \n");
    for (i=0;i<count20;i++){
        printf("%lf ",arr20[i]);
    }

The result is something like

00.0000 00.0000 9.555 8.564 11.123 14.666 ....

14.553 13.653 00.000......00.000

but I don't want zeros to appear or have such disrupted results but something like

9.55 8.564 ...... 7.123 and 14.533 13.653 .....11.123

Why does this happen and how to do it in the right way?

Upvotes: 1

Views: 154

Answers (3)

ryyker
ryyker

Reputation: 23218

As mentioned in comments, when splitting the contents of an array, recognize each element is located in a specific addressable place in memory, making this a perfect job for memcpy(). Here is a simple illustration using that concept:

int main(void)
{
    double source[] = {3.4,5.6,2.3,4.5,6.7,8.9,10.1,11.1,12.3,4.5};
    double split1[3];
    double split2[7];

    memcpy(split1, &source[0], 3*sizeof(double));
    memcpy(split2, &source[3], 7*sizeof(double));

    return 0;   
}

If your project has well defined and static parameters that are known at runtime, then using a few common macros, and some additional variables, this could be made a little more general.

The following example does essentially the same as the illustration above, but in a loop, potentially a more adaptable construct.

#define SPLIT_CNT 3

int main(void)
{
    double source[] = {3.4,5.6,2.3,4.5,6.7,8.9,10.1,11.1,12.3,4.5,8.5,9.5};
    double split1[3];                         // arrays if differing sizes
    double split2[7];
    double split3[2];
    size_t start_pos;                         //position accumulator
    size_t cpy_len[SPLIT_CNT] = {3,7,2};      //known array sections
    double *split[] = {split1,split2,split3}; //enables looping on arrays of differing sizes
    start_pos = 0;
    for(int i=0;i<SPLIT_CNT;i++)
    {
        if(i > 0)start_pos += cpy_len[i-1]; //move the start postition  
        memcpy(split[i], &source[start_pos], sizeof(double)*cpy_len[i]);
    }

    return 0;   
}

Upvotes: 3

Patrick
Patrick

Reputation: 368

As someprogrammerdude commented, you should look into using memcpy when copying data. If you still want to use your implementation instead, the problem lies with how you use i in the for loop. Remember that in this instance, i will be the position in the big array that the number you want to copy appears. If you want the first element you copy from the big array to be in position 0 of one of the smaller arrays, there's no way that will happen for both if you use arr10[i] and arr20[i]. Instead you can use a counter for each smaller array and increment each time an element goes into it. Here's a quick example I did with an online compiler after hard coding some values:

int arr10Count = 0;
int arr20Count = 0;

int i;
for (i=0;i<size;i++){
        if (indicatorArray[i]==10) {
            arr10[arr10Count]=bigArray[i];
            arr10Count++;
        //  printf("%lf ",arr10[i]); /*this shows me correct results*/
        }
        else {
            arr20[arr20Count]=bigArray[i];
            arr20Count++;
        }
    }

Upvotes: 1

Bodo
Bodo

Reputation: 9855

Use separate counters for the index in array10 and array20.

#define size 20

double bigArray[size]={14.553,13.653,9.555,8.564..and so on...9.324,11.123};

/*IndicatorArray is associated to bigArray as follows:
 if bigArray[i]<10 then indicatorArray[i]=10 else =20 */
int indicatorArray[size]={20,20,10,10,..and so on..};

double array10[count10], array20[count20]; /*count10 and count20 are 
counters from indicatorArray passed as a size of each array 
in earlier function not shown here*/

size_t i10; /* index for array10 *** */
size_t i20; /* index for array20 *** */

for (i=0, i10=0, i20=0; i<size; i++){
        if (indicatorArray[i]==10) {
            if(i10 < count10) { /* prevent array index out of range *** */
                arr10[i10++]=bigArray[i];
            }
        }
        else {
            if(i20 < count20) { /* prevent array index out of range *** */
                arr20[i20++]=bigArray[i];
            }
        }
    }
    for (i=0;i<count10;i++){
        printf("%lf ",arr10[i]);
    }
    printf("\n \n");
    for (i=0;i<count20;i++){
        printf("%lf ",arr20[i]);
    }

Upvotes: 0

Related Questions