Search code examples
cmatrixsubmatrix

How to extract a 2x2 submatrix from a bigger matrix


I am a very basic user and do not know much about commands used in C, so please bear with me...I cant use very complicated codes. I have some knowledge in the stdio.h and ctype.h library, but thats about it. I have a matrix in a txt file and I want to load the matrix based on my input of number of rows and columns

For example, I have a 5 by 5 matrix in the file. I want to extract a specific 2 by 2 submatrix, how can I do that ?

I created a nested loop using :

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

Sadly the code does not work .. If I have this matrix :

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

And inputting 3 for row and 3 for column, I get :

5.00 4.00 5.00
6.00 5.00 4.00
3.00 25.00 5.00

Not only this isnt a 2 by 2 submatrix, but even if I wanted the first 3 rows and first 3 columns, its not printing it correctly....

I need to start at row 3 and col 3, then take the 2 by 2 submatrix !

I should have ended up with :

4.00 23.00 
352.00 6.00

I heard that I can use fgets and sscanf to accomplish this. Here is my trial code :

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

But this doesnt work either :(

What am I doing wrong ?

Please help. Thanks !


Solution

  • OK, so you want to read a submatrix of size n x m, starting at positions x, y in the big matrix of size p x q. You need two things:

    1. (verify that x + n <= p and y + m <= q)
    2. skip to the first element of the matrix you want to read. This requires first skipping the first y - 1 rows
    3. skip x - 1 elements from the next row, then read n elements into your submatrix. Repeat m times.

    Your current implementation starts reading from the very first element of the matrix, then reads elements contiguously into the submatrix. An updated version:

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

    Update: to read the submatrix from an array instead is even simpler, just requires a bit more calculation. The gist is, a matrix of size p x q can be stored in a contiguous array of size p x q such that matrix[i,j] can be read from array[i*(j-1)+j] (approximately - there may be off-by-one errors and I am never sure which is the column and which is the row, but hopefully you get the idea :-)

    So the code would be something like

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