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

    #include <stdio.h>
    #include <stdlib.h>

    void create() {
        FILE *fin = fopen("in", "r");
        int temp[4], t;
        int aaa;

        while ((aaa = scanf(fin, "%d:%d:%d:%d/%d", 
                      &temp[0], &temp[1], &temp[2], &temp[3], t)) != EOF) {
            printf("%d\n", aaa);
            printf("%d:%d:%d:%d\n", temp[0], temp[1], temp[2], temp[3]);
        }

        fclose(fin);
    }

    int main() {
        create();

        return 0;
    }

И содержимое моего входного файла:

103.29.43.0/24
103.29.5.0/24
103.29.52.0/22
103.29.56.0/22
103.29.60.0/22
103.2.96.0/22
103.29.64.0/24
103.29.65.0/24
103.29.66.0/24
103.29.67.0/24
103.29.7.0/24

Но он выводит:

0
103:0:0:0
0
103:0:0:0
0
103:0:0:0
....(loop)
c
1
wind910037 6 Янв 2016 в 18:53

3 ответа

Лучший ответ

С вашим кодом есть несколько проблем:

  • вы передаете t вместо его адреса &t в качестве последнего спецификатора формата, вызывая неопределенное поведение.

  • Строка формата использует : вместо . в качестве разделителя, что вызывает сбой синтаксического анализа.

  • fscanf возвращает количество успешно проанализированных полей. Только в конце файла и если ни одно поле не может быть проанализировано, возвращается EOF. В противном случае, если во входном потоке есть символ, который не соответствует формату, он останавливается и возвращается между 0 и 5 для вашей строки формата. Например, . во входном потоке приведет к тому, что ваш цикл while будет продолжаться вечно, и fscanf вернет 0, поскольку . не соответствует { {X9}}. Это объясняет текущее поведение, которое вы наблюдаете .

Вы должны изменить тест на:

    while ((aaa = fscanf(fin, "%d.%d.%d.%d/%d",
                     &temp[0], &temp[1], &temp[2], &temp[3], &t)) == 5) {
        printf("%d\n", aaa);
        printf("%d:%d:%d:%d\n", temp[0], temp[1], temp[2], temp[3]);
    }
0
chqrlie 6 Янв 2016 в 16:05
  1. Ваш fscanf должен иметь . вместо : между %d, поскольку это вызывает несоответствие.
  2. Также используйте &t вместо t. См. man fscanf
  3. Также while(fscanf() != EOF) означает, что даже если происходит сбой сопоставления и fscanf не удается сопоставить и сохранить все 5 аргументов (что происходит здесь из-за несоответствия : и .), тогда тоже продолжайте петля.
    Вы должны использовать while(fscanf() == 5) для продолжения цикла только тогда, когда все 5 аргументов fscanf найдены и сохранены.
1
rootkea 6 Янв 2016 в 16:04

Если вы хотите читать из дескриптора FILE *, вам нужно использовать fscanf() вместо scanf().

Например, с fin в качестве FILE * здесь:

while (fscanf(fin, "%d:%d:%d:%d/%d",
              &temp[0], &temp[1], &temp[2], &temp[3], &t) != EOF) { ... }
0
John Hascall 6 Янв 2016 в 16:46