Четене ред по ред и оценяване на низове в координати с помощта на 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" улавя броя на сканираните до момента знаци, така че можете да го използвате, за да придвижите указателя към последната сканирана позиция в изходния низ.

И "%*[^(" ще пропусне всички знаци, докато бъде намерен следващият '('.

Моля, вижте sscanf(3) за повече информация относно спецификатора "%n" и спецификаторът %[.

person Iharob Al Asimi    schedule 24.09.2015
comment
Благодаря, но използвам char temp3[255], така че мисля, че това е причината вашето решение все още да не работи за мен. - person gkhnavarro; 24.09.2015
comment
@bhounter Можете лесно да направите указател към масив, това е естествено нещо в езика c, si моя редакция, моля. - person Iharob Al Asimi; 24.09.2015
comment
Програмата все още влиза в безкраен цикъл. Предполагам, че не работи добре с fgets(). - person gkhnavarro; 24.09.2015
comment
Обърнете внимание, че имам неизвестен брой линии и върхове, така че предложението по-горе, с всички низове в temp3, не е моят случай. - person gkhnavarro; 24.09.2015
comment
@bhounter Така че трябва да уточни какво точно е това. - 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