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()
结果。
所以,我有一个包含 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()
结果。