简体   繁体   English

读取pgm文件时C sscanf()返回零

[英]C sscanf() returning zeros when reading a pgm file

I am trying to read a pgm file and put it into an array for an assignment and I have it to where I can get each line into a string then I try to sscanf each line to get the values, but it always puts a zero in for num no matter what it really is. 我正在尝试读取一个pgm文件,并将其放入一个数组中进行赋值,然后将其放入可以将每一行放入字符串中的位置,然后尝试扫描每一行以获取值,但是它始终将零放在不管它到底是什么。 It might have something to do with the pgm files have either 1 or 2 spaces between each column, but I'm not sure` 可能与pgm文件有关,每列之间有1或2个空格,但我不确定。

int **image = (int**) malloc(*numCols * sizeof(int*));
int i;
for(i = 0; i < *numCols; i++)
{
    image[i] = (int *) malloc(*numRows * sizeof(int));
}


int r,c;
int num = 0;
char *line = (char *) malloc(*numCols * sizeof(char));
for(r = 0; r < *numRows; r++)
{
    int number = (*numCols * sizeof(int));
    fgets(line, number, in);

    for(c = 0; c < *numCols; c++)
    {
        sscanf(line,"%d",&num);
        printf("%d",num);
        image[r][c] = num;
    }
    sscanf(line,"%*[\n]");
    printf("\n");
}
return image;

The PGM file doesn't start with a number, use a text editor to open the file to find its format. PGM文件不是以数字开头,请使用文本编辑器打开文件以查找其格式。 Another problem is if you use sscanf() like that, you will only read the first number permanently, maybe you need strtok() instead or like this: 另一个问题是,如果您像这样使用sscanf() ,则只会永久读取第一个数字,也许您需要使用strtok()或这样:

int offset = 0, readCount;
for(c = 0; c < *numCols; c++)
{
    sscanf(line + offset,"%d%n",&num, &readCount);
    printf("%d",num);
    image[r][c] = num;
    offset += readCount;
}

Lots of problems here. 这里有很多问题。 There are memory allocation problems as well as logic problems. 存在内存分配问题和逻辑问题。

Firstly, you have a buffer overflow. 首先,您有一个缓冲区溢出。 You malloc *numCols bytes in the second section but then you read in *numCols * sizeof(int) bytes. 您在第二部分中*numCols个字节,但随后读取了*numCols * sizeof(int)字节。 Actually, the length of the line will need to be at least as long as the longest line in your PGM file. 实际上,行的长度至少需要与PGM文件中的最长行一样长。 This has nothing to do with sizeof(int) - a number written in text can take up to 10 characters (or 20 if it's a 64-bit int). 这与sizeof(int)无关-用文本编写的数字最多可以包含10个字符(如果是64位int,则为20个字符)。 And then there's the spaces between the numbers. 然后数字之间有空格。

Secondly, you have your rows and columns around the wrong way, your allocation should be: 其次,行和列的排列方式错误,分配应为:

int **image = malloc( *numRows * sizeof *image );
for (int i = 0; i < *numRows; ++i)
    image[i] = malloc( *numCols * sizeof *image[i] );

(note how my mallocs are not full of warts). (请注意我的malloc如何不充满疣)。

Thirdly, you should check the result of sscanf . 第三,您应该检查sscanf的结果。 Maybe what is happening is that the read is failing (ie there were not any numbers there), so num is retaining its previous value. 也许正在发生的事情是读取失败(即那里没有任何数字),因此num保留了其先前的值。 sscanf will return 1 if and only if it succeeded. 且仅当成功时, sscanf才会返回1

Even if that succeeds, you then go through a loop and call sscanf(line,"%d",&num) over and over. 即使成功,您sscanf(line,"%d",&num)遍历循环并反复调用sscanf(line,"%d",&num) This will just read the first item on the line over and over. 这将反复读取该行上的第一项。 If you want to read the second number on the line, you're going to have to start from after the number you just read, instead of starting from the start of the line each time. 如果要读取行中的第二个数字,则必须从刚读的数字之后开始,而不是每次都从行的开头开始。 Actually this is not simple to do, so I would suggest that you read numbers using strtol instead of sscanf . 其实这并不容易,所以我建议您使用strtol而不是sscanf读取数字。

Finally, sscanf(line,"%*[\\n]"); 最后, sscanf(line,"%*[\\n]"); has no effect whatsoever. 没有任何作用。 It seems that you think line gets consumed each time you call sscanf , but that actually doesn't happen; 似乎您认为每次调用sscanf都会消耗掉该line ,但这实际上并没有发生。 line is not an input stream, it's an array of chars. line不是输入流,它是一个字符数组。

I guess you might want to "move onto the next line" in the input file also. 我猜您可能也想在输入文件中“移至下一行”。 You currently don't have any code to do that; 您目前没有任何代码可以执行此操作; you'll need to detect whether your fgets reached the end of the input line or not, and if it didn't, then read up until you do reach the end of the line and discard those characters. 您需要检测您的fgets是否到达输入行的末尾,如果没有到达,请继续阅读直到到达行尾并丢弃这些字符。

NB. NB。 I'm assuming you also have some code before the code you actually showed, that reads the header of the PGM file, before it gets up to reading the image data. 我假设您在实际显示的代码之前也有一些代码,该代码在读取图像数据之前先读取PGM文件的标题。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM