Question

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. It might have something to do with the pgm files have either 1 or 2 spaces between each column, but I'm not sure`

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;
Was it helpful?

Solution

The PGM file doesn't start with a number, use a text editor to open the file to find its format. 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:

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

OTHER TIPS

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. Actually, the length of the line will need to be at least as long as the longest line in your PGM file. 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). 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).

Thirdly, you should check the result of sscanf. Maybe what is happening is that the read is failing (i.e. there were not any numbers there), so num is retaining its previous value. sscanf will return 1 if and only if it succeeded.

Even if that succeeds, you then go through a loop and call sscanf(line,"%d",&num) over and over. 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.

Finally, 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; line is not an input stream, it's an array of chars.

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.

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.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top