【问题标题】:How to solve the issue passing an unknown-sized 2D array to a function?如何解决将未知大小的二维数组传递给函数的问题?
【发布时间】:2013-03-12 13:29:30
【问题描述】:

我有一个程序,其中对象数组的大小是在运行时确定的,因此它是动态分配的(二维数组,从文件中读取)。我还有一个将这些对象作为参数的函数。问题是如果函数参数是传递给函数的二维数组,则应确定第二维。但是,就我而言,事实并非如此。我的程序无法编译,因为原型没有提到第二维。

这是我尝试过的:

//global variables
int residentCount=0;
int hospitalCount=0;
Resident** residents;
Hospital** hospitals;
bool readFromFiles(const string, const string, const int); //sizes are determined in here
void print(Hospital*[hospitalCount], Resident*[residentCount]); //declaration issue

我该如何解决这个问题?

【问题讨论】:

  • 当你需要动态数组时停止使用指针,而开始使用std::vector
  • 我为什么要这样做?
  • 因为那样你就不必担心这些事情了。使用the standard library让您作为 C++ 程序员的生活更轻松。
  • 我现在看到了困难:) 下一次,我一定会使用它。感谢您的建议。
  • @JoachimPileborg 请发布解决方案,以便我们对其进行投票。

标签: c++ arrays pointers parameter-passing multidimensional-array


【解决方案1】:

只需传递一个指向数组第一个元素和维度的指针,就足够了,例如:

void PrintHospitals(Hospital* Hospitals, size_t HospitalRows, size_t HospitalColumns)
{
  size_t i, j;
  Hospital* hospital;

  for (i = 0; i < HospitalRows; i++)
    for (j = 0; j < HospitalColumns; j++)
    {
      hospital = Hospitals + HospitalColumns * i + j;
      PrintHospital(hospital);
    }
}

int main()
{
  Hospital hospitals[10][20];
  // ...
  PrintHospitals(&hospitals[0][0], 10, 20);
  return 0;
}

【讨论】:

  • 这是一个解决方案,我很理解你的回答,但我觉得它在语义上不方便。你认为它在语义上方便吗?我的意思是,我不想将整个数组传递给在运行时确定尺寸的函数,然后打印它。我真的不想玩代码,做一些有效的事情,但我也在寻找一种“正确”的方式。如果真的没有其他方法,我会尝试这种解决方法(我不接受以其他方式更改数据结构)。
  • 没有人阻止您动态分配数组(通过 new 或 malloc 或其他方式)并传递变量而不是示例中的硬编码维度,例如 10 和 20。你能明白我在说什么吗?
  • 是的,我愿意。我不是在谈论那个,我在谈论你重新确定阵列的尺寸并使其成为一维阵列并安排循环,使其成为二维阵列。这就是我所说的“语义上不方便”,而不是数组的静态大小。
  • 很抱歉,但“语义上的不便”对我来说没有任何意义。这是有效的代码,它可以解决您的问题。如果您出于任何审美或其他原因不喜欢它,请不要使用它。
  • 我不知道你为什么生气,我的意图绝对不是那样,我首先感谢你的回答。只是想让你知道..
【解决方案2】:
您正在使用 C++ 进行编程,因此您应该:
  • 尽可能避免动态分配和自行处理内存管理
    • 利用具有自动存储持续时间的对象,关注RAII idiom
  • 避免使用 C 样式的数组,实际上避免编写通常只能编译为 C++ 的 C 代码
    • 使用 C++ 提供的强大功能,尤其是那些捆绑在 STL 中的功能
  • 当局部等效项足够时避免使用全局变量

这就是它的样子:

typedef std::vector<Resident> Residents;
typedef std::vector<Hospital> Hospitals;

// passing by const reference:
void print(const std::vector<Hospitals>&, const std::vector<Residents>&);

int main()
{
    std::vector<Hospitals> hospitals;
    std::vector<Residents> residents;
    ...
} // <-- lifetime of automatics declared within main ends here

请注意,hospitalsresidents 将是具有自动存储持续时间的对象,其使用方式与您的 C 样式 2D 数组类似。当执行超出main 的范围时,这些向量将被破坏并自动清理其元素(包括其元素的元素)之前所在的内存。

另外请注意,我建议您通过 const 引用传递,即 const std::vector&lt;Hospitals&gt;&amp;,它可以防止创建传递对象的副本,并且 const 关键字明确告诉调用者:“虽然你通过这个对象传递参考,我就不改了。”

【讨论】:

  • 感谢您的精彩回答。这个特殊的程序教会了我你所说的(经验就是一切,对吧?)。现在我了解了 STL 容器的美妙之处:)
【解决方案3】:

这是一个使用模板为现有数据创建二维数组包装器的解决方案:

template<typename T>
class Array2d {
  public:
  int Rows;
  int Cols;
  T** Data;

  Array2d(int rows, int cols, T** data) :
    Rows(rows),
    Cols(cols),
    Data(data) { }
};

void print(Array2d<Hospital> h, Array2d<Resident> r) {
  for (int i = 0; i < h.Rows; i++) {
    for (int j = 0; j < h.Cols; j++) {
      //Print Data[i][j] element here
    }
  }
  // Other print code
}

int main()
{
   Resident** residents;
   Hospital** hospitals;

   //Init data arrays

   Array2d<Hospital> h(10, 10, hospitals);
   Array2d<Resident> r(10, 10, residents);

   print(h, r);
}

【讨论】:

    猜你喜欢
    • 2012-04-27
    • 1970-01-01
    • 1970-01-01
    • 2017-07-26
    • 2011-05-24
    • 2017-11-22
    • 2011-08-20
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多