Вопрос о функции произвольного доступа в C - PullRequest
2 голосов
/ 11 октября 2010

Я пытаюсь изучить C, и в книге, которую я использую (Apress '' Learn C '), есть глава, которая ужасно запутывает функции произвольного доступа.Следующий код вводит меня в заблуждение:

 int    GetNumberOfDinos( void ) {
    FILE    *fp;
    long    fileLength;

    if ( (fp = fopen( kDinoFileName, "r" )) == NULL )
        DoError( "Couldn't open file...Goodbye!" );

    if ( fseek( fp, 0L, SEEK_END ) != 0 )
        DoError( "Couldn't seek to end of file...Goodbye!" );

    if ( (fileLength = ftell( fp )) == -1L )
        DoError( "ftell() failed...Goodbye!" );

    fclose( fp );

    return( (int)(fileLength / kDinoRecordSize) );
}

Я понимаю цель кода, но не понимаю, как эта цель достигается.Линия Fopen легко понять.Это случай, когда начинаются мои неприятности.Параметры для fseek - это файл, смещение, а затем один из 3 SEEK.Почему условие того, что оно не равно нулю, дано там?Если файл действительно существует (kDinoFileName), и они хотят указать на конец этого файла, почему местоположение будет нулевым?Файл существует и есть информация!И тогда я совершенно не понимаю, как функция ftell могла бы когда-либо заканчиваться -1L ??Этот код сложнее, чем должен быть?

Ответы [ 6 ]

5 голосов
/ 11 октября 2010

Код просто проверяет наличие ошибок. fseek() возвращает 0 в случае успеха и ненулевое значение в случае ошибки. ftell() возвращает -1 при ошибке.

Насколько "почему это место будет нулевым?" - вызов fseek() запрашивает поиск с конца файла (SEEK_END). Нулевые байты от конца файла - это ... конец файла. Так

fseek( fp, 0L, SEEK_END )

- это запрос на перемещение указателя файла в конец файла.

Код выполняет следующие шаги:

  1. открыть файл
  2. стремиться к концу
  3. получить позицию указателя файла (который, поскольку мы в конце сообщаем вам, сколько байтов в файле - обратите внимание, строго говоря, файл должен быть открыт с двоичным доступом, например, с помощью «rb») , чтобы это было правдой)

Код несколько усложняется обработкой ошибок. Многие книги и статьи исключают обработку ошибок именно по этой причине. Однако у этого есть свой недостаток - учить людей игнорировать ошибки.

2 голосов
/ 11 октября 2010

-1 может произойти, если есть какая-то неизвестная ошибка, например, ошибка ввода-вывода при попытке прочитать файл. Вы обнаружите, что C использует это специальное значение -1, так как оно не имеет истинного механизма исключений, как это делают более современные языки, так что это просто способ сказать: «Эй, здесь случилось что-то плохое». 1002 *

См. здесь для получения дополнительной информации о ftell.

"Если возникает ошибка, возвращается -1L, а глобальной переменной errno присваивается положительное значение. Это значение может интерпретироваться perror."

1 голос
/ 11 октября 2010

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

0 голосов
/ 12 октября 2010

Возвращаемые значения для стандартных функций C иногда могут быть странными, поскольку многие функции возвращают значение типа int, которое не может использовать одно и то же возвращаемое значение типа int для указания ошибки.

В случае ftell возвращает текущее смещение указателя вашего файла. Если указатель файла находится в начале файла, то он имеет смещение 0. Следовательно, 0 является допустимым смещением и не может использоваться для указания ошибки. Поэтому они используют -1 вместо.

fseek - это инструкция. Это может вернуть пустоту, но они решают вернуть что-то более значимое. Используя 0 для успеха и ненулевое значение для сбоя, они могут возвращать разные ненулевые значения для указания разных ошибок.

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

0 голосов
/ 11 октября 2010

fseek возвращает только указание успеха или неудачи, но не возвращает позицию, в которой оказался указатель файла.Он возвращает 0 в случае успеха, который является стандартным возвращением успеха для многих библиотечных функций.

В случае ftell он вернет текущую позицию файла в указателе файла, если он не имеетошибка, поэтому простое возвращение 0 в случае успеха и ненулевое значение в случае неудачи не работает.Таким образом, функция ftell возвращает -1 в случае сбоя.Это стандартный возврат ошибок для функций, которые возвращают число, имеющее значение.

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

0 голосов
/ 11 октября 2010

Google - ваш друг:

http://www.cplusplus.com/reference/clibrary/cstdio/fseek/

http://www.cplusplus.com/reference/clibrary/cstdio/ftell/

Функции ввода-вывода имеют хороший потенциал ошибок, поэтому рекомендуется проверять возвратзначения.

Да, также есть синтаксис POSIX, который требует, чтобы fseek() возвращала новую позицию вместо кода ошибки.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...