Чтение строки за строкой и преобразование строк в координаты с помощью fgets() и sscanf()

Я пытаюсь прочитать несколько строк вершин разной длины, используя fgets и sscanf.

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

Моя программа входит в бесконечный цикл, застрявший в первой вершине.

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

Я должен иметь возможность передавать значения x и y вершин в массивы полигонов, поэтому я застрял с использованием sscanf. У меня также возникла проблема, так как я не могу найти в Интернете ничего, что сканировало бы различное количество элементов в строке.


person gkhnavarro    schedule 24.09.2015    source источник
comment
sscanf снова и снова читает одно и то же, вызывая бесконечный цикл. Он не продвигается, как вы думаете.   -  person Spikatrix    schedule 24.09.2015
comment
Исправлен sscanf ранее, вместе с предложениями @iharob. Моя основная проблема заключалась в том, что мой указатель не обновлялся после итерации fgets(). Спасибо, в любом случае. :)   -  person gkhnavarro    schedule 24.09.2015


Ответы (2)


Это потому что это

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

никогда не будет true Я думаю, поскольку scanf() возвращает количество успешно отсканированных параметров, я бы сделал это вместо этого

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

Ваш код не работает, потому что он не удовлетворяет условию sscanf() для возврата EOF, следующее взято со страницы руководства, на которую ссылается в конце

Значение EOF возвращается, если конец ввода достигнут до первого успешного преобразования или ошибки сопоставления. EOF также возвращается, если возникает ошибка чтения, и в этом случае устанавливается индикатор ошибки для потока (см. ferror(3)), а errno устанавливается для индикации ошибки.

Таким образом, кажется, что вы не достигаете конца, если вводите до первого успешного преобразования или ошибки сопоставления, что имеет смысл в соответствии с содержимым файла. И вторая часть относится только к файловым потокам, конечно.

И вместо sscanf(temp3, ","), который не делает то, что вы думаете, вы могли бы сделать это так

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

Это предложение о том, как разобрать этот файл

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

Спецификатор "%n" фиксирует количество просканированных на данный момент символов, поэтому его можно использовать для перемещения указателя на позицию las, просканированную в исходной строке.

И "%*[^(" будет пропускать все символы, пока не будет найден следующий '('.

Пожалуйста, обратитесь к sscanf(3) для получения дополнительной информации о спецификаторе "%n" и спецификатор %[.

person Iharob Al Asimi    schedule 24.09.2015
comment
Спасибо, но я использую char temp3[255], поэтому я думаю, что ваше решение все еще не работает для меня. - person gkhnavarro; 24.09.2015
comment
@bhunter Вы можете легко сделать указатель на массив, это естественная вещь в языке c, пожалуйста, отредактируйте. - person Iharob Al Asimi; 24.09.2015
comment
Программа все еще входит в бесконечный цикл. Я предполагаю, что это плохо работает с fgets(). - person gkhnavarro; 24.09.2015
comment
Обратите внимание, что у меня есть неизвестное количество линий и вершин, поэтому приведенное выше предложение со всеми строками в temp3 не подходит для меня. - person gkhnavarro; 24.09.2015
comment
@bhunter Итак, следует указать, что именно это такое. - person ameyCU; 24.09.2015

В случае успешного чтения sscanf в этом случае будет возвращено 2 . sscanf возвращает количество заполненных переменных.

Проверьте, возвращает ли он 2, что укажет здесь на успех.

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

Вместо этого проверьте вот так -

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

также, чтобы игнорировать ',' после координат, вы используете -

sscanf(temp3, ",");

не является правильным . В приведенном выше sscanf вы можете прочитать его и отбросить, используя спецификатор %*c.

person ameyCU    schedule 24.09.2015
comment
"%*c" подходит, если после конца кортежа есть только один , или любой другой символ, "%*[^(]" будет более надежным. - person Iharob Al Asimi; 24.09.2015
comment
Я не думаю, что %*c делает здесь что-то полезное. sscanf вел бы себя так же, если бы его там не было. - person Spikatrix; 24.09.2015
comment
@iharob Я думаю, формат кода исправлен. И ( будет соответствовать в следующей итерации. Так что нам не о чем беспокоиться. - person ameyCU; 24.09.2015
comment
@CoolGuy Нет, ты был прав. Я действительно сделал что-то глупое. Действительно промахнулся. :| - person ameyCU; 24.09.2015
comment
Решение в вашем ответе не сработает. sscanf не продвигается в чтении. Как только sscanf в вашем ответе вернет 2, вы получите бесконечный цикл. - person Spikatrix; 24.09.2015