TL; DR : EOF n'est pas un caractère, c'est une macro utilisée pour évaluer le retour négatif d'une fonction de lecture d'entrée. On peut utiliser Ctrl+ Dpour envoyer un EOT
caractère qui forcera le retour de la fonction-1
Chaque programmeur doit RTFM
Reportons-nous au "CA Reference Manual", de Harbison et Steele, 4e éd. à partir de 1995, page 317:
L'entier négatif EOF est une valeur qui n'est pas un codage d'un "caractère réel". . . Par exemple, fget (section 15.6) renvoie EOF à la fin du fichier, car il n'y a pas de "vrai caractère" à lire.
Ce EOF
n'est essentiellement pas un caractère, mais plutôt une valeur entière implémentée stdio.h
pour représenter -1
. Ainsi, la réponse de kos est correcte dans la mesure où cela va, mais il ne s'agit pas de recevoir une entrée "vide". Il est important de noter qu'EOF sert ici de comparaison de valeur de retourgetchar()
, pas pour signifier un caractère réel. Le man getchar
soutient que:
VALEUR DE RETOUR
fgetc (), getc () et getchar () renvoient le caractère lu sous forme de transtypage non signé à un int ou EOF à la fin du fichier ou d'une erreur.
gets () et fgets () renvoient s en cas de succès, et NULL en cas d'erreur ou lorsque la fin du fichier se produit alors qu'aucun caractère n'a été lu.
ungetc () renvoie c en cas de succès, ou EOF en cas d'erreur.
Considérez la while
boucle - son objectif principal est de répéter l'action si la condition entre crochets est vraie . Regarde encore:
while ((c = getchar ()) != EOF)
Il dit essentiellement de continuer à faire des choses si c = getchar()
renvoie un code réussi ( 0
ou supérieur; c'est une chose courante d'ailleurs, essayez d'exécuter une commande réussie, echo $?
puis échouez echo $?
et voyez les nombres qu'ils renvoient). Donc, si nous obtenons avec succès le caractère et l'assing à C, le code d'état renvoyé est 0, l'échec est -1. EOF
est défini comme -1
. Par conséquent, lorsque la condition -1 == -1
se produit, les boucles s'arrêtent. Et quand cela arrivera-t-il? Quand il n'y a plus de personnage à obtenir, quand c = getchar()
échoue. Vous pourriez écrire while ((c = getchar ()) != -1)
et ça marcherait toujours
Revenons également au code actuel, voici un extrait de stdio.h
/* End of file character.
Some things throughout the library rely on this being -1. */
#ifndef EOF
# define EOF (-1)
#endif
Codes ASCII et EOT
Bien que le caractère EOF ne soit pas un caractère réel, cependant, il existe un caractère EOT
(Fin de transmission), qui a une valeur décimale ASCII de 04; il est lié au raccourci Ctrl+ D(représenté également par un méta-caractère ^D
). Le caractère de fin de transmission signifiait la fermeture d'un flux de données remontant à l'époque où les ordinateurs étaient utilisés pour contrôler les connexions téléphoniques, d'où le nom de «fin de transmission».
Il est donc possible d'envoyer cette valeur ascii au programme comme ceci, notez $'\04'
qui est l'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
Ainsi, nous pouvons dire qu'il existe, mais il n'est pas imprimable
Note latérale
Nous oublions souvent que dans le passé, les ordinateurs n'étaient pas aussi polyvalents - les concepteurs doivent utiliser toutes les touches du clavier disponibles. Ainsi, l'envoi de EOT
caractère avec CtrlD est toujours "l'envoi d'un caractère", contrairement à la saisie de majuscules A, ShiftA, vous faites toujours donner à l'ordinateur une entrée avec les touches disponibles. Ainsi EOT est un vrai personnage dans le sens où il vient de l'utilisateur, il est lisible par ordinateur (bien que non imprimable, non visible par l'homme), il existe dans la mémoire de l'ordinateur
Commentaire de Byte Commander
Si vous essayez de lire à partir de / dev / null, cela devrait également renvoyer un EOF, non? Ou qu'est-ce que j'y arrive?
Oui, exactement, car /dev/null
il n'y a pas de caractère réel à lire, donc il c = getchar()
renverra du -1
code et le programme se fermera immédiatement. Encore une fois, la commande ne renvoie pas EOF. EOF est juste une variable constante égale à -1, que nous utilisons pour comparer le code retour de la fonction getchar . EOF
n'existe pas en tant que personnage, c'est juste une valeur statique à l'intérieur stdio.h
.
Démo:
# 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
Un autre clou dans le cercueil
Parfois, on tente de prouver que EOF est un caractère avec un code comme celui-ci:
#include <stdio.h>
int main(void)
{
printf("%c", EOF);
return 0;
}
Le problème est que le type de données char peut être une valeur signée ou non signée. De plus, ce sont les plus petits types de données adressables, ce qui les rend très utiles dans les microcontrôleurs, où la mémoire est limitée. Ainsi, au lieu de déclarer, int foo = 25;
il est courant de voir dans les microcontrôleurs à petite mémoire char foo = 25;
ou quelque chose de similaire. De plus, les caractères peuvent être signés ou non signés .
On pourrait vérifier que la taille en octets avec un programme comme celui-ci:
#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
Quel est le but ? Le fait est que EOF est défini comme -1, mais le type de données char peut imprimer des valeurs entières .
D'ACCORD . . Et si nous essayons d'imprimer char en chaîne?
#include <stdio.h>
int main(void)
{
printf("%s", EOF);
return 0;
}
Évidemment, une erreur, mais néanmoins, l'erreur nous dira quelque chose d'intéressant:
skolodya @ ubuntu: $ gcc EOF.c -o EOF
EOF.c: dans la fonction 'main': EOF.c: 4: 5: avertissement: le format '% s' attend l'argument de type 'char *', mais l'argument 2 a tapez 'int'
[-Wformat =] printf ("% s", EOF);
Valeurs hexadécimales
L'impression EOF sous forme de valeur hexadécimale donne FFFFFFFF
, une valeur de 16 bits (8 octets), compliment à deux de a -1
.
#include <stdio.h>
int main(void)
{
printf("This is EOF: %X\n", EOF);
printf("This is Z: %X\n",'Z');
return 0;
}
Production:
DIR:/xieerqi
skolodya@ubuntu:$ ./EOF
This is EOF: FFFFFFFF
This is Z: 5A
Une autre chose curieuse se produit avec le code suivant:
#include <stdio.h>
int main(void)
{
char c;
if (c = getchar())
printf ("%x",c);
return 0;
}
Si l'on appuie sur Shift+ A, nous obtenons la valeur hexadécimale 41, évidemment la même que dans le tableau ASCII. Mais pour Ctrl+ D, nous avons ffffffff
, encore une fois - la valeur de retour de getchar()
stocké dans 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
Se référer à d'autres langues
Notez que d'autres langages évitent cette confusion, car ils opèrent sur l'évaluation d'un état de sortie de fonction, et non sur la comparaison avec une macro. Comment lit-on un fichier en Java?
File inputFile = new File (filename);
Scanner readFile = new Scanner(inputFile);
while (readFile.hasNext())
{ //more code bellow }
Et le python?
with open("/etc/passwd") as file:
for line in file:
print line
-1
est équivalent à EOF. Il est défini/usr/include/stdio.h
comme une constante macro