J'écrivais donc un programme sur mon Raspberry Pi Zero pour compter les fréquences de différentes longueurs de mot dans l'entrée, mais le programme ne s'est pas arrêté à EOF.
J'ai donc essayé ceci pour déboguer:
gcc test.c && ./a.out <input.txt
Et compilé avec ceci:
#include <stdio.h> #include <stdlib.h> void main() { char c; while ( (c = getchar()) != EOF) { putchar(c); } }
Il a imprimé le texte d'entrée, mais a continué à imprimer des points d'interrogation jusqu'à ce que j'appuie sur Ctrl + C. Quand j'ai copié le programme sur mon ordinateur portable et l'ai exécuté là-bas, tout fonctionnait bien.
Je pourrais simplement terminer sur l'ordinateur portable, mais je suis curieux. Pourquoi le Pi ne peut-il pas détecter quand le fichier atteint EOF?
3 Réponses :
getchar
renvoie la valeur int
et non la valeur char
. Puisque vous avez besoin d'un moyen de reconnaître dans une fonction getchar
si vous lisez un caractère normal ou si la fonction vous dit qu'il n'y a plus rien à lire - il y a longtemps, quelqu'un a décidé d'utiliser int
afin qu'une valeur plus grande que char
puisse être retournée pour indiquer la fin du fichier. Remplacez char
par int
.
La valeur de retour de getchar
est censée pouvoir renvoyer n'importe quel caractère ASCII (et ASCII étendu) compris entre 0 et 255.
Afin de faire la distinction entre un ascii et un EOF, EOF ne peut pas être une valeur dans cet intervalle, donc le type de retour de getchar doit avoir plus de 8 bits.
int c; while ( (c = getchar()) != EOF) ...
Vous devriez donc écrire
int getchar(void);
Premiers faits:
EOF
est une macro qui se développe jusqu'à la constante entière -1
. Cette constante entière aura le type int
. char
est signé ou non signé. Le même compilateur sur différentes plates-formes peut avoir différentes implémentations de char
. Maintenant, pour la longue explication de votre problème:
Lorsque des types entiers de différentes tailles sont utilisés dans des expressions arithmétiques (et que la comparaison est considérée comme un opérateur arithmétique), alors les deux opérandes de l'expression subit une conversion arithmétique habituelle pour obtenir un type commun (généralement int
).
Pour les types d'entiers plus petits, comme par exemple char
, cela implique promotion d'entier pour le convertir en un int
. Pour cette promotion, la valeur du char
doit être conservée intacte, par exemple -1
en tant que char
sera toujours -1
en tant que int
.
Parce que de la façon dont les nombres négatifs sont représentés sur la plupart des systèmes, la valeur char
de -1
est (en hexadécimal) 0xff
. Pour un char
signé, lorsque -1
est converti en un int
, il conserve la valeur -1
(qui sera représenté par 0xffffffff
pour un type int
32 bits).
Le problème survient lorsque char
est unsigned , car alors quand getchar
renvoie EOF
(la valeur -1
) le char
non signé La valeur sera égale à 255
(la représentation décimale non signée de 0xff
). Et une fois promu à un int
, la valeur sera toujours 255
. Et 255! = -1
!
C'est pourquoi le getchar
le type de retour est int
et non char
. Et l'une des raisons pour lesquelles toutes les fonctions de gestion des caractères utilisent int
au lieu de char
.
Donc, pour résoudre votre problème problème, vous devez changer le type de la variable c
en int
:
int c;
Ensuite, cela fonctionnera p>