繁体   English   中英

传递两个不同的动态分配的数组以在C中运行

[英]Passing two different dynamically allocated arrays to function in C

我试图将分配在堆上的两个数组(一个NxN,一个1XN)传递给一个函数。 我一直得到分段错误11。根据gdb ,seg错误发生在double c=matrix[i][j]/matrix[j][j] 我忍不住觉得问题出在我在函数中声明参数的方式。

double **Mat_A=(double **) malloc(dim_matrix*sizeof(double));
double *Vec_B=(double *) malloc(dim_vector*sizeof(double));

//read in numbers from file
for(int i=0; i<dim_matrix; i++)
{
  for(int j=0; j<dim_matrix; j++)
  {
    fscanf(f1, "%lf%*[^\n]%*c", &Mat_A[i][j]);
  }
}
for(int k=0; k<dim_vector; k++)
{
  fscanf(f2, "%lf%*[^\n]%*c", &Vec_B[k]);
}

void reduce_mat(double **matrix, double *vector, int row, int column)
{
    int i;
    int j;
    for( j = 0; j < row; j++ )
    {
        for( i = 0; i < column; i++ )
        {
            if ( i != j )
            {
                double c= matrix[i][j] / matrix[j][j];
                for( int k = 0; k < column + 1; k++ )
                {
                    matrix[i][k] = matrix[i][k] - c * matrix[j][k];
                }
            }
         }
      }
      printf("\nSolution:\n");
      for(i=0; i<column; i++)
        {
          vector[i]=matrix[i][column+1]/matrix[i][i];
          printf("\nx%d=%f\n",i,vector[i]);
        }
      return;

我假设column是矩阵中列的序数,所以如果值是5则这些列的索引为0..4

但是,在您的if( i != j )...语句中,您有以下内容:

k < column + 1 // so `k == column` can be true
...
matrix[i][k]

这意味着您要使用偏移量i * row + k取消引用matrix指针,该偏移量可能超出范围。

这假定矩阵的缓冲区在每一行的末尾(对于其他列)没有多余的空间,在缓冲区的末尾也没有额外的行。

由于您没有提供矩阵形状的任何指示,因此我尝试使用非正方形矩阵。 事情似乎并没有像正方形矩阵那样好用,因此显示的代码可以在6x6正方形矩阵和6号矢量下工作。

这是使用GCC 7.2.0在运行macOS 10.13.1 High Sierra的Mac上对我来说可以正常运行的代码。 它从标准输入读取所有数据; 它写入标准输出。

dump_matrix()dump_vector()函数代表有用的函数类,该类以可读格式转储数据结构。 更通用的版本将文件流作为第一个参数,并在最后添加fflush(fp) ,并可能检查非空指针。 有时,它也有助于打印地址。

#include <stdio.h>
#include <stdlib.h>

static void reduce_mat(int row, int col, double matrix[row][col], double vector[col]);

static void dump_matrix(const char *tag, int row, int col, double matrix[row][col]);
static void dump_vector(const char *tag, int col, double vector[col]);

int main(void)
{
    FILE *f1 = stdin;
    int row = 6;
    //int col = 8;
    int col = 6;

    double (*Mat_A)[col] = malloc(row * col * sizeof(double));
    double *Vec_B =  malloc(col * sizeof(double));

    // read in numbers from standard input
    for (int i = 0; i < row; i++)
    {
        for (int j = 0; j < col; j++)
        {
            if (fscanf(f1, "%lf", &Mat_A[i][j]) != 1)
            {
                fprintf(stderr, "Read error matrix[%d,%d]\n", i, j);
                exit(1);
            }
        }
    }

    for (int k = 0; k < col; k++)
    {
        if (fscanf(f1, "%lf", &Vec_B[k]) != 1)      // Beware - changed to f1
        {
            fprintf(stderr, "Read error vector[%d]\n", k);
            exit(1);
        }
    }

    dump_matrix("Matrix A", row, col, Mat_A);
    dump_vector("Vector B", col, Vec_B);

    reduce_mat(row, col, Mat_A, Vec_B);

    dump_vector("Solution Vector", col, Vec_B);
    dump_matrix("Reduced  Matrix", row, col, Mat_A);

    free(Mat_A);
    free(Vec_B);

    return 0;
}

static void reduce_mat(int row, int col, double matrix[row][col], double vector[col])
{
    for (int j = 0; j < row; j++)
    {
        for (int i = 0; i < col; i++)
        {
            if (i != j)
            {
                double c = matrix[i][j] / matrix[j][j];
                for (int k = 0; k < col + 1; k++)
                {
                    matrix[i][k] = matrix[i][k] - c * matrix[j][k];
                }
            }
        }
    }

    printf("\nSolution:\n");
    for (int i = 0; i < col; i++)
    {
        vector[i] = matrix[i][col + 1] / matrix[i][i];
        printf("x%d = %9.2f\n", i, vector[i]);
    }
    putchar('\n');
}

static void dump_matrix(const char *tag, int row, int col, double matrix[row][col])
{
    printf("%s (matrix[%d][%d]):\n", tag, row, col);
    for (int i = 0; i < row; i++)
    {
        for (int j = 0; j < col; j++)
            printf("%9.2f", matrix[i][j]);
        putchar('\n');
    }
}

static void dump_vector(const char *tag, int col, double vector[col])
{
    printf("%s (vector[%d]):\n", tag, col);
    for (int i = 0; i < col; i++)
        printf("%9.2f", vector[i]);
    putchar('\n');
}

给定一个包含42个介于0和1000之间的随机浮点数的输入文件,将产生:

Matrix A (matrix[6][6]):
   994.60   955.00   769.60    32.10   950.10   555.90
   105.50   857.50   606.10   289.30   592.60    95.60
   437.50    90.20   264.10   262.40   879.00   708.20
   236.40     1.00   273.90   405.60     4.80   199.90
   114.90   713.70   433.90   739.00    42.10   184.80
   895.40   911.00   161.80   829.20   487.90   864.80
Vector B (vector[6]):
   543.10   258.70   556.60   101.50   685.30   899.30

Solution:
x0 =      0.76
x1 =      0.00
x2 =      0.00
x3 =     -0.00
x4 =     -0.00
x5 =     -0.00

Solution Vector (vector[6]):
     0.76     0.00     0.00    -0.00    -0.00    -0.00
Reduced  Matrix (matrix[6][6]):
   994.60     0.00     0.00     0.00     0.00     0.00
     0.00   756.20     0.00     0.00     0.00     0.00
    -0.00     0.00   154.36     0.00     0.00     0.00
    -0.00     0.00     0.00  -115.16     0.00     0.00
    -0.00     0.00     0.00     0.00 -7025.36     0.00
    -0.00     0.00     0.00     0.00     0.00  -237.16

我不知道这是否是一个适当的计算,但是与问题AFAICT中的代码相同(任何此类更改都是偶然的和无意的),我不知道。 修改了功能矩阵参数的类型,使其更易于管理,并且将内存分配分配给了指向double值数组的适当指针。 请注意,对于6x6阵列,实际上没有必要使用动态内存分配。 在堆栈上进行普通分配会很好。

可变长度数组(VLA)有用吗? 它们确实简化了很多矩阵处理代码。

对于VLA的堆栈分配,您确实需要注意堆栈有足够的空间。 如果没有,您的程序可能会崩溃。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM