2017-09-17 5 views
1

Je suis conscient que cette question a été posée, mais elle n'a pas été expliquée étape par étape et ou assez pour moi bien comprendre comment son exécuté, donc, dire que j'ai cette partie du code:Nécessaire explication étape par étape de "while ((ch = getchar())! = ' N' && c! = EOF;"

char ch; 
while((ch = getchar()) != '\n' && ch != EOF); 

Est-ce que getchar() lire un seul caractère dans la 1ère variable de ch puis faire la comparaison, c'est ch != '\n' && ch != EOF, en laissant la séquence d'échappement de nouvelle ligne tamponnée, mais pas réellement dans la variable ch? Et si oui, cela ne signifie-t-il pas qu'il bouclera infiniment jusqu'à ce qu'il rencontre la séquence d'échappement de nouvelle ligne/EOF? rencontre une nouvelle séquence d'échappement, est-elle stockée dans la variable ch? f pas, comment pas?

+0

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

+3

Ce code est cassé. 'getchar' renvoie' int' (pas 'char') pour une raison. – melpomene

+0

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

Répondre

7
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:

  1. 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).

  2. 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;