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

时间:2015-10-05 21:35:31

标签: c arrays string matrix scanf

所以,我有一个包含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 **数据'变量。但现在我需要处理这些数字,所以我试图将这个字符串转换为整数矩阵。我试着做这样的事情:

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

好吧,我理解为什么这不起作用以及为什么我的&#C3; matrixAux&#39;将是一个只有1&s的CxL矩阵。但是我不知道在不知道矩阵中有多少元素的情况下使用sscanf的任何方法。

所以,我的问题是:是否有更好的方法来转换未签名的char **数据&#39;字符串成整数矩阵而不改变数据&#39; type(unsigned char **)?

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

2 个答案:

答案 0 :(得分:2)

问题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)的返回值分配给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);
      }
   }
}

答案 1 :(得分:0)

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

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()结果。