0

我是一个非常基础的用户,对 C 中使用的命令不太了解,所以请多多包涵……我不能使用非常复杂的代码。我对 stdio.h 和 ctype.h 库有一些了解,但仅此而已。我在 txt 文件中有一个矩阵,我想根据我输入的行数和列数加载矩阵

例如,我在文件中有一个 5 x 5 矩阵。我想提取一个特定的 2 x 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 x 2 子矩阵,而且即使我想要前 3 行和前 3 列,它也无法正确打印它......

我需要从第 3 行和第 3 列开始,然后取 2 x 2 子矩阵!

我应该最终得到:

4.00 23.00 
352.00 6.00

我听说我可以使用 fgets 和 sscanf 来完成这个。这是我的试用代码:

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

但这也不起作用:(

我究竟做错了什么 ?

请帮忙。谢谢 !

4

3 回答 3

5

好的,所以您想读取大小为n x m的子矩阵,从大小为p x q的大矩阵中的xy位置开始。你需要两件事:

  1. (验证x + n <= py + m <= q
  2. 跳到要读取的矩阵的第一个元素。这需要首先跳过前y - 1 行
  3. 从下一行跳过x - 1 个元素,然后将n 个元素读入您的子矩阵。重复m次。

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

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];
  }
}
于 2010-05-09T13:50:06.373 回答
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;
    }
  }
}

请注意,现在只有我们想要的值被复制到matrix中,其余的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];
  }
}
于 2010-05-09T14:30:31.823 回答
2

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

(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
于 2016-01-06T05:08:13.627 回答