TL; DR : EOF ไม่ใช่ตัวอักษร แต่เป็นมาโครที่ใช้สำหรับประเมินผลตอบแทนเชิงลบของฟังก์ชั่นอ่านอินพุต หนึ่งสามารถใช้Ctrl+ Dเพื่อส่งEOT
ตัวละครซึ่งจะบังคับให้กลับมาทำงาน-1
โปรแกรมเมอร์ทุกคนต้อง RTFM
ให้เราอ้างอิงถึง "คู่มืออ้างอิง CA" โดย Harbison และ Steele, 4th ed จาก 1995 หน้า 317:
จำนวนเต็มลบ EOF คือค่าที่ไม่ใช่การเข้ารหัสของ "อักขระจริง" . . ตัวอย่างเช่น fget (ส่วนที่ 15.6) จะส่งคืน EOFเมื่อสิ้นสุดไฟล์เนื่องจากไม่มี "อักขระตัวจริง" ที่ต้องอ่าน
เป็นหลักEOF
ไม่ได้เป็นตัวอักษร แต่ค่อนข้างค่าจำนวนเต็มดำเนินการในการเป็นตัวแทนของstdio.h
-1
ดังนั้นคำตอบของ kos นั้นถูกต้องที่สุดเท่าที่จะทำได้ แต่ไม่เกี่ยวกับการรับอินพุต "ว่าง" หมายเหตุสำคัญคือที่นี่ EOF ทำหน้าที่เป็นการเปรียบเทียบค่าส่งคืน (จากgetchar()
) ไม่ใช่เพื่อแสดงถึงอักขระจริง man getchar
สนับสนุนว่า
คืนค่า
fgetc (), getc () และ getchar () ส่งคืนอักขระที่อ่านเป็นอักขระแคสต์ที่ไม่ได้ลงชื่อไปยัง int หรือ EOF เมื่อสิ้นสุดไฟล์หรือข้อผิดพลาด
ได้รับ () และ fgets () กลับ s เมื่อประสบความสำเร็จและ NULL จากข้อผิดพลาดหรือเมื่อสิ้นสุดไฟล์เกิดขึ้นในขณะที่ไม่มีการอ่านตัวอักษร
ungetc () ส่งคืน c เมื่อสำเร็จหรือ EOF เนื่องจากข้อผิดพลาด
พิจารณาwhile
ห่วง - จุดประสงค์หลักของมันคือการทำซ้ำการกระทำถ้าเงื่อนไขในวงเล็บเป็นจริง ดูอีกครั้ง:
while ((c = getchar ()) != EOF)
โดยทั่วไปแล้วจะบอกว่าทำสิ่งต่าง ๆ ถ้า c = getchar()
ส่งคืนรหัสที่ประสบความสำเร็จ ( 0
หรือเหนือกว่านั้นมันเป็นเรื่องปกติโดยวิธีลองใช้คำสั่งที่ประสบความสำเร็จจากecho $?
นั้นก็ล้มเหลวecho $?
และดูตัวเลขที่พวกเขากลับมา) ดังนั้นหากเราได้รับตัวอักษรและ assing ไปที่ C เรียบร้อยแล้วรหัสสถานะที่ส่งคืนคือ 0, ล้มเหลวคือ -1 ถูกกำหนดให้เป็นEOF
-1
ดังนั้นเมื่อเงื่อนไข-1 == -1
เกิดขึ้นลูปจะหยุด แล้วจะเกิดอะไรขึ้น เมื่อไม่มีตัวละครที่จะได้รับอีกเมื่อc = getchar()
ล้มเหลว คุณสามารถเขียนwhile ((c = getchar ()) != -1)
และมันจะยังคงทำงาน
นอกจากนี้เรากลับไปที่รหัสจริงนี่เป็นข้อความที่ตัดตอนมา stdio.h
/* End of file character.
Some things throughout the library rely on this being -1. */
#ifndef EOF
# define EOF (-1)
#endif
รหัส ASCII และ EOT
แม้ว่าอักขระ EOF ไม่ใช่อักขระจริงอย่างไรก็ตามมีอักขระEOT
(สิ้นสุดการส่ง) ซึ่งมีค่าทศนิยม ASCII เป็น 04; มันถูกลิงค์ไปยังCtrl+ Dทางลัด (แสดงด้วยเช่นกันว่าเป็นอักขระเมตา^D
) จุดจบของตัวส่งกำลังใช้เพื่อแสดงถึงการปิดกระแสข้อมูลย้อนกลับเมื่อคอมพิวเตอร์ถูกใช้เพื่อควบคุมการเชื่อมต่อโทรศัพท์ดังนั้นการตั้งชื่อ "สิ้นสุดการส่งสัญญาณ"
ดังนั้นจึงเป็นไปได้ที่จะส่งค่า ascii ไปยังโปรแกรมเช่นนั้นโปรดสังเกต$'\04'
ว่า EOT คืออะไร:
skolodya@ubuntu:$ ./a.out <<< "a,b,c $'\04'"
digits = 1 0 0 0 1 0 0 0 0 0, white space = 2, other = 9
ดังนั้นเราสามารถพูดได้ว่ามันมีอยู่ แต่ไม่สามารถพิมพ์ได้
หมายเหตุด้านข้าง
เรามักจะลืมว่าในคอมพิวเตอร์ที่ผ่านมาไม่ได้เป็นอเนกประสงค์ - นักออกแบบจะต้องใช้ประโยชน์จากแป้นพิมพ์ทุกปุ่มใช้ได้ ดังนั้นการส่งEOT
อักขระด้วย CtrlD ยังคงเป็น "การส่งอักขระ" ซึ่งไม่เหมือนกับการพิมพ์ตัวใหญ่ A, ShiftA คุณยังคงให้อินพุตกับคีย์ที่มีอยู่ในคอมพิวเตอร์ ดังนั้น EOT จึงเป็นตัวละครที่แท้จริงในแง่ที่ว่ามันมาจากผู้ใช้มันสามารถอ่านได้โดยคอมพิวเตอร์ (แม้ว่าจะไม่สามารถพิมพ์ได้หรือไม่สามารถมองเห็นได้โดยมนุษย์) มันมีอยู่ในหน่วยความจำคอมพิวเตอร์
ความคิดเห็นของผู้บัญชาการไบต์
หากคุณพยายามอ่านจาก / dev / null นั่นควรจะส่งคืน EOF ด้วยใช่ไหม หรือฉันจะไปที่นั่นอะไร
ใช่ถูกต้องเพราะ/dev/null
ไม่มีตัวอักษรจริงที่จะอ่านดังนั้นมันc = getchar()
จะส่งคืน-1
รหัสและโปรแกรมจะออกทันที คำสั่งอีกครั้งจะไม่ส่งคืน EOF EOF เป็นเพียงตัวแปรคงที่เท่ากับ -1 ซึ่งเราใช้ในการเปรียบเทียบรหัสการกลับมาของฟังก์ชั่น ไม่ได้อยู่ในฐานะตัวละครมันเป็นเพียงแค่ภายในค่าคงที่EOF
stdio.h
การสาธิต:
# cat /dev/null shows there's no readable chars
DIR:/xieerqi
skolodya@ubuntu:$ cat /dev/null | cat -A
# Bellow is simple program that will open /dev/null for reading. Note the use of literal -1
DIR:/xieerqi
skolodya@ubuntu:$ cat readNull.c
#include<stdio.h>
void main()
{
char c;
FILE *file;
file = fopen("/dev/null", "r");
if (file)
{
printf ("Before while loop\n");
while ((c = getc(file)) != -1)
putchar(c);
printf("After while loop\n");
fclose(file);
}
}
DIR:/xieerqi
skolodya@ubuntu:$ gcc readNull.c -o readNull
DIR:/xieerqi
skolodya@ubuntu:$ ./readNull
Before while loop
After while loop
เล็บอีกอันในโลงศพ
บางครั้งมีการพยายามพิสูจน์ว่า EOF เป็นอักขระที่มีรหัสดังนี้:
#include <stdio.h>
int main(void)
{
printf("%c", EOF);
return 0;
}
ปัญหาที่เป็นที่ประเภทข้อมูลถ่านสามารถเป็นค่าที่ลงนามหรือไม่ได้ลงนาม นอกจากนี้ยังเป็นประเภทข้อมูลที่เล็กที่สุดซึ่งทำให้เป็นประโยชน์อย่างมากในไมโครคอนโทรลเลอร์ที่หน่วยความจำมี จำกัด ดังนั้นแทนที่จะประกาศint foo = 25;
ว่าเป็นเรื่องปกติที่จะเห็นในไมโครคอนโทรลเลอร์ที่มีหน่วยความจำขนาดเล็กchar foo = 25;
หรืออะไรที่คล้ายกัน นอกจากนี้ตัวอักษรอาจจะลงนามหรือไม่มีการลงชื่อ
หนึ่งสามารถตรวจสอบว่าขนาดเป็นไบต์ด้วยโปรแกรมดังนี้:
#include <stdio.h>
int main(void)
{
printf("Size of int: %lu\n",sizeof(int));
printf("Sieze of char: %lu\n",sizeof(char));
//printf("%s", EOF);
return 0;
}
skolodya@ubuntu:$ ./EOF
Size of int: 4
Sieze of char: 1
ประเด็นคืออะไร? ประเด็นก็คือว่า EOF ถูกกำหนดให้เป็น -1 แต่ถ่านประเภทข้อมูลสามารถพิมพ์จำนวนเต็มค่า
ตกลง . . ดังนั้นถ้าเราพยายามพิมพ์อักขระ char เป็นสตริง
#include <stdio.h>
int main(void)
{
printf("%s", EOF);
return 0;
}
เห็นได้ชัดว่ามีข้อผิดพลาด แต่อย่างไรก็ตามข้อผิดพลาดจะบอกสิ่งที่น่าสนใจ:
skolodya @ ubuntu: $ gcc EOF.c -o EOF
EOF.c: ในฟังก์ชั่น 'main': EOF.c: 4: 5: คำเตือน: รูปแบบ '% s' คาดว่าจะได้อาร์กิวเมนต์ประเภท 'char *' แต่อาร์กิวเมนต์ 2 มี พิมพ์ 'int'
[-Wformat =] printf ("% s", EOF);
ค่าเลขฐานสิบหก
พิมพ์ EOF เป็นค่าฐานสิบหกให้FFFFFFFF
เป็น 16 บิต (8 ไบต์) -1
มูลค่าชมเชยสองของ
#include <stdio.h>
int main(void)
{
printf("This is EOF: %X\n", EOF);
printf("This is Z: %X\n",'Z');
return 0;
}
เอาท์พุท:
DIR:/xieerqi
skolodya@ubuntu:$ ./EOF
This is EOF: FFFFFFFF
This is Z: 5A
อีกสิ่งที่อยากรู้อยากเห็นเกิดขึ้นกับรหัสต่อไปนี้:
#include <stdio.h>
int main(void)
{
char c;
if (c = getchar())
printf ("%x",c);
return 0;
}
หากกดShift+ Aเราจะได้ค่าฐานสิบ 41 อย่างเห็นได้ชัดเหมือนกับในตาราง ASCII แต่สำหรับCtrl+ Dเรามีffffffff
อีกครั้ง - ค่าตอบแทนของที่เก็บไว้ในgetchar()
c
DIR:/xieerqi
skolodya@ubuntu:$ gcc EOF.c -o ASDF.asdf
DIR:/xieerqi
skolodya@ubuntu:$ ./ASDF.asdf
A
41
DIR:/xieerqi
skolodya@ubuntu:$ ./ASDF.asdf
ffffffff
อ้างถึงภาษาอื่น ๆ
ขอให้สังเกตว่าภาษาอื่นหลีกเลี่ยงความสับสนนี้เพราะพวกเขาทำงานในการประเมินสถานะออกจากฟังก์ชั่นไม่ได้เปรียบเทียบกับแมโคร หนึ่งไฟล์อ่านใน Java อย่างไร
File inputFile = new File (filename);
Scanner readFile = new Scanner(inputFile);
while (readFile.hasNext())
{ //more code bellow }
หลามเกี่ยวกับอะไร
with open("/etc/passwd") as file:
for line in file:
print line
-1
เทียบเท่ากับ EOF มันถูกกำหนด/usr/include/stdio.h
เป็นค่าคงที่มาโคร