在递归函数中通过引用传递的数组 - 最后一列重新初始化

Array passed by reference in recursive function - last column reinitialized

本文关键字:最后 一列 初始化 数组 递归函数 引用      更新时间:2023-10-16

我的一个函数遇到了一个相当意外的问题。让我解释一下。我正在编写一个校准算法,由于我想做一些网格搜索(非连续优化),我正在创建自己的网格 - 不同的概率组合。网格的大小和网格本身是递归计算的(我知道......所以按顺序:

  1. 获取变量
  2. 递归计算相应的大小
  3. 为网格分配内存
  4. 通过引用传递空网格并递归填充它

我遇到的问题是在步骤 4 之后,一旦我尝试检索此网格。在第 4 步中,我在控制台上"打印"结果以检查它们,一切都很好。我用几个变量计算了几个网格,它们都与我期望的结果相匹配。但是,一旦网格从递归函数中取出,最后一列就会用 0 填充(之前的所有值仅在此列中替换)。我尝试在步骤 3 中为网格分配一列额外的列,但这只会使问题变得更糟(-3e303 等值)。此外,无论我用什么大小(从小到非常大)计算它,我都有错误,所以我认为这不是内存错误(或至少是"内存不足"错误)。最后,下面列出了使用的两个函数及其调用,这已经快速编程,因此某些变量可能看起来有点无用 - 我知道。但是,我始终对您的评论持开放态度(而且我不是C++方面的专家 - 因此此线程)。

void size_Grid_Computation(int nVars, int endPoint, int consideredVariable, int * indexes, int &sum, int nChoices)
{
/** Remember to initialize r at 1 !! - we exclude var_0 and var_(m-1) (first and last variables) in this algorithm **/
 int endPoint2 = 0;
 if (consideredVariable < nVars - 2)
 {
    for (indexes[consideredVariable] = 0; indexes[consideredVariable] < endPoint; indexes[consideredVariable] ++)
    {
        endPoint2 = endPoint - indexes[consideredVariable];
        size_Grid_Computation(nVars, endPoint2, consideredVariable + 1, indexes, sum, nChoices);
    }
 }
 else
 {
    for (int i = 0; i < nVars - 2; i++)
    {
        sum -= indexes[i];
    }
    sum += nChoices;
    return;
 }
}

上述函数适用于网格大小。下面是网格本身 -

void grid_Creation(double* choicesVector, double** varVector, int consideredVariable, int * indexes, int endPoint, int nVars, int &r)
{
 if (consideredVariable > nVars-1)
    return;
 for (indexes[consideredVariable] = 0; indexes[consideredVariable] < endPoint; indexes[consideredVariable]++)
 {
    if (consideredVariable == nVars - 1)
    {   
        double sum = 0.0;
        for (int j = 0; j <= consideredVariable; j++)
        {
            varVector[r][j] = choicesVector[indexes[j]];
            sum += varVector[r][j];
            printf("%lft", varVector[r][j]);
        }
        varVector[r][nVars - 1] = 1 - sum;
        printf("%lf row %dn", varVector[r][nVars - 1],r+1);
        r += 1;
    }
    grid_Creation(choicesVector, varVector, consideredVariable + 1, indexes, endPoint - indexes[consideredVariable], nVars, r);
 }
}

最后的电话

#include <stdio.h>
#include <stdlib.h>
int main()
{
 int nVars = 5;
 int gridPrecision = 3;

int sum1 = 0;
int r = 0;
int size = 0;
int * index, * indexes;
index = (int *) calloc(nVars - 1, sizeof(int));
indexes = (int *) calloc(nVars, sizeof(int));
for (index[0] = 0; index[0] < gridPrecision + 1; index[0] ++)
{
    size_Grid_Computation(nVars, gridPrecision + 1 - index[0], 1, index, size, gridPrecision + 1);
}
double * Y;
Y = (double *) calloc(gridPrecision + 1, sizeof(double));
for (int i = 0; i <= gridPrecision; i++)
{
    Y[i] = (double) i/ (double) gridPrecision;
}
double ** varVector;
varVector = (double **) calloc(size, sizeof(double *));
for (int i = 0; i < size; i++)
{
    varVector[i] = (double *) calloc(nVars, sizeof(double *));
}

grid_Creation(Y, varVector, 0, indexes, gridPrecision + 1, nVars - 1, r);
for (int i = 0; i < size; i++)
{
    printf("%lfn", varVector[i][nVars - 1]);
}
}

我离开了我的野蛮人"printf",他们帮助缩小了问题的范围。最有可能的是,我忘记或屠杀了一个内存分配。但我看不出是哪一个。无论如何,感谢您的帮助!

在我看来,您有一个主要的错误设计,即您的 2D 数组。您在这里编程的不是 2D 数组,而是它的仿真。只有当你想要一种稀疏的数据结构,你可能会省略部分时,它才有意义。在您的情况下,它看起来好像只是一个您需要的普通旧矩阵。

如今,在

C 语言和C++中都不适合这样编程。

在 C 中,由于这似乎是您所追求的,在函数中,即使动态边界为

double A[n][m];

如果你担心这会破坏你的"堆栈",你可以动态分配它

double (*B)[m] = malloc(sizeof(double[n][m]));

通过将边界放在参数列表中的第一位来将这些野兽传递给函数

void toto(size_t n, size_t m, double X[n][m]) {
 ...
}

一旦你有了干净和可读的代码,你会发现你的错误要容易得多。