如何从更大的矩阵中提取2x2子矩阵

时间:2010-05-09 13:33:54

标签: c matrix submatrix

我是一个非常基本的用户,对C中使用的命令知之甚少,所以请耐心等待...我不能使用非常复杂的代码。我对stdio.h和ctype.h库有一些了解,但就此而言。 我在txt文件中有一个矩阵,我想根据输入的行数和列数来加载矩阵

例如,我在文件中有一个5乘5的矩阵。我想提取一个特定的2乘2子矩阵,我该怎么做?

我使用:

创建了一个嵌套循环
FILE *sample
sample=fopen("randomfile.txt","r"); 
for(i=0;i<rows;i++){
  for(j=0;j<cols;j++){
     fscanf(sample,"%f",&matrix[i][j]);
   }
 fscanf(sample,"\n",&matrix[i][j]);
}
fclose(sample);

可悲的是,代码不起作用..如果我有这个矩阵:

5.00 4.00 5.00 6.00 
5.00 4.00 3.00 25.00 
5.00 3.00 4.00 23.00 
5.00 2.00 352.00 6.00

输入3为行,3为列,我得到:

5.00 4.00 5.00
6.00 5.00 4.00
3.00 25.00 5.00

不仅这不是一个2乘2的子矩阵,但即使我想要前3行和前3列,它也不能正确打印....

我需要从第3行和第3列开始,然后选择2乘2的子矩阵!

我应该最终得到:

4.00 23.00 
352.00 6.00

我听说我可以使用fgets和sscanf来实现这一目标。这是我的试用代码:

fgets(garbage,1,fin);
sscanf(garbage,"\n");

但这也不起作用:(

我做错了什么?

请帮忙。 谢谢!

3 个答案:

答案 0 :(得分:5)

好的,所以你想读一个大小 n x m 的子矩阵,从位置 x 开始, y 在大小 p x q 的大矩阵中。你需要两件事:

  1. (验证 x + n &lt; = p y + m &lt; = q
  2. 跳到要阅读的矩阵的第一个元素。这需要先跳过第一个 y - 1行
  3. 跳过 x - 下一行中的1个元素,然后将 n 元素读入子矩阵。重复 m 次。
  4. 您当前的实现从矩阵的第一个元素开始读取,然后将元素连续读入子矩阵。更新版本:

    FILE *sample = fopen("randomfile.txt", "r");
    // skip the first y-1 rows
    for (i = 0; i < y - 1; i++) {
      fscanf(sample, "%*[^\n]\n", &matrix[i][j]);
    }
    for (i = 0; i < m; i++) {
      // skip the first x-1 numbers
      for (j = 0; j < x - 1; j++) {
         fscanf(sample, "%*f");
      }
      // read n numbers
      for (j = 0; j < n; j++) {
         fscanf(sample, "%f", &matrix[i][j]);
      }
      if (x + n < p) {
        // consume the rest of the line
        fscanf(sample, "%*[^\n]\n");
      }
    }
    fclose(sample);
    

    更新:从数组中读取子矩阵甚至更简单,只需要更多的计算。要点是,一个大小为 p x q 的矩阵可以存储在一个大小为 p x q 这样矩阵[i,j]可以从数组[i *(j-1)+ j]中读取(大约 - 可能有一个错误,我不知道哪个是列,哪个是排,但希望你明白了: - )

    所以代码就像

    for (i = 0; i < m; i++) {
      for (j = 0; j < n; j++) {
         submatrix[i][j] = array[(y + i) * p + x + j];
      }
    }
    

答案 1 :(得分:2)

让我们分阶段进行。首先对代码进行一些小修复:

for(i=0;i<rows;i++){
  for(j=0;j<cols;j++){
    float dummy;  /* this will make thing easier later */
    fscanf(sample,"%f",&dummy);
    matrix[i][j] = dummy;
  }
/* fscanf(sample,"\n",&matrix[i][j]); this isn't even legal */
}

现在我们定义我们想要的东西:

int startrow = 2; /* The starting index. Remember we index 0,1,2,3 */
int startcol = 2;
int resultrows = 2; /* How many rows we want in our answer */
int resultcols = 2;
float result[resultrows][resultcols];

现在我们忽略了我们不想要的东西:

for(i=0;i<rows;i++){
  for(j=0;j<cols;j++){
    float dummy;
    fscanf(sample,"%f",&dummy);
    if(i >= startrow && i < startrow + resultrows &&
       j >= startcol && j < startcol + resultcols){
      matrix[i][j] = dummy;
    }
  }
}

请注意,现在只有我们想要的值被复制到matrixmatrix的其余部分是未初始化的乱码。现在将其写入result而不是:

for(i=0;i<rows;i++){
  for(j=0;j<cols;j++){
    float dummy;
    fscanf(sample,"%f",&dummy);
    if(i >= startrow && i < startrow + resultrows &&
       j >= startcol && j < startcol + resultcols){
      result[i-startrow][j-startcol] = dummy;
    }
  }
}

修改:
如果要从内存中已有的较大矩阵复制子矩阵,则内循环应为

for(j=0;j<cols;j++){
  if(i >= startrow && i < startrow + resultrows &&
     j >= startcol && j < startcol + resultcols){
      result[i-startrow][j-startcol] = matrix[i][j];
  }
}

答案 2 :(得分:1)

诀窍是让编译器将您的特定数组元素视为矩阵的起点;以下代码片段可以做到:

(int(*)[SIZE_OF_2ND_DIM])(&a[4][3])

以下程序捕获了预期目的:

#include <stdio.h>

int num;

void print( int a[][num], int row, int col )
{
  int i, j;
  for(i = 0; i < row; i++)
  {
    for(j = 0; j < col; j++)
      printf("%3d ", a[i][j]);
    printf("\n");
  }
}


int main()
{
  int a[10][10];
  int i, j;

  for(i = 0; i < 10; i++)
    for(j = 0; j < 10; j++)
      a[i][j] = i*10+j;

  num = 10;
  print(a, 10, 10);

  printf("\n\n");

  print((int(*)[num])(&a[4][3]), 5, 4);

  return 0;
}

以下是相应的输出:

  0   1   2   3   4   5   6   7   8   9
 10  11  12  13  14  15  16  17  18  19
 20  21  22  23  24  25  26  27  28  29
 30  31  32  33  34  35  36  37  38  39
 40  41  42  43  44  45  46  47  48  49
 50  51  52  53  54  55  56  57  58  59
 60  61  62  63  64  65  66  67  68  69
 70  71  72  73  74  75  76  77  78  79
 80  81  82  83  84  85  86  87  88  89
 90  91  92  93  94  95  96  97  98  99


 43  44  45  46
 53  54  55  56
 63  64  65  66
 73  74  75  76
 83  84  85  86