Allie H
Allie H

Reputation: 121

C - creating a struct with input-dependent number of arrays

I’m wondering if anyone could provide any advice on storing “class slices” of values? I.e., for a table of values (see below for example), I want to be able to store, for each row, an array of the values that corresponds to each class. I have already sorted the table by class and determined the number of classes and the number of elements in each class. I’ve written out the basic conditions that I think will let me iterate over each row, over each class with the goal of copying the values from one struct into the new “class slice arrays”:

int x = 0;
for(int i = 0; i < total_rows - 1; i++)
{
    for (int j = 0; j < n_classes; j++)
    {
        for (int k = 0; k < class_size[j]; k++)
        {
            data[x].value[i] =  // value at the xth position of the “class slice” array for the jth class of values in the ith row //
            x++;
        }
    }
}

where data[x].value[0] is the value I have stored for the xth sample in row i. I guess my question is - how would you start mallocing space for arrays to store these class slices if you don’t know how many you’re even going to need (since that’s dependent on the number of rows and the number of classes)?

Example input, if this helps to make it clearer:

Class   Case    Case    Case    Case    Case    Case    Case    Case    Case    Case    Case    Case    Case    Case    Control Control Control Control Control Control Control Control Control Control Control Control Control Control Control Control
Obs1   0.000741628 0.00308607  0.000267431 0.001418697 0.001237904 0.000761145 0.0008281   0.002426075 0.000236698 0.004924871 0.000722752 0.003758006 0.000104813 0.000986619 0.000121803 0.000666854 0   0.000171394 0.000877993 0.002717391 0.001336501 0.000812089 0.001448743 5.28E-05    0.001944298 0.000292529 0.000469631 0.001674047 0.000651526 0.000336615
Obs2   0.102002396 0.108035127 0.015052531 0.079923731 0.020643362 0.086480609 0.017907667 0.016279315 0.076263965 0.034876124 0.187481931 0.090615572 0.037460171 0.143326961 0.029628502 0.049487575 0.020175439 0.122975405 0.019754837 0.006702899 0.014033264 0.040024363 0.076610375 0.069287599 0.098896479 0.011813681 0.293331246 0.037558052 0.303052867 0.137591517
Obs3   0.218495065 0.242891829 0.23747851  0.101306336 0.309040188 0.237477347 0.293837554 0.34351816  0.217572429 0.168651691 0.179387106 0.166516699 0.099970652 0.181003474 0.076126675 0.10244981  0.449561404 0.139257863 0.127579104 0.355797101 0.354544105 0.262855651 0.10167146  0.186068602 0.316763006 0.187466247 0.05701315  0.123825467 0.064780343 0.069847682
Obs4   0.141137543 0.090948286 0.102502388 0.013063365 0.162060849 0.166292135 0.070215996 0.063535037 0.333743609 0.131011609 0.140936687 0.150108506 0.07812762  0.230704405 0.069792935 0.120770743 0.164473684 0.448110378 0.42599534  0.074094203 0.096525097 0.157661185 0.036737518 0.213931398 0.091119285 0.438073807 0.224921728 0.187034237 0.06611442  0.086005218
Obs5   0.003594044 0.003948354 0.008137536 0.001327901 0.002161974 0.003552012 0.002760334 0.001898667 0.001420186 0.003165988 0.001011853 0.001217382 0.000314439 0.004254794 0.000213155 0.003650147 0   0.002742309 0.002633978 0   0.002524503 0.002146234 0.001751465 0.006543536 0.003941146 0.00049505  0.00435191  0.001944054 0.001303053 0.004207692
Obs6   0.000285242 2.27E-05    0   1.13E-05    0.0002964   3.62E-05    0.000138017 0.000210963 0.000662753 0   0   0   0   4.11E-05    0   0   0   0   0.000101307 0   0   0   0   5.28E-05    0.00152391  0   0   0   0   0
Obs7   0.002624223 0.001134584 0.00095511  0.000419934 0.000401011 0.001739761 0.00272583  0.002566717 0.000520735 0.002311674 0.006287944 0   6.29E-05    0.000143882 3.05E-05    0.000491366 0   0   3.38E-05    0   0.001782002 0.000957104 0.002594763 0.000527704 0.000105097 0.001192619 3.13E-05    0   0.000744602 0.000252461
Obs8   0.392777683 0.383875286 0.451499522 0.684663315 0.387394299 0.357992026 0.488406597 0.423473155 0.27267563  0.47454646  0.331020526 0.484041709 0.735955056 0.338841956 0.781699147 0.625403622 0.313596491 0.270545891 0.379259109 0.498913043 0.372438372 0.446271644 0.606698813 0.305593668 0.360535996 0.29889739  0.328710081 0.521222594 0.419924299 0.584111756

Upvotes: 0

Views: 101

Answers (1)

ad absurdum
ad absurdum

Reputation: 21367

I think what you are looking for is a struct containing a pointer to double and an int that keeps track of the number of values being stored:

struct data {
    int numValues;
    double *value;
};

If you don't know how many data structs you need, you declare a pointer to one, and allocate them as needed. Whenever you allocate a new data struct, you set the value to point to NULL. As you add values, you reallocate storage, reset the value pointer, and update the counter for that struct. Here is a little toy example to illustrate how it works:

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

struct data {
    int numValues;
    double *value;
};

int main(void)
{
    struct data *myData;
    int numData = 0;
    int i, last;

    myData = NULL;

    ++numData;
    i = numData - 1;
    myData = realloc(myData, sizeof(*myData) * numData);

    myData[i].numValues = 0;
    myData[i].value = NULL;

    last = myData[i].numValues;
    myData[i].value = realloc(myData[i].value, sizeof(double) * (last + 1));
    myData[i].numValues += 1;
    myData[i].value[last] = 3.1415926536;

    last = myData[i].numValues;
    myData[i].value = realloc(myData[i].value, sizeof(double) * (last + 1));
    myData[i].numValues += 1;
    myData[i].value[last] = 2.7182818285;

    printf("Value [0][0]: %lf\n", myData[i].value[0]);
    printf("Value [0][1]: %lf\n", myData[i].value[1]);

    ++numData;
    i = numData - 1;
    myData = realloc(myData, sizeof(*myData) * numData);

    myData[i].numValues = 0;
    myData[i].value = NULL;

    last = myData[i].numValues;
    myData[i].value = realloc(myData[i].value, sizeof(double) * (last + 1));
    myData[i].numValues += 1;
    myData[i].value[last] = 1.6180340;

    last = myData[i].numValues;
    myData[i].value = realloc(myData[i].value, sizeof(double) * (last + 1));
    myData[i].numValues += 1;
    myData[i].value[last] = 2.99792458;

    printf("Value [1][0]: %lf\n", myData[i].value[0]);
    printf("Value [1][1]: %lf\n", myData[i].value[1]);

    /* Let's free all of the memory we allocated! */
    // first, free space allocated for values
    for (int j = 0; j <= i; j++)
        free(myData[j].value);

    // next, free space allocated for structs
    free(myData);

    return 0;

}

Edit

I cleaned up the code a bit and stored a couple of numbers in a second struct in an attempt to make the example a little more illustrative. I also added a few lines to free the allocated memory.

I am not exactly sure what your data is representing, but it might be useful to add a second dynamic array to the struct:

struct data {
    int numCase;
    int numControl;
    double *caseValue;
    double *controlValue;
};

Some variation on this idea would allow you to keep your "case" and "control" values separate, and you could manage the addition of new values as before.

Upvotes: 1

Related Questions