char ch;
D'abord, nous définissons une variable ch
de type char
.
while((ch = getchar()) != '\n' && ch != EOF);
Ceci est une boucle while
. La condition de boucle est (ch = getchar()) != '\n' && ch != EOF
et le corps de la boucle est ;
(une instruction null).
La condition de boucle est constituée d'un &&
(logique "et") et de deux opérandes, (ch = getchar()) != '\n'
et ch != EOF
. L'opérateur &&
évalue toujours son opérande gauche en premier.
(ch = getchar()) != '\n'
est une comparaison d'inégalité. Le côté droit est '\n'
(qui représente un caractère de retour à la ligne). Le côté gauche est une expression d'affectation, ch = getchar()
.
getchar()
appelle la fonction getchar
, qui lit un caractère de stdin
(entrée standard). En cas de succès, ce caractère est retourné sous la forme d'un unsigned char
(généralement dans la plage 0 .. 255); sinon (si getchar
échoue), il renvoie EOF
(qui est une valeur négative (spécifique à l'implémentation)). C'est pourquoi le type de retour de getchar
est int
: Il doit représenter toutes les valeurs de caractères valides et un indicateur d'erreur.
Cette valeur est stockée dans ch
. À ce stade, il y a deux possibilités:
char
est un type non signé dans votre mise en œuvre. Dans ce cas, chaque caractère lu avec succès est stocké tel quel, mais EOF
sera mappé à un caractère normal. Si (comme d'habitude) EOF
a la valeur -1
, cela finira par devenir UCHAR_MAX
(typiquement 255).
char
est un type signé dans votre implémentation. Dans ce cas, la moitié de toutes les valeurs de caractères possibles sont hors de portée (typiquement char
a une plage de -128 .. 127 et est incapable de stocker des valeurs de 128 .. 255). Ici, les choses deviennent un peu floues: un caractère hors limites produira un signal (défini par l'implémentation) ou sera converti en un autre caractère (défini par l'implémentation). D'autre part, EOF
sera probablement conservé tel quel (sauf s'il a une valeur inférieure à CHAR_MIN
, auquel cas vous obtenez un signal défini par l'implémentation ou une conversion, comme précédemment).
Une expression d'affectation a la valeur de l'opérande gauche après l'affectation. Ainsi, (ch = getchar())
renvoie la nouvelle valeur ch
(qui est le caractère d'entrée tronqué comme décrit ci-dessus). Nous comparons ce personnage à '\n'
(newline). Si c'est un retour à la ligne, !=
donne un résultat faux, &&
donne un résultat faux immédiatement, et la boucle s'arrête. (Notez que selon votre mise en œuvre, d'autres personnages ou même EOF pourrait être mal détecté comme '\n'
en raison de la mutiler décrit ci-dessus.)
Si le caractère d'entrée est une nouvelle ligne, !=
cède vrai et &&
produit pour évaluer sa droite opérande de la main. Ici, nous comparons ch != EOF
. Si nous sommes dans le cas n ° 1 (ie char
est un type non signé), cette comparaison est toujours vraie car EOF
est une valeur négative (sauf si nous sommes dans une situation encore plus exotique et char
/int
ont la même taille/gamme de valeurs possibles , que je ne vais pas aller dans). Si nous sommes dans le cas # 2 (c'est-à-dire char
est un type signé), cette comparaison retournera false si getchar
a renvoyé EOF
(c'est-à-dire si la fin de l'entrée a été atteinte ou une erreur s'est produite) et la boucle s'arrête. Il va aussi mal identifier certains caractères (habituellement UCHAR_MAX
, 255) comme EOF
.
Dans le cas contraire (par exemple si ch
est pas '\n'
ou EOF
) les séquences répétées en boucle et le caractère suivant est lu et examiné.
L'intention de ce code est de consommer et de rejeter l'entrée jusqu'à ce qu'un retour à la ligne ou une fin d'entrée soit atteint. Mais en raison de la façon dont le code est écrit, il ne reconnaît pas EOF
(et boucle donc toujours quand il atteint la fin de l'entrée) ou traite l'entrée valide comme EOF
(et donc se termine tôt).
Le correctif est de déclarer ch
comme int
:
int ch;
Commencez avec les parens les plus internes et travailler votre chemin. L'affectation à 'ch' d'un appel' getchar() 'consommant du flux par définition écrase toute la théorie de *" laissant la séquence d'échappement de nouvelle ligne tamponnée, mais pas réellement dans la variable ch "*. – WhozCraig
Ce code est cassé. 'getchar' renvoie' int' (pas 'char') pour une raison. – melpomene
Je ne comprends pas ce que vous voulez dire quand vous dites "nouvelle séquence d'échappement". Une séquence d'échappement comme '\ n' (backslash-n) est une caractéristique du code source C; ce n'est pas une chose qui existe dans les données au moment de l'exécution. – melpomene