开发者

passing multidimensional arrays to function when the dimension size is not clear

I have a function in my class which should get a multi-dimensional array. the problem is that the value of these dimensions is calculated in the class, using another function and is stored in some public variables. so all the other functions within the class can read the value stored in these vars. the definition of function is like this:

double calcSS(double tfpairexp[][max_ctrl_no][max_rep_no])

where max_ctrl_no and max_rep_no are those public variables. and I call the function like this:

calcSS(tfpairexp);

but the compiler gives error for the definition of the function. and if I put some constant numbers instead of those vars, there is no error. But I don't know the dimension when the program begins. what should I do?

Update

void tripleofgenes(int begind,int endind) {             
            for (int tf1=0; tf1<tfact; ++tf1)
            {   
                    for (int tf2=tf1+1; tf2<tfact; ++tf2)
                    { 
开发者_JAVA百科                        double tfpairexp[cchips][max_ctrl_no][max_rep_no];
                        double w,d;
                        int ctrl_no;int c, ctr;
                        for (int j = 0; j < cchips ; j += c)
                        {
                            c = chips[j].crepls;
                            int ctrl_no=0;
                            for (int *p = chips[j].ctrl ; p && (ctr=*p)>=0; ++p,ctrl_no++) {
                                for (int k = 0; k < c; ++k)
                                {
                                    double tf1exp=chips[k+j].vals[tf1].val-((chips[k+j].useextra) ? chips[ctr].extra[tf1] : chips[ctr].mean[tf1].val);
                                    double tf2exp=chips[k+j].vals[tf2].val-((chips[k+j].useextra) ? chips[ctr].extra[tf2] : chips[ctr].mean[tf2].val);
                                    tfpairexp[j][ctrl_no][k]=interactionFunc(tf1exp,tf2exp,1);
                                }
                            }
                        }
                        for (int tg=begind; tg<=endind; ++tg) 
                            if (tf1!=tg){

                        calcSS(tfpairexp);

                        }


                    }
            }
        fclose(f);
    }

    double calcSS(double ***tfpairexp)
    {
    for (int row = 0; row <= 1 ; row++)
                for (int col = 0; col <= 1 ; col++) {
                    int cond=0;
                    for (int j = 0; j < cchips; j += c) {
                        c = chips[j].crepls; // the number of replicants
                        int ctrl_no=0;
                        for (int *p = chips[j].ctrl; p && (ctr=*p)>=0; ++p,ctrl_no++) {
    a = tfpairexp[j][ctrl_no][k];}
    }
    }
    }
    }


The kind of arrays in you are using here (C-style) are not really designed to be used with dynamic sizes, though you can use new to allocate them that way. One solution for function calling is do use a double *** and three size_t parameters for dimensions to pass into a function, but that still requires you to declare the array in the caller with dimensions as large as you will ever need. or you will corrupt your process memory and likely crash.

A better solution is to use vector which is designed from the beginning to deal with array with runtime-determined sizes. You can either declare a multi-D vector and use it directly, or go for a single-dimensional vector and do a bit of math at access time to convert a triple of coordinates into an index into the vector.

Either way, you need the vector header, here is how I recommend placing that setup:

#include <vector> // in your includes

using std::vector; // at global scope immediately after all #includes

Some code samples. I'll use cchips for the size of the third dimension based on another answer. The multidimensional solution looks something like this:

// at global scope
typedef vector< vector<double> > vec2double;
typedef vector< vector<vec2double> > vec3double;

// in the caller of your calcSS after you know how big to make the array {
    vec3double tfairexp(cchips, vec2double(max_ctrl_no, vector<double>(max_rep_no)));
    // now fill up tfairexp
    calcSS(tfairexp);
// }

// important: pass a reference here, or you will copy the whole array at call time!
void calcSS(vec3double &tfairexp) {
    // you can use cchips etc here but don't have to:
    for (size_t i = 0; i < tfairexp.size(); i++) {
        for (size_t j = 0; j < tfairexp[0].size(); j++) {
            for (size_t k = 0; k < tfairexp[0][0].size(); k++) {
                // access tfairexp[i][j][k] here
            }
        }
    }
}

That solution will actually do 1+j+j*k allocations of dynamic arrays. You could instead write a wrapper class that would "own" the vector and do the dimension-translation stuff, and have the class you're currently writing use that. I'm making some stylistic sacrifices to continue to use your "public class member variables for dimension sizes" approach. However, this one more closely models how the compiler translates C-style multidimensional arrays, and only does one memory allocation per run:

// as a member of your class -- returns a live reference that can be assigned to!
double &vec3_get(vector<double> &array, const size_t i, const size_t j, const size_t k) {
    return array[i*max_ctrl_no*max_rep_no + j*max_rep_no +k];
}

// in caller of calcSS {
    vector<double> tfairexp(cchips*max_ctrl_no*max_rep_no);
    // fill in by doing vec3_get(tfairexp, i, j, k) = val;
    calcSS(tfairexp)
// }

// again, pass a reference to the vector!
void calcSS(vector<double> &tfairexp) {
    for (size_t i = 0; i < cchips; i++) {
        for (size_t j = 0; j < max_ctrl_no; j++) {
            for (size_t k = 0; k < max_rep_no; k++) {
                // access vec3_get(tfairexp, i, j, k) here
            }
        }
    }
}


double calcSS(double tfpairexp[][max_ctrl_no][max_rep_no])

One solution is to change the function signature to,

double calcSS(double ***tfpairexp, int M, int N, int P);

where M, N and P are dimensions of the arrray!

Or you can pass the instance of your class itself. After all, you've made the dimensions public in your class. And if this function is a member function of the class, then you don't even need to pass anything; you can access them from the function itself like this:

double calcSS(double ***tfpairexp)
{

      for(int i = 0 ; i < cchips ; i++ )
      {
           for(int j = 0 ; j < max_ctrl_no ; j++ )
          {
                for(int k = 0 ; k < max_rep_no ; k++ )
                {
                       //access elements as tfpairexp[i][j][k]
                }
          }
      }

}

You can see this answer if it solves your problem: using a function template

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜