|
feof กับ ferror
function ที่ใช้อ่าน file ใน standard library ของภาษา C มีอยู่ด้วยกันหลาย function แต่ function เหล่านี้จะไม่สามารถแยกความแตกต่างระหว่าง end-of-file กับการเกิด error ได้ ตัวอย่างของ function เหล่านี้คือ
int fgetc (FILE *stream); int getc (FILE *stream); int getchar (void); จะ return EOF เมื่อเจอ end-of-file หรือเมื่อเกิด error
char *fgets (char *s, int n, FILE *stream); char *gets (char *s); จะ return NULL เมื่อเจอ end-of-file หรือเมื่อเกิด error
int fscanf (FILE *stream, char *format, ... ); int scanf (char *format, ... ); จะ return EOF เมื่อเจอ end-of-file หรือเมื่อเกิด error
size_t fread (void *ptr, size_t size, size_t nitems, FILE *stream); จะ return ค่าไม่เท่ากับ nitems เมื่อเจอ end-of-file หรือเมื่อเกิด error
การที่จะแยกให้ได้ว่าเกิด end-of-file หรือเกิด error ต้องใช้ feof กับ ferror ครับ int feof (FILE *stream); int ferror (FILE *stream);
เมื่อเกิด error ในการอ่าน FILE *stream การเรียกใช้ ferror (stream) จะ return ค่าเป็น non-zero ทำนองเดียวกัน เมื่ออ่าน FILE *stream จนเจอ end-of-file การเรียกใช้ feof (FILE *stream) จะ return ค่าเป็น non-zero function ทั้งสองจะมีลักษณะเหมือนกันคือ ต้องเกิด เหตุ ขึ้นเสียก่อน แล้วถึงจะทดสอบเจอ หาก เหตุไม่เกิด ก็ทดสอบไม่เจอ
สำหรับ ferror คงไม่ค่อยมีปัญหา (อาจเป็นเพราะไม่ค่อยเห็นใช้กัน) แต่ feof นี่ผมเห็นใช้ผิดกันบ่อยๆ เพราะว่ามันต้องอ่านจนเจอ end-of-file ถึงจะใช้ feof ทดสอบได้ แต่ที่เห็นใช้กันผิด คือไปทดสอบ feof ก่อน แล้วค่อยไปอ่าน stream เช่น
while (!feof(fp)) { c = getc(fp); putchar(c); }
เพราะว่าถึงอ่าน byte สุดท้ายของ file ไปแล้ว คืออยู่ที่ท้าย file ไม่มีข้อมูลแล้ว แต่ว่าตัว library function มันยังไม่รู้นะครับว่าไม่มีข้อมูลแล้ว เราต้องสั่งให้อ่านต่อไป มันถึงจะรู้ว่าไม่มีข้อมูลแล้ว เจอ end-of-file แล้ว feof ถึงจะทดสอบเจอ
มาทดสอบกันโดยสร้าง file ที่มีหนึ่งตัวอักษร แล้วลองอ่าน file โดยใช้โปรแกรมที่ผิดแบบข้างบน เปรียบเทียบกับโปรแกรมที่เขียนถูก
#include <stdio.h> #define TEST_FILE "test.dat"
int main () { int c; FILE *fp;
puts("Create file contains one character"); fp = fopen(TEST_FILE, "w"); if (fp == NULL) { perror("fopen w"); return -1; } putc('A',fp); fclose(fp);
puts("Bad feof program"); fp = fopen(TEST_FILE, "r"); if (fp == NULL) { perror("fopen r"); return -1; } while (!feof(fp)) { c = getc(fp); printf("%c(%d)\n", c, c); } fclose(fp);
puts("Good program"); fp = fopen(TEST_FILE, "r"); if (fp == NULL) { perror("fopen r"); return -1; } while ((c = getc(fp)) != EOF) printf("%c(%d)\n", c, c); fclose(fp);
puts("End"); getchar(); return 0; }
ผลลัพธ์ที่ได้คือ Create file contains one character Bad feof program A(65) (-1) Good program A(65) End
จะเห็นว่า feof จะทดสอบไม่เจอ end-of-file มันเลยอ่านเกินไปตัวนึง
แล้วควรใช้งาน feof ยังไง คำตอบคือ ให้ใช้เท่าที่จำเป็น
จะเห็นว่าในโปรแกรมทดสอบอันที่ถูกของผม ไม่ใช้ feof ด้วยซ้ำ เพราะมันไม่จำเป็นต้องใช้ ที่ผิดกันบ่อยคือใช้ feof เป็น loop condition ทั้งที่จริงๆเราก็ loop อ่านจนมันอ่านไม่ได้แหละครับ ไม่ว่าจะอ่านไม่ได้เพราะ end-of-file หรือ error ไม่เห็นต้องใช้ feof เลย หลังออกจาก loop แล้วถ้าอยากรู้ว่า error หรือเปล่าค่อยไปใช้ ferror เช่น
while ((c = getc(fp)) != EOF) printf("%c(%d)\n", c, c); if (ferror(fp)) perror("getc");
สรุปว่าใช้แบบพอเพียงครับ
Create Date : 12 กันยายน 2552 |
Last Update : 12 กันยายน 2552 21:27:08 น. |
|
5 comments
|
Counter : 3522 Pageviews. |
|
|
|
โดย: motokop วันที่: 10 ตุลาคม 2552 เวลา:22:38:44 น. |
|
|
|
โดย: motokop วันที่: 16 ตุลาคม 2552 เวลา:20:30:29 น. |
|
|
|
โดย: motokop วันที่: 31 ธันวาคม 2552 เวลา:14:37:12 น. |
|
|
|
โดย: motokop วันที่: 13 เมษายน 2553 เวลา:23:16:48 น. |
|
|
|
โดย: prikthai IP: 202.12.74.1 วันที่: 14 มกราคม 2554 เวลา:18:19:14 น. |
|
|
|
| |
|
|