简体   繁体   中英

Reading line per line, and evaluating strings into coordinates using fgets() and sscanf()

I'm trying to read multiple lines of vertices with varying length using fgets and sscanf.

(1,6),(2,6),(2,9),(1,9)
(1,5)

My program goes into an infinite loop stuck within the first vertex.

    char temp3[255];
    while(fgets(temp3, 255, fp)!= NULL){
        printf("Polygon %d: ", polycount);
        while(sscanf(temp3, "(%d,%d)", &polygonx[polycount][vertcount], &polygony[polycount][vertcount]) != EOF){
            sscanf(temp3, ",");
            printf("(%d,%d),",polygonx[polycount][vertcount], polygony[polycount][vertcount]);
            vertcount++;
        }
        vertcounts[polycount] = vertcount;
        vertcount = 0;
        polycount++;
    }

I must be able to feed the x and y values of the vertices into the polygon arrays, so i'm stuck with using sscanf. I'm also having a problem since I cant find anything on the internet that scans varying numbers of elements per line.

It's because this

while(sscanf(temp3, "(%d,%d)", 
  &polygonx[polycount][vertcount], &polygony[polycount][vertcount]) != EOF)
 {
 }

is never going to be true I think, because scanf() returns the number of parameters succesfuly scanned, I would do this instead

while(sscanf(temp3, "(%d,%d)", 
  &polygonx[polycount][vertcount], &polygony[polycount][vertcount]) == 2)
 {
 }

Your code doesn't work because it does not satisfy the condition for sscanf() to return EOF , the following is from the manual page referenced at the end

The value EOF is returned if the end of input is reached before either the first successful conversion or a matching failure occurs. EOF is also returned if a read error occurs, in which case the error indicator for the stream (see ferror(3) ) is set, and errno is set to indicate the error.

So it appears that you are not reaching the end if input before the first successful conversion or a matching failure occurs, which makes sense according to the contents of the file. And the second part applies only to file streams of course.

And instead of the sscanf(temp3, ",") which doesn't do what you think, you could do it like this

next = strchr(temp3, ',');
if (next != NULL)
    temp3 = next + 1;
else
    /* you've reached the end here */

This is a suggestion on how to parse this file

#include <stdio.h>
#include <string.h>

int
main(void)
{
    const char temp3[] = "(1,6),(2,6),(2,9),(1,9)\n(1,5)";
    char *source;
    int x, y;
    int count;
    source = temp3;
    while (sscanf(source, "(%d,%d)%*[^(]%n", &x, &y, &count) == 2)
    {
        /* this is just for code clarity */
        polygonx[polycount][vertcount] = x;
        polygony[polycount][vertcount] = y;
        /* Process here if needed, and then advance the pointer */
        source += count;
    }
    return 0;
}

The "%n" specifier captures the number of characters scanned so far, so you can use it to advance the pointer to the las position scanned in the source string.

And the "%*[^(" will skip all characters until the next '(' is found.

Please refer to sscanf(3) for more information on the "%n" specifier, and the %[ specifier.

If successfully read sscanf will return 2 in this case . sscanf returns numbers of variables filled.

Check if it returns 2 which will indicate success here .

while(sscanf(temp3,"(%d,%d)",&polygonx[polycount][vertcount],&polygony[polycount]][vertcount]) != EOF)

Instead of this , check like this -

 while(sscanf(temp3,"(%d,%d)%*c",&polygonx[polycount][vertcount],&polygony[polycount]][vertcount])== 2)
                             ^ to exclude the comma after it             

also to ignore ',' after the coordinates , you use -

sscanf(temp3, ",");

is not correct . In the above sscanf you can read it and discard it as well by using %*c specifier.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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