Почему функция fgets устарела?

Из Учебник по программированию GNU C:

Функция fgets ( "get get string" ) аналогична функции get функция. Эта функция устарела - это означает, что она устарела и настоятельно рекомендуется, чтобы вы его не использовали, потому что это опасно. Это опасно, потому что если входные данные содержат нулевой характер, вы не можете сказать. Не используйте fgets, если вы не знаете данные не может содержать нуль. Не используйте его для чтения файлов, отредактированных пользователем. потому что, если пользователь вставляет нулевой символ, вы должны либо правильно обработайте его или распечатайте сообщение об ошибке. Всегда используйте getline или getdelim вместо fgets, если вы можете.

Я думал, что функция fgets останавливается, когда она встречает \0 или \n; почему эта страница руководства предлагает нулевой байт, является "опасным", когда fgets должен правильно обрабатывать вход? Кроме того, в чем разница между getline и fgets и является ли функция fgets действительно считающейся устаревшей в C99 или будущих стандартах C?

Ответ 1

Нет, fgets на самом деле не устарел в C99 или в текущем стандарте C11. Но автор этого руководства прав, что fgets не остановится, когда он встретит NUL, и не имеет механизма для сообщения о его чтении такого символа.

Функция fgets читает не более, чем число символов, указанных в nиз потока, на который указывает stream, в массив, на который указывает s. Никакие дополнительные символы не читаются после символа новой строки (который сохраняется) или после окончания файла.

(§7.21.7.2)

GNU getdelim и getline были стандартизованы в POSIX 2008, поэтому, если вы настроите таргетинг на платформу POSIX, не будет плохой идеей использовать их вместо этого.

EDIT Я думал, что нет абсолютно безопасного способа использовать fgets перед символами NUL, но R.. (см. комментарии) указал, что есть:

char buf[256];

memset(buf, '\n', sizeof(buf));  // fgets will never write a newline
fgets(buf, sizeof(buf), fp);

Теперь найдите последний символ не \n в buf. На самом деле я бы не рекомендовал этот kludge.

Ответ 2

Это просто пропаганда GNU. В официальном смысле fgets не рекомендуется. gets однако опасен и устарел.