TL; DR : EOF bir karakter değil, giriş okuma fonksiyonunun negatif dönüşünü değerlendirmek için kullanılan bir makro. Biri işlev döndürmeye zorlayacak karakter göndermek için Ctrl+ kullanabilirDEOT
-1
Her programcı RTFM'ye sahip olmalıdır
Harbison ve Steele tarafından yayınlanan 4. CA Referans Kılavuzuna bakalım, 4. baskı. 1995, sayfa 317:
Negatif tamsayı EOF, "gerçek karakterin" kodlaması olmayan bir değerdir. . . Örneğin, fget (bölüm 15.6) dosya sonunda EOF değerini döndürür , çünkü okunacak "gerçek karakter" yoktur.
Esasen EOF
bir karakter değil , temsil etmek için uygulanan bir tamsayı değerdir . Bu nedenle, kos'un cevabı olabildiğince doğrudur, ancak "boş" girdi almakla ilgili değildir. Önemli not, burada EOF, gerçek bir karakteri belirtmek için değil, dönüş değeri (of ) karşılaştırması olarak hizmet eder . Taşıyıcıların:stdio.h
-1
getchar()
man getchar
GERİ DÖNÜŞ DEĞERİ
fgetc (), getc () ve getchar (), okunan karakteri dosya veya hata sonunda int veya EOF'ye imzasız bir char karakteri olarak döndürür.
gets () ve fgets () başarılı olduğunda döndürür ve hata durumunda veya hiçbir karakter okunmazken dosya sonu oluştuğunda NULL döndürür.
ungetc () başarı durumunda c'yi veya hata durumunda EOF değerini döndürür.
while
Döngüyü düşünün - birincil amacı, parantez içindeki durum doğruysa eylemi tekrarlamaktır . Tekrar bak:
while ((c = getchar ()) != EOF)
Temelde c = getchar()
başarılı kod döndürürse bir şeyler yapmaya devam et ( 0
ya da yukarıda; bu arada yaygın bir şey, başarılı komut çalıştırmayı deneyin, echo $?
sonra başarısız oldu echo $?
ve döndükleri sayıları görün) diyor . Bu yüzden başarıyla karakter alırsak ve C'ye değer verirsek, döndürülen durum kodu 0, başarısız -1 olur. EOF
olarak tanımlanır -1
. Bu nedenle koşul -1 == -1
oluştuğunda döngüler durur. Ve bu ne zaman olacak? Alınacak başka karakter olmadığında, c = getchar()
başarısız olduğunda. Yazabilirsiniz while ((c = getchar ()) != -1)
ve yine de işe yarardı
Ayrıca, gerçek koda geri dönelim, işte bir alıntı stdio.h
/* End of file character.
Some things throughout the library rely on this being -1. */
#ifndef EOF
# define EOF (-1)
#endif
ASCII kodları ve EOT
EOF karakteri gerçek bir karakter olmamasına rağmen EOT
, ASCII ondalık değeri 04 olan bir (İletim Sonu) karakteri vardır; Bu bağlantılıdır Ctrl+ D(meta karakter olarak da temsil kısayol ^D
). İletim sonu karakteri, bilgisayarlar telefon bağlantılarını kontrol etmek için kullanıldığında bir veri akışının kapanışını, dolayısıyla "iletim sonu" adını belirtmek için kullanılır.
Bu nedenle, bu ascii değerini programa şu şekilde göndermek mümkündür, $'\04'
hangisinin EOT olduğuna dikkat edin :
skolodya@ubuntu:$ ./a.out <<< "a,b,c $'\04'"
digits = 1 0 0 0 1 0 0 0 0 0, white space = 2, other = 9
Böylece var olduğunu söyleyebiliriz, ancak yazdırılamaz
Kenar notu
Geçmiş bilgisayarlarda çok yönlü olmadığını sık sık unutuyoruz - tasarımcılar mevcut her klavye tuşunu kullanmak zorundalar. Bu nedenle, EOT
CtrlD ile karakter gönderme, büyük harf A, ShiftA yazmanın aksine hala "bir karakter gönderir", yine de bilgisayara kullanılabilir tuşlarla bir giriş verirsiniz. Böylece EOT, kullanıcıdan geldiği anlamında gerçek bir karakterdir, bilgisayar tarafından okunabilir (yazdırılabilir olmasa da, insanlar tarafından görülemez), bilgisayar belleğinde bulunur
Byte Commander adlı kullanıcının yorumu
/ Dev / null'dan okumaya çalışırsanız, bu bir EOF da döndürmelidir, değil mi? Ya da oraya ne getireyim?
Evet, kesinlikle doğru, çünkü /dev/null
okunacak gerçek bir karakter yok, bu yüzden kodu c = getchar()
döndürecek -1
ve program hemen kapanacak. Yine komut EOF döndürmez. EOF, getchar fonksiyonunun dönüş kodunu karşılaştırmak için kullandığımız -1'e eşit sabit bir değişkendir . EOF
karakter olarak mevcut değil, içinde sadece statik bir değer var stdio.h
.
Demo:
# 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
Tabutta başka bir çivi
Bazen EOF'un böyle bir kodu olan bir karakter olduğu kanıtlanmaya çalışılır:
#include <stdio.h>
int main(void)
{
printf("%c", EOF);
return 0;
}
Sorun şu ki, char veri tipi imzalı veya imzasız bir değer olabilir. Ayrıca, hafızanın sınırlı olduğu mikrodenetleyicilerde onları çok kullanışlı kılan adreslenebilir en küçük veri tipidir. Bu nedenle, beyan int foo = 25;
etmek yerine, küçük hafızaya char foo = 25;
veya benzer bir şeye sahip mikrodenetleyicilerde görmek yaygındır . Ayrıca, karakter imzalı veya imzasız olabilir .
Aşağıdaki gibi bir programla bayt cinsinden boyut doğrulanabilir:
#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
Amaç tam olarak nedir? Mesele şu ki, EOF -1 olarak tanımlanmıştır, ancak char veri tipi tamsayı değerlerini yazdırabilir .
TAMAM . . .so char karakterlerini dize olarak yazdırmaya çalışırsak?
#include <stdio.h>
int main(void)
{
printf("%s", EOF);
return 0;
}
Açıkçası bir hata, ama yine de, hata bize ilginç bir şey söyleyecektir:
skolodya @ ubuntu: $ gcc EOF.c -o EOF
EOF.c: 'main' fonksiyonunda: EOF.c: 4: 5: uyarı: '% s' biçimi 'char *' türünde bir argüman bekliyor, ancak 2 argümanı 'int'
[-Wformat =] printf ("% s", EOF) yazın;
Onaltılı değerler
EOF'u onaltılık değer olarak yazdırmak FFFFFFFF
, 16 bit (8 bayt) bir değer verir, ikisinin a -1
.
#include <stdio.h>
int main(void)
{
printf("This is EOF: %X\n", EOF);
printf("This is Z: %X\n",'Z');
return 0;
}
Çıktı:
DIR:/xieerqi
skolodya@ubuntu:$ ./EOF
This is EOF: FFFFFFFF
This is Z: 5A
Başka bir meraklı şey aşağıdaki kodla gerçekleşir:
#include <stdio.h>
int main(void)
{
char c;
if (c = getchar())
printf ("%x",c);
return 0;
}
Biri Shift+ tuşuna basarsa A, ASCII tablosunda olduğu gibi onaltılık 41 değerini alırız. Ama Ctrl+ Diçin ffffffff
, yine - içinde getchar()
depolanan dönüş değerine sahibiz 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
Diğer dillere bakın
Diğer dilin bu karışıklığı önlediğine dikkat edin, çünkü bir işlev çıkış durumunu değerlendirmekle çalışırlar, bir makro ile karşılaştırmazlar. Java ile dosya nasıl okunur?
File inputFile = new File (filename);
Scanner readFile = new Scanner(inputFile);
while (readFile.hasNext())
{ //more code bellow }
Python'a ne dersin?
with open("/etc/passwd") as file:
for line in file:
print line
-1
EOF karşılığıdır./usr/include/stdio.h
Makro sabit olarak tanımlanır