sscanf usage on matrix of unknown size?

此生再无相见时 提交于 2021-02-19 05:26:16

问题


So, I have a file that contains a matrix of NxM size. For example:

P2
3 3 1
1 0 0
0 1 0
0 0 1

The 'P2' is just an useless indicator, the first '3' indicates how many columns are and the second '3' indicates how many lines, '1' indicates the maximum value among the matrix's numbers. This matrix was stored in a data structure like this:

typedef struct {
    int c; // columns
    int l; // lines
    unsigned char max; // max value
    unsigned char** data // variable to store matrix's numbers
} Matrix;

To store the numbers from file to the data variable, I used the fread function, like this:

Matrix* newMatrix = NULL;
newMatrix = malloc(sizeof(Matrix));

FILE* fp = NULL;
fp = fopen(matrixfile, "r");

long size;
fseek(matrixfile, 0, SEEK_END);
size = ftell(matrixfile);
newMatrix->data = malloc(size);

// Jump the 'P2' bytes.
fseek(matrixfile, 2, SEEK_SET);

// Get the c, l and max values.
fscanf(matrixfile, "%i %i %i", &newMatrix->c, &newMatrix->l, &newMatrix->max);

// Jump a '\n' character.
fseek(matrixfile, 1, SEEK_CUR);

// Get matrix's numbers.
fread(newMatrix->data, 1, size, matrixfile);

Ok, I have the matrix's numbers stored as a string in the 'unsigned char** data' variable. But now I need to work with those numbers, so I'm trying to transform this string into a matrix of integers. I tried to do something like this:

void StringtoInt (Matrix* str){

int matrixAux[str->l][str->c], i, j;
for(i=0; i<str->l; i++)
    for(j=0; j<str->c; j++)
        sscanf(str->data, "%i ", &matrixAux[i][j]);
}

Well, I understand why this doesn't work and why my 'matrixAux' will be a CxL matrix with only 1's. But I cannot think of any way to work with sscanf without knowing how many elements are in the matrix.

So, my question: is there a better way to transform the 'unsigned char** data' string into a integer matrix WITHOUT changing the 'data' type (unsigned char**)?

I think maybe I'm just using the wrong method to store the file's matrix into the data variable (fread function), or messing up with the pointer to pointer syntax. But I also don't see any other good alternative to do that.


回答1:


Problem 1: Computing the size of data

If the matrix is stored as a text file, just like you have posted, using

fseek(matrixfile, 0, SEEK_END);
size = ftell(matrixfile);

to come up with the size of data is not correct.

All you have to do is read the number of rows and the number of columns and then, you can use numRows * numCols to come up with the size of data.

Problem 2: Allocating memory for data

Use of

newMatrix->data = malloc(size);

to allocate memory for data seems to indicate a lack of understanding of how memory is allocated.

Type of data is char**.

malloc(size) allocates memory for an array of characters of size size. Assigning the return value of malloc(size) to newMatrix->data is wrong.

What you need is:

newMatrix->data = malloc(numRows*sizeof(char*)); // Assuming you read numRows first.
for ( int i = 0; < numRows; ++i )
{
   newMatrix->data[i] = malloc(numCols);
}

Reading the data

Now you can read the data from the file using:

for ( int i = 0; < numRows; ++i )
{
   for ( int j = 0; j < numCols; ++j )
   {
      int number;
      if ( fscanf(matrixfile, "%d", &number) == 1 )
      {
         // Check that number is within range.
         // ...

         newMatrix->data[i][j] = number;
      }
      else
      {
         // Unable to read the number.
         // Deal with the error.
         exit(1);
      }
   }
}



回答2:


To scan a number directly into a unsigned char, use "hhu" ("hh" available since C99)

sscanf(str->data, "%hhu", &matrixAux[i][j]);

As a text file fseek(matrixfile, 2, SEEK_SET); is UB. Can only seek to the start, beginning or to a previous tell() offset. Instead, seek to beginning and fscanf(matrixfile, "P2 %i %i %i", &newMatrix->c, &newMatrix->l, &newMatrix->max);. Always check fscanf() results.



来源:https://stackoverflow.com/questions/32958291/sscanf-usage-on-matrix-of-unknown-size

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!