Langage de programmation K & R C 1.5.1 (copie de fichier)

Eh bien, j’ai lu il y a quelques mois un autre livre C “bien connu” (dans ma langue), et je n’ai jamais rien appris à ce sujet. La façon dont K & R écrit 3 chapitres en 20 pages est tout simplement incroyable, et bien sûr, je ne peux pas espérer d’énormes explications, mais cela soulève également des questions.

J’ai une question à propos de ce point 1.5.1 Le livre dit (page 16):

main(){ int c;// <-- Here is the question c=getchar(); while (c != EOF){ putchar(c); c = getchar(); } } 

[…] Le caractère de type est spécifiquement destiné à stocker de telles données de caractères, mais tout type entier peut être utilisé. Nous avons utilisé int pour une raison subtile mais importante. Le problème consiste à distinguer la fin de la saisie des données valides. La solution est que getchar renvoie une valeur distinctive lorsqu’il n’y a plus d’entrées, une valeur qui ne peut être transmise à aucun caractère réel. Cette valeur s’appelle EOF, pour “fin de fichier”. Nous devons déclarer que c est un type assez grand pour contenir toute valeur renvoyée par getchar. Nous ne pouvons pas utiliser char car c doit être assez grand pour contenir EOF en plus des char possibles. Par conséquent, nous utilisons int. […]

Après avoir cherché sur Google pour une autre explication:

EOF est une macro spéciale représentant End Of File (Linux: utilisez CTRL + d sur le clavier pour le créer, commande Windows: utilisez CTRL + z (il peut être nécessaire de placer le début de la nouvelle ligne, suivi de RETURN)): EOF = -1, mais dépend de l’implémentation. Doit être une valeur qui n’est pas une valeur valide pour tout caractère possible. Pour cette raison, c est de type int (pas de caractère comme on pouvait s’y attendre).

J’ai donc modifié la source d’Int à Char pour voir quel est le problème, prendre des valeurs EOF … mais il n’y a pas de problème. Fonctionne de la même manière.

Je n’ai pas non plus compris comment getchar prend chaque caractère que j’écris et imprime tout. Le type Int a une longueur de 4 octets et peut donc prendre 4 caractères dans une variable. Mais je peux mettre n’importe quel nombre de caractères, il va tout lire et tout écrire de la même manière. Et avec les personnages, il se passe la même chose … Qu’est-ce qui se passe réellement? Où sont les valeurs stockées quand il y a plus de 1-4 caractères?

J’ai donc modifié la source d’Int à Char pour voir quel est le problème, prendre des valeurs EOF … mais il n’y a pas de problème. Fonctionne de la même manière

Il se trouve que je travaille de la même manière. Tout dépend du type de caractère réel, c’est-à-dire s’il est signé ou non. Il y a aussi une FAQ sur ce sujet. Vous êtes plus susceptible de voir le bogue si vos caractères ne sont pas signés.

Le bogue peut restr longtemps non détecté, cependant, si les caractères sont signés et si l’entrée est composée uniquement de caractères 7 bits.

MODIFIER

La dernière question est la suivante: le type char est long d’un octet et int est long de 4 octets. Ainsi, char ne prendra qu’un caractère ascii. Mais si je tape “débordement de stack supérieur à 1 octet”, le résultat sera “débordement de stack supérieur à 1 octet”. Où est “le dépassement de virement est supérieur à 1 octet de long” stocké, et comment putchar met une chaîne entière

Chaque caractère sera stocké par c à tour de rôle. Ainsi, la première fois, getchar() retournera s et putchar le renverra. Ensuite, ça va venir et ainsi de suite. A aucun moment, c stockera plus d’un caractère. Donc, bien que vous le nourrissiez avec une grosse ficelle, il le fait en mangeant un caractère à la fois.

Séparer en deux réponses:

Pourquoi int et pas char

Réponse courte et formelle: si vous voulez pouvoir représenter tous les caractères réels et un autre caractère non réel (EOF), vous ne pouvez pas utiliser un type de données conçu pour contenir uniquement des caractères réels.

Réponse qui peut être comprise mais pas tout à fait exacte : La fonction getchar() renvoie le code ASCII du caractère lu, ou EOF.

Étant donné que -1 correspond à 255, nous ne pouvons pas distinguer le caractère 255 et le caractère EOF. C’est,

 char a = 255; char b = EOF; a == b // Evaluates to TRUE 

mais,

 int a = 255; int b = EOF; a == b // Evaluates to FALSE 

Donc, utiliser char ne vous permettra pas de faire la distinction entre un caractère dont le code ASCII est 255 (ce qui peut arriver lors de la lecture d’un fichier) et EOF.

Comment pouvez-vous utiliser putchar() avec un int

La fonction putchar() examine son paramètre, voit un nombre, puis passe à la table ASCII et dessine le glyphe qu’elle voit. Lorsque vous passez un int , il est implicitement converti en char . Si le nombre dans l’ int correspond au caractère, tout va bien et personne ne remarquera rien.

Si vous utilisez char pour stocker le résultat de getchar() , il existe deux problèmes potentiels, que vous rencontrerez dépend de la signature de char .

  • si char est non signé, c == EOF ne sera jamais vrai et vous obtiendrez une boucle infinie.

  • si char est signé, c == EOF sera vrai lorsque vous saisirez un caractère. Ce qui dépendra du charset utilisé; dans les parameters régionaux utilisant ISO8859-1 ou CP852, il est ‘ÿ’ si EOF est égal à -1 (valeur la plus courante). Certains jeux de caractères, par exemple UTF-8, n’utilisent pas la valeur (char)EOF dans des codes valides, mais vous pouvez rarement garantir que votre problème restra en implémentation de caractères signés et ne sera utilisé que dans des parameters régionaux non problématiques.