Linux программирование в примерах | страница 65



', против которой мы предостерегали ранее.

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

>97   if (ferror(ebuf->fp))

>98    pfatal_with_name(ebuf->floc.filenm);

>99

>100  /* Если обнаружено несколько строк, возвратить их число.

>101     Если не несколько, но _что-то_ нашли, значит, прочитана

>102     последняя строка файла без завершающего символа конца

>103     строки; вернуть 1. Если ничего не прочитано, это EOF;

>104     возвратить -1. */

>105  return nlines ? nlines : p == ebuf->bufstart ? -1 : 1;

>106 }

В заключение, функция >readline() проверяет ошибки ввода/вывода, а затем возвращает описательное значение. Функция >pfatal_with_name() (строка 98) не возвращается.[44]

3.2.1.9. Только GLIBC: чтение целых строк: >getline() и >getdelim()

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

>#define _GNU_SOURCE 1 /* GLIBC */

>#include

>#include /* для ssize_t */


>ssize_t getline(char **lineptr, size_t *n, FILE *stream);

>ssize_t getdelim(char **lineptr, size_t *n, int delim, FILE *stream);

Определение константы >_GNU_SOURCE вводит объявления функций >getline() и >getdelim(). В противном случае они неявно объявлены как возвращающие >int. Для объявления возвращаемого типа >ssize_t нужен файл >. (>ssize_t является «знаковым >size_t». Он предназначен для такого же использования, что и >size_t, но в местах, где может понадобиться использование также и отрицательных значений.)

Обе функции управляют для вас динамической памятью, гарантируя, что буфер, содержащий входную строку, достаточно большой для размещения всей строки. Их отличие друг от друга в том, что >getline() читает до символа конца строки, a >getdelim() использует в качестве разделителя символ, предоставленный пользователем. Общие аргументы следующие:

>char **lineptr

Указатель на >char* указатель для адреса динамически выделенного буфера. Чтобы >getline() сделала всю работу, он должен быть инициализирован >NULL. В противном случае, он должен указывать на область памяти, выделенную с помощью >malloc().

>size_t *n

Указатель на размер буфера. Если вы выделяете свой собственный буфер, >*n должно содержать размер буфера. Обе функции обновляют