【问题标题】:passing multidimensional arrays to function when the dimension size is not clear当维度大小不明确时,将多维数组传递给函数
【发布时间】:2011-01-23 09:37:27
【问题描述】:

我的班级中有一个函数应该得到一个多维数组。问题是这些维度的值是在类中计算的,使用另一个函数并存储在一些公共变量中。因此类中的所有其他函数都可以读取存储在这些变量中的值。 函数的定义是这样的:

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

其中max_ctrl_nomax_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];}
    }
    }
    }
    }

【问题讨论】:

  • void Tripleofgenes(int begind,int endind) { for (int tf1=0; tf1
  • @Pegah:这个函数和 calcSS() 都是在你的类中定义的,对吧?
  • @Pegah:那么您不需要传递维度,因为您已经在该函数中拥有它们。只需将您的 calcSS() 定义为 calcSS(double ***arr).. 并像往常一样以 arr[i][j][k] 访问元素!
  • 我就是这样做的。你也可以在上面看到它。但它在这里说: calcSS(tfpairexp);我称之为 calcSS,它找不到合适的功能。
  • @Pegah:再次查看我的答案;我已经更新了。顺便说一句,你也可以发布错误消息吗?你为什么不一次发布所有相关的东西?

标签: c++ multidimensional-array


【解决方案1】:

您在此处使用的数组类型(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
            }
        }
    }
}

【讨论】:

  • 非常感谢。代码在这里:pastebin.com/UTg3Dd2P 我想你以为我在填充数组时不知道大小。你能看一下吗?
  • 谢谢。我尝试了你的最后一个解决方案,我的问题得到了解决。再次感谢您。
  • 不,我想你知道填充时它有多大。但是,在填充时知道数组有多大(在运行时)和知道有多大是有很大区别的数组是在编写代码时(-> 在编译时)。在程序运行之前你不知道的任何大小数据都必须使用动态分配来合并,无论是使用 operator new 还是使用向量等。
【解决方案2】:
double calcSS(double tfpairexp[][max_ctrl_no][max_rep_no])

一种解决方案是将函数签名更改为,

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

其中MNP 是阵列的尺寸!

或者你可以传递你的类本身的实例。毕竟,您已经在课堂上公开了维度。如果这个函数是类的成员函数,那么你甚至不需要传递任何东西;您可以像这样从函数本身访问它们:

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

}

如果它解决了你的问题,你可以看到这个答案:using a function template

【讨论】:

  • 感谢您的回答。在一个函数中,我计算 tfpairexp 的值,然后调用 calcSS 以使用存储在 tfpairexp 中的值。如果我编写像 double calcSS(double ***tfpairexp, int M, int N, int P) 这样的函数,我应该如何检索数组的值?第二:是的,起初我也想将 tfpairexp 定义为 public,所以所有函数都可以看到它。但由于尺寸的原因,我又遇到了同样的问题。你能解释一下你的意思吗?
  • @Pegah:你是 C++ 新手吗?您对此有何经验?我认为您需要先获取一些有关 C++ 的书并阅读它。 :-)
  • 不,很遗憾我不是新手。但我总是对指针有问题。我是这样写的: double tfpairexp[cchips][max_ctrl_no][max_rep_no];然后想象:tfpairexp[0][0][1]=10;等等。然后: calcSS(tfpairexp);对于 func 定义:double calcSS(double ***tfpairexp)。但它仍然给出错误:它在写的行中说“没有适当的功能”: calcSS(tfpairexp);
  • @Pegah : 在 C++ 中,如果维度未定义为 const,则不能编写 double tfpairexp[cchips][max_ctrl_no][max_rep_no];
  • @Pegah:仅某些编译器支持将变量用于数组维度——它不是 C++ 标准的一部分(参见 C++98、C++03 的 § 5.19)。因此它可能在某些编译器上的问题。
猜你喜欢
  • 1970-01-01
  • 2014-01-15
  • 1970-01-01
  • 1970-01-01
  • 2011-02-24
  • 2018-05-10
  • 2017-07-26
相关资源
最近更新 更多