2009-11-02 29 views
11

Fgets() luôn luôn chấm dứt bộ đệm char với \ 0 ngay cả khi EOF đã đạt được? Nó trông giống như nó (nó chắc chắn không trong việc thực hiện trình bày trong ANSI K & R cuốn sách), nhưng tôi nghĩ rằng tôi sẽ yêu cầu để chắc chắn.Fgets() luôn luôn chấm dứt bộ đệm char với 0?

Tôi đoán câu hỏi này áp dụng cho các chức năng tương tự khác như get().

EDIT: Tôi biết rằng \ 0 được nối thêm trong các trường hợp "bình thường", câu hỏi của tôi được nhắm mục tiêu theo EOF hoặc các điều kiện lỗi. Ví dụ:

FILE *fp; 
char b[128]; 
/* ... */ 
if (feof(fp)) { 
    /* is \0 appended after EACH of these calls? */ 
    fgets(b, 128, fp); 
    fgets(b, 128, fp); 
    fgets(b, 128, fp); 
} 
+1

Luôn kiểm tra giá trị trả về của 'fgets()': 'if (fgets (...) == NULL)/* không xác định mảng * /;' – pmg

+0

Bạn có thể đúng, tuy nhiên, Tôi thấy có những câu trả lời khác cho biết '\ 0' luôn được nối thêm, ngay cả khi' fgets() 'trả về' NULL'. – Ree

Trả lời

6

Không bao giờ sử dụng được !!

 
    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. 

Vì vậy, , khi fgets() không trả lại NULL mảng điểm đến luôn luôn có một ký tự null.

Nếu fgets() trả về NULL, mảng đích có thể đã bị thay đổi và có thể không có ký tự rỗng. Không bao giờ dựa vào mảng sau khi nhận được NULL từ fgets().


Sửa dụ thêm

 
$ 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] 
$ 

Thấy không?no NUL in buf :)

+0

Bạn giành chiến thắng: D .... – Ree

+0

@pmg lại "Không bao giờ sử dụng được !!", bạn có thay thế cho việc đọc tệp không? – atlex2

+1

@ atlex2: có, thay thế là 'fgets()'. – pmg

0

Có. Từ CPlusPlus.com

Đọc ký tự từ suối và lưu trữ chúng như là một chuỗi C vào str cho đến khi ký tự (num-1) đã được đọc hoặc một trong hai một dòng mới hoặc một File End-of-đạt được, nào đến trước.

Một ký tự dòng mới làm cho fgets ngừng đọc, nhưng nó được coi là một ký tự hợp lệ và do đó nó được bao gồm trong chuỗi được sao chép vào str.

Ký tự rỗng được tự động nối vào sau khi ký tự được đọc để báo hiệu kết thúc chuỗi C.

7

fgets không luôn thêm một '\ 0' để bộ đệm đọc, nó đọc nhiều nhất size - 1 ký tự từ luồng (size là tham số thứ hai) vì điều này.

Không bao giờ sử dụng gets vì bạn không bao giờ có thể đảm bảo rằng nó sẽ không tràn bộ đệm mà bạn cung cấp, vì vậy trong khi về mặt kỹ thuật, luôn luôn chấm dứt chuỗi đọc này không thực sự hữu ích.

2

người fgets:

fgets() đọc trong ít nhất một ít hơn nhân vật có kích thước từ suối và lưu trữ chúng vào bộ đệm được trỏ đến bởi s. Đọc dừng sau một EOF hoặc một dòng mới. Nếu một dòng mới được đọc, nó được lưu vào bộ đệm. A '\ 0' được lưu sau ký tự cuối cùng trong bộ đệm.

0

Nếu bạn mở tệp ở chế độ nhị phân "rb" và nếu bạn muốn đọc dòng văn bản bằng cách sử dụng fgets, bạn có thể sử dụng mã sau để bảo vệ phần mềm mất văn bản, nếu do nhầm lẫn, văn bản chứa byte '\ 0'. Nhưng cuối cùng cũng giống như những người khác được đề cập, thông thường bạn không nên sử dụng fgets nếu luồng có chứa '\ 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'; 
    } 
} 
Các vấn đề liên quan