【问题标题】:Variable size matrix in CC中的可变大小矩阵
【发布时间】:2012-04-08 20:26:44
【问题描述】:

如何在 C 中实现可变大小的矩阵(int)?为了澄清起见,我必须能够根据情况添加行和列(在 if 子句中)。

谢谢,维。

【问题讨论】:

    标签: c variables dynamic matrix size


    【解决方案1】:

    您可以编写一个可重用的组件,将接口与实现分开。 您应该做出的主要决定是实现稀疏或密集分配模式。

    假设一个密集模式,对象可能是

    在矩阵.h

    #include <stdio.h>
    
    typedef struct matrix {
      int nrows, ncols, *data;
    } matrix;
    
    matrix* allocate(matrix *mat, int nrows, int ncols);
    int *cell(const matrix *mat, int row, int col);
    matrix *addrow(matrix *mat);
    matrix *addcol(matrix *mat);
    matrix *print(FILE *f, matrix *mat);
    

    在matrix.c中

    #include "matrix.h"
    #include <assert.h>
    #include <stdlib.h>
    #include <string.h>
    
    matrix* allocate(matrix *mat, int nrows, int ncols)
    {
      assert(nrows > 0 && ncols > 0);
      mat->nrows = nrows;
      mat->ncols = ncols;
      mat->data = malloc(sizeof(int) * nrows * ncols);
      return mat;
    }
    
    int *cell(const matrix *mat, int row, int col)
    {
      assert(row >= 0 && row < mat->nrows);
      assert(col >= 0 && col < mat->ncols);
      return mat->data + row * mat->ncols + col;
    }
    
    matrix *addrow(matrix *mat)
    {
      mat->nrows++;
      mat->data = realloc(mat->data, sizeof(int) * mat->nrows * mat->ncols);
      return mat;
    }
    
    /* adding a column it's an expensive operation */
    matrix *addcol(matrix *mat)
    {
      mat->ncols++;
      mat->data = realloc(mat->data, sizeof(int) * mat->nrows * mat->ncols);
    
      /* shift rows' elements, to make room for last column */
      for (int r = mat->nrows - 1; r > 0; --r)
      {
        int *dest = mat->data + r * mat->ncols,
            *orig = mat->data + r * (mat->ncols - 1);
        memmove(dest, orig, sizeof(int) * (mat->ncols - 1));
      }
      return mat;
    }
    
    matrix *print(FILE *f, matrix *mat)
    {
        for (int r = 0; r < mat->nrows; ++r)
        {
            for (int c = 0; c < mat->ncols; ++c)
                fprintf(f, "%4d ", *cell(mat, r, c));
            fprintf(f, "\n");
        }
        return mat;
    }
    
    int main_matrix(int argc, char **argv)
    {
        matrix m;
        allocate(&m, 3, 5);
    
        for (int r = 0; r < m.nrows; ++r)
            for (int c = 0; c < m.ncols; ++c)
                *cell(&m, r, c) = 35;
        print(stdout, &m);
        fprintf(stdout, "\n");
    
        addrow(&m);
        for (int c = 0; c < m.ncols; ++c)
            *cell(&m, m.nrows - 1, c) = 45;
        print(stdout, &m);
        fprintf(stdout, "\n");
    
        addcol(&m);
        for (int r = 0; r < m.nrows; ++r)
            *cell(&m, r, m.ncols - 1) = 46;
        print(stdout, &m);
        fprintf(stdout, "\n");
    
        // remember to free memory
        free(m.data);
    
        return argc;
    }
    

    测试输出:

      35   35   35   35   35 
      35   35   35   35   35 
      35   35   35   35   35 
    
      35   35   35   35   35 
      35   35   35   35   35 
      35   35   35   35   35 
      45   45   45   45   45 
    
      35   35   35   35   35   46 
      35   35   35   35   35   46 
      35   35   35   35   35   46 
      45   45   45   45   45   46 
    

    【讨论】:

      【解决方案2】:

      我看到你不想像这样声明:int arr[5][5];

      您可以使用mallocrealloc 来完成我的工作。例如动态创建二维数组:

      int nrows;
      int ncolumns;
      
      scanf("%d %d", &nrows, &ncolumns);
      
      int **arr = malloc(nrows * sizeof(int *));
          for(i = 0; i < nrows; i++)
              arr[i] = malloc(ncolumns * sizeof(int));
      

      如果要更改大小,请发送至realloc。使用 realloc 的好处是它会自动将值从原始内存位置复制到新位置,以防万一它无法在同一区域中扩展内存。

      注意这里是二维数组。如果您想更改尺寸本身,或者如果您希望能够修改尺寸,那么您可以使用与上述类似的代码,为每种情况使用不同的功能。同样,这看起来有点难看。但是在 C 中没有优雅的方式来做这些事情。

      【讨论】:

        【解决方案3】:

        仅仅因为 C 语言不支持封装和信息隐藏等面向对象的思想,并不意味着您不能在代码中使用它们;你只需要更加努力地把它们付诸实施。

        我已经很久没有写更具体的 C 语言了,但是斯坦福大学的 Eric Roberts 在 C 编程课程中教授了一些很棒的技术。我建议你调查一下。

        您的想法是,您必须为新大小的矩阵重新分配内存,将旧元素复制到其中,初始化新值,清理旧内存,并将新矩阵分配给指针变量。如果您将所有这些隐藏在一个方法中,您的代码的客户只会调用它,而不用担心您在下面做的魔术。您不必在多个地方重复复杂性。您只需调用一个方法即可完成。

        【讨论】:

          【解决方案4】:

          一旦知道大小,就必须在堆上分配足够的空间来容纳该大小。您可以使用malloccalloc 在堆上分配空间。

          例如:

          #include <stdio.h>
          #include <stdlib.h>
          
          void set_value(int * matrix, int row, int col, int value);
          int get_value(int * matrix, int row, int col);
          
          int main() {
              int rows = 5; /* arbitrary */
              int cols = 3; /* arbitrary */
              int * matrix = (int *) calloc(rows * cols, sizeof(int));
          
              if (matrix == NULL) {
                  printf("Error with allocation!\n");
                  return -1;
              }
          
              set_value(matrix, 0, 0, 5);
              set_value(matrix, 0, 1, 2);
              set_value(matrix, 4, 2, 1);
          
              printf("%d\n", get_value(matrix, 0, 0));
              printf("%d\n", get_value(matrix, 0, 1));
              printf("%d\n", get_value(matrix, 4, 2));
          
              free(matrix);
          
              return 0;
          }
          
          void set_value(int * matrix, int row, int col, int value) {
              *(matrix + col * sizeof(int) + row) = value;
          }
          
          int get_value(int * matrix, int row, int col) {
              return *(matrix + col * sizeof(int) + row);
          }
          

          请确保您始终检查对 malloccalloc 的调用是否有效,并且您以后始终使用 free 释放内存。

          如果您需要调整矩阵大小,您将不得不使用realloc 或在堆上请求更多空间,复制您的值并释放旧内存。

          【讨论】:

          • 一开始不知道尺寸。我会根据条件子句逐步添加行和列。
          【解决方案5】:

          我认为您可以使用动态内存分配“malloc”创建缓冲区

          【讨论】:

          • 欢迎来到 SO!回答问题时,尽量具体,并尽可能包含代码。
          【解决方案6】:

          我只是写了它...希望它会工作。

          int **matrix;
          
          int m=10;
          int n=10;
          
          int i,j;
          
          matrix = (int)** malloc (m*sizeof(int*));
          for(i=0;i<m;i++){
          matrix[i]= (int)* malloc (n*sizeof(int));
          for(j=0;j<n;j++)
          matrix[i][j] = (10.0*rand());
          }
          
          free(matrix);
          

          【讨论】:

          • 仅释放matrix时出现大内存泄漏
          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2015-04-11
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多