sscanf 在未知大小的矩阵上的用法?

sscanf usage on matrix of unknown size?

所以,我有一个包含 NxM 大小矩阵的文件。例如:

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

'P2'只是一个无用的指标,第一个'3'表示有多少列,第二个'3'表示有多少行,'1'表示矩阵数字中的最大值。该矩阵存储在如下数据结构中:

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

为了将文件中的数字存储到数据变量中,我使用了 fread 函数,如下所示:

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

好的,我将矩阵的数字作为字符串存储在 'unsigned char** data' 变量中。但现在我需要处理这些数字,所以我试图将这个字符串转换为整数矩阵。我试着做这样的事情:

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

好吧,我明白为什么这不起作用以及为什么我的 'matrixAux' 将是一个只有 1 的 CxL 矩阵。但是在不知道矩阵中有多少元素的情况下,我想不出任何方法来使用 sscanf。

所以,我的问题是:有没有更好的方法将 'unsigned char** data' 字符串转换为整数矩阵而不更改 'data' 类型(unsigned char**)?

我想也许我只是使用了错误的方法将文件的矩阵存储到数据变量(fread 函数)中,或者搞乱了指向指针的指针语法。但我也没有看到任何其他好的选择来做到这一点。

问题 1:计算 data

的大小

如果矩阵存储为文本文件,就像您发布的那样,使用

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

想出 data 的大小是不正确的。

你只需要读取行数和列数,然后,你可以使用numRows * numCols得出data的大小。

问题 2:为 data

分配内存

使用

newMatrix->data = malloc(size);

data分配内存,好像是对内存分配的理解不够

data 的类型是 char**

malloc(size) 为大小为 size 的字符数组分配内存。将 malloc(size) 的 return 值分配给 newMatrix->data 是错误的。

您需要的是:

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

读取数据

现在您可以使用以下方法从文件中读取数据:

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

要将数字直接扫描到 unsigned char,请使用 "hhu""hh" 自 C99 起可用)

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

作为文本文件 fseek(matrixfile, 2, SEEK_SET); 是 UB。只能寻找开始、开头或前一个 tell() 偏移量。相反,寻求开始和 fscanf(matrixfile, "P2 %i %i %i", &newMatrix->c, &newMatrix->l, &newMatrix->max);。始终检查 fscanf() 结果。