Всегда ли fgets() завершает буфер char с помощью ?
Всегда ли fgets() завершает буфер char с , даже если EOF уже достигнут? Похоже, что это так (это, безусловно, так в реализации, представленной в книге ANSI K&R), но я подумал, что хотел бы спросить, чтобы быть уверенным.
Я думаю, что этот вопрос относится и к другим подобным функциям, таким как Get().
EDIT: я знаю, что добавляется во время "нормальных" обстоятельств, мой вопрос нацелен на EOF или условия ошибки. Например:
FILE *fp;
char b[128];
/* ... */
if (feof(fp)) {
/* is appended after EACH of these calls? */
fgets(b, 128, fp);
fgets(b, 128, fp);
fgets(b, 128, fp);
}
5 ответов:
Никогда не используйте gets!!
7.19.7.2 The fgets function Synopsis 1 #include <stdio.h> char *fgets(char * restrict s, int n, FILE * restrict stream); Description 2 The fgets function reads at most one less than the number of characters specified by n from the stream pointed to by stream into the array pointed to by s. No additional characters are read after a new-line character (which is retained) or after end-of-file. A null character is written immediately after the last character read into the array. Returns 3 The fgets function returns s if successful. If end-of-file is encountered and no characters have been read into the array, the contents of the array remain unchanged and a null pointer is returned. If a read error occurs during the operation, the array contents are indeterminate and a null pointer is returned.Итак, Да, Когда
fgets()
не возвращает NULL, конечный массив всегда имеет нулевой символ.Если
fgets()
возвращает NULL, то конечный массив может быть изменен и не иметь нулевого символа. Никогда не полагайтесь на массив после получения NULL изfgets()
.
Edit пример добавлен
$ cat fgets_error.c #include <stdio.h> void print_buf(char *buf, size_t len) { int k; printf("%02X", buf[0]); for (k=1; k<len; k++) printf(" %02X", buf[k]); } int main(void) { char buf[3] = {1, 1, 1}; char *r; printf("Enter CTRL+D: "); fflush(stdout); r = fgets(buf, sizeof buf, stdin); printf("\nfgets returned %p, buf has [", (void*)r); print_buf(buf, sizeof buf); printf("]\n"); return 0; } $ ./a.out Enter CTRL+D: fgets returned (nil), buf has [01 01 01] $Видите? no NUL in buf:)
fgets
всегда добавляет' \0 ' в буфер чтения, он читает не болееsize - 1
символов из потока (size
является вторым параметром) из-за этого.Никогда не используйте
gets
, поскольку вы никогда не можете гарантировать, что он не переполнит буфер, который вы ему даете, поэтому, хотя технически он всегда завершает строку чтения, это на самом деле не помогает.
Man fgets:
Fgets () считывает из потока не более одного символа меньше размера и сохраняет их в буфер, на который указывает s. чтение останавливается после EOF или новой строки. Если новая строка считывается, она сохраняется в буфере. a '\0 ' сохраняется после последнего символа в буфере.
Да, это так. От CPlusPlus.com
Считывает символы из потока и сохраняет их в виде строки C в str до тех пор, пока не будут прочитаны символы (num-1) или не будет достигнута новая строка или конец файла, в зависимости от того, что наступит раньше.
Символ новой строки останавливает чтение fgets, но он считается допустимым символом и поэтому включается в строку, скопированную в str.
Нулевой символ автоматически добавляется в str после символов считывание означает конец строки C.
Если вы открыли файл в двоичном режиме "rb", и если вы хотите читать текст строка за строкой с помощью fgets, вы можете использовать следующий код для защиты вашего программного обеспечения от потери текста, если по ошибке текст содержал байт '\0'. Но, наконец, как и другие упомянутые, обычно вы не должны использовать
fgets
, если поток содержит '\0'.
size_t filepos=ftell(stream); fgets(buffer, buffersize, stream); len=strlen(buffer); /* now check for > len+1 since no problem if the last byte is 0 */ if(ftell(stream)-filepos > len+1) { if(!len) filepos++; if(!fseek(stream, filepos, SEEK_SET) && len) { fread(buffer, 1, len, stream); buffer[len]='\0'; } }