feof обнаруживает ложный конец файла

Ранее я задавал другой вопрос об этом, но я был далеко не в том, что касается проблемы, поэтому я создал новый вопрос, поскольку задаю совершенно другой вопрос.

У меня есть функция, которая читает заданную строку в текстовом файле (заданную переменной ac). Он выполняет чтение строки, а затем проверяет, была ли эта строка последней в файле. Если это так, он увеличивает значение.

Проблема в том, что он увеличивает значение, даже если это не фактический конец файла. Я думаю, что неправильно использую feof, но мне не повезло заставить его работать:

int readIn(TinCan* inCan, int toggle)
  {
  int ii, isFinished = 0;
  char fullName[20];
  sprintf(fullName, "Label_%d.txt", inCan->pid);

  FILE* fp; 
    fp = fopen(fullName, "r");

    if(fp==NULL) 
      {
      printf("Error: could not open %s\n", fullName);
      }

    else
      {
      for (ii=0; ii < ((inCan->ac)-1); ii++)
        {
        fscanf(fp, "%*d %*d %*d\n"); /*move through lines without scanning*/
        }
      fscanf(fp,"%d %d %d", &inCan->ac, &inCan->state, &inCan->time);
      }

    if (feof(fp) && (toggle == 1)) 
      {
      printf("File ended"); 
      writeLog(inCan);
      isFinished = 1;
      terminated++;
      }

  fclose(fp);
  return finished;
  }

Пример данных по запросу, это текстовый файл, который я могу использовать:

1 1 30
2 2 5
3 1 1

fscanf правильно присваивает значения. Во второй строке feof возвращает значение true, а значение terminated увеличивается. feof снова возвращает true для 3-й строки, и приращение прерывается во второй раз.


person Dawson    schedule 19.05.2013    source источник
comment
возвращение завершено, я думаю, завершено   -  person Nick Maroulis    schedule 19.05.2013
comment
Все, что я сказал по другому вопросу, остается в силе. Пожалуйста, предоставьте образец данных файла, что вы получаете на выходе, что вы ожидаете получить на выходе и возвращаемые значения из fscanf   -  person xaxxon    schedule 19.05.2013
comment
О, странно. Да, то, что сказал @marabutt - если это компилируется, то завершение является где-то глобальной переменной, и это совсем не то, что вы думаете, что возвращаете. Или вы опечатались при копировании в stackoverflow   -  person xaxxon    schedule 19.05.2013
comment
В этом случае нет необходимости feof(fp), потому что EOF не является до тех пор, пока вы что-то не прочитаете, а затем даже после прочтения всех данных.   -  person BLUEPIXY    schedule 19.05.2013
comment
готовая переменная была ошибкой копирования/вставки, переменные соответствуют isFinished в моем коде, и она компилируется нормально.   -  person Dawson    schedule 19.05.2013
comment
создайте несколько фиктивных переменных внутри цикла for, чтобы присвоить значения fscanf %d и еще одну для возвращаемого значения fscanf, затем распечатайте их, а также данные из fscanf прямо вне цикла for, и прикрепите этот вывод, пожалуйста . Кроме того, вы вызываете эту функцию более одного раза и ожидаете, что она продолжится с того места, где она была раньше?   -  person xaxxon    schedule 19.05.2013


Ответы (2)


feof() не определяет, закончился ли файл. Он определяет, была ли последняя ошибка чтения вызвана окончанием файла.

feof() происходит только после неудачного чтения.

Итак, сначала прочитайте данные и проверьте возвращаемое значение. Если чтение не удалось, используйте feof(), чтобы убедиться, что это не удалось, потому что был достигнут КОНЕЦ ФАЙЛА (другими причинами сбоя чтения являются какие-либо ошибки (сеть не работает, поврежденный сектор, принтер горит, ...), обнаруживаемые с ferror()).

person pmg    schedule 19.05.2013
comment
Как проверить возвращаемое значение? Сравните это с NULL? - person Dawson; 19.05.2013
comment
@Dawson, распечатав коды возврата fscanf, как я просил вас об этом последние 30 минут :-P - person xaxxon; 19.05.2013
comment
fscanf() возвращает количество выполненных заданий или EOF в случае раннего END-OF-FILE или ошибки. Используйте это возвращаемое значение: if (fscanf(...) != <expected_value>) /* something strange */; - person pmg; 19.05.2013
comment
Я не уверен, как это закодировать. Могу ли я вместо этого использовать if (fscanf(f, "%*d %*d %*d\n")==EOF)? Это доставляет мне те же проблемы. - person Dawson; 19.05.2013
comment
fscanf(f, "%*d %*d %*d\n") ???? Почему вы пытаетесь прочитать 3 значения в никуда? Если вы хотите прочитать (и отбросить) строку, попробуйте fgets(). - person pmg; 19.05.2013
comment
Я до сих пор не понимаю, почему вы вообще хотите проверить EOF. Если вам нужна пятая строка, у вас есть код, который это сделает. - person xaxxon; 19.05.2013
comment
Я хочу знать, является ли последняя строка, которую я прочитал, последней строкой, и файл больше не следует читать. - person Dawson; 19.05.2013
comment
Итак, после чтения я поставил это, но это дает мне сравнение между указателем и целочисленной ошибкой. char str[30]; if (fgets(str, 30, f)==EOF) /*check if end of file*/ - person Dawson; 19.05.2013
comment
fgets() возвращает значение типа char*; EOF — это значение типа int; вы сравниваете значения разных типов, и компилятор справедливо жалуется. Сравните значение, возвращенное из fgets(), с NULL (NULL — это, по сути, значение типа void*, которое совместимо с любым значением типа указателя), а не EOF. - person pmg; 19.05.2013

Трудно сказать, не зная формата данных, но

 fscanf(fp,"%d %d %d", &inCan->ac, &inCan->state, &inCan->time); 

будет читать 3 значения, но в последней строке он не будет читать символ конца строки, поэтому это не конец файла.

Пытаться:

 fscanf(fp,"%d %d %d\n", &inCan->ac, &inCan->state, &inCan->time);
person parkydr    schedule 19.05.2013