Передача многомерных массивов в функцию, когда размер измерения неясен - PullRequest
0 голосов
/ 23 января 2011

В моем классе есть функция, которая должна получить многомерный массив.проблема заключается в том, что значение этих измерений вычисляется в классе с использованием другой функции и сохраняется в некоторых открытых переменных.так что все другие функции в классе могут читать значения, хранящиеся в этих переменных.определение функции выглядит следующим образом:

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

, где max_ctrl_no и max_rep_no являются этими public переменными.и я вызываю функцию следующим образом:

calcSS(tfpairexp);

, но компилятор выдает ошибку для определения функции.и если я поставлю некоторые постоянные числа вместо этих переменных, ошибки не будет.Но я не знаю размер, когда начинается программа.что мне делать?

Обновление

void tripleofgenes(int begind,int endind) {             
            for (int tf1=0; tf1<tfact; ++tf1)
            {   
                    for (int tf2=tf1+1; tf2<tfact; ++tf2)
                    { 
                        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];}
    }
    }
    }
    }

Ответы [ 2 ]

2 голосов
/ 23 января 2011

Типы используемых вами массивов (в стиле C) на самом деле не предназначены для использования с динамическими размерами, хотя вы можете использовать new для их распределения таким образом. Одним из решений для вызова функции является использование параметров double *** и трех size_t для измерений, передаваемых в функцию, но для этого все равно требуется объявить массив в вызывающей программе с размерами, которые вам когда-либо понадобятся. или вы повредите память процесса и, скорее всего, потерпите крах.

Лучшее решение - использовать vector, который с самого начала предназначен для работы с массивом с размерами, определяемыми во время выполнения. Вы можете либо объявить многомерный вектор и использовать его напрямую, либо перейти к одномерному вектору и выполнить математические расчеты во время доступа, чтобы преобразовать тройку координат в индекс в вектор.

В любом случае, вам нужен векторный заголовок, вот как я рекомендую разместить эту настройку:

#include <vector> // in your includes

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

Некоторые примеры кода. Я буду использовать cchips для размера третьего измерения, основанного на другом ответе. Многомерное решение выглядит примерно так:

// 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
            }
        }
    }
}

Это решение на самом деле будет делать 1+j+j*k размещения динамических массивов. Вместо этого вы могли бы написать класс-обертку, который бы «владел» вектором и выполнял трансляцию измерений, и чтобы класс, который вы сейчас пишете, использовал это. Я делаю некоторые стилистические жертвы, чтобы продолжать использовать ваш подход «переменные-члены открытого класса для размеров размеров». Однако этот пример более точно моделирует, как компилятор переводит многомерные массивы в стиле C, и выполняет только одно выделение памяти за цикл:

// 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
            }
        }
    }
}
0 голосов
/ 23 января 2011
double calcSS(double tfpairexp[][max_ctrl_no][max_rep_no])

Одним из решений является изменение сигнатуры функции на

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

, где M, N и P - размеры массива!Вы можете передать экземпляр вашего класса сам.В конце концов, вы обнародовали измерения в своем классе.И если эта функция является функцией-членом класса, вам даже не нужно ничего передавать;Вы можете получить к ним доступ из самой функции следующим образом:

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]
                }
          }
      }

}

Этот ответ можно увидеть, если он решит вашу проблему: с использованием шаблона функции

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...