2
votes

EOF non détecté par C sur Raspberry Pi

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?


0 commentaires

3 Réponses :


2
votes

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 .


0 commentaires

1
votes

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);


0 commentaires

3
votes

Premiers faits:

  • Le symbole EOF est une macro qui se développe jusqu'à la constante entière -1 . Cette constante entière aura le type int .
  • Il est défini par l'implémentation si 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>


0 commentaires