代码之家  ›  专栏  ›  技术社区  ›  NLed

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

  •  0
  • NLed  · 技术社区  · 14 年前

    我是一个非常基础的用户,对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 回复  |  直到 14 年前
        1
  •  5
  •   Péter Török    14 年前

    好吧,那么你想读一个尺寸的子矩阵 n X ,从位置开始 X , Y 在大矩阵中 X Q . 你需要两件事:

    1. (核实 X + n & = Y + & = Q )
    2. 跳到要读取的矩阵的第一个元素。这需要先跳过第一个 Y -1行
    3. 跳过 X -下一行中的1个元素,然后读取 n 元素进入你的潜艇。重复 时代。

    当前的实现从矩阵的第一个元素开始读取,然后连续地将元素读取到子矩阵中。更新版本:

    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);
    

    更新: 从数组中读取子矩阵更简单,只需要更多的计算。要点是,一个大小矩阵 X Q 可以存储在大小连续的数组中 X Q 这样就可以从数组[i*(j-1)+j]中读取矩阵[i,j](大约-可能有一个错误,我不确定哪一个是列,哪一个是行,但希望您得到这样的想法:-)

    所以代码应该是

    for (i = 0; i < m; i++) {
      for (j = 0; j < n; j++) {
         submatrix[i][j] = array[(y + i) * p + x + j];
      }
    }
    
        2
  •  2
  •   Beta    14 年前

    我们分阶段来做。首先对代码进行一些小的修改:

    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;
        }
      }
    }
    

    注意,现在只有我们想要的值被复制到 matrix ,其余的 矩阵 是未经初始化的胡言乱语。现在写进 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];
      }
    }
    
        3
  •  1
  •   LKB    9 年前

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

    (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