OVH Cloud OVH Cloud

comprendre getchar()

59 réponses
Avatar
bpascal123
Je trouve getchar() assez difficile =E0 comprendre. Au lieu de saisir du
clavier, getchar lit directement dans la m=E9moire? Presser une touche
du claver entraine un signal dans le bios qui "renvoie" ce signal dans
le kernel puis dans la m=E9moire (buffer) et de ce dernier est affich=E9
le caract=E8re de la touche press=E9e (par ex.: a) pr=E9c=E9demment. Par
contre le caract=E8re reste toujours dans le buffer mais dans la partie
"ancienne" du buffer. Dans la partie "neuve", se trouverait les
caract=E8res qui n'ont pas =E9t=E9 affich=E9s =E0 l'=E9cran ou trait=E9s d'=
une autre
mani=E8re.

Ce code d'apparence simple pour la saisie me laisse perplexe:

#include <stdio.h>

int main(void)
{
char c ;
c =3D getchar() ;

while ( c !=3D EOF )
{
putchar(c) ;
c =3D getchar() ;
}
return 0 ;
}

Je me demande si un petit apprentissage de l'assembleur jusqu'=E0
comprendre ce code, ne serait pas utile dans ce cas?

10 réponses

1 2 3 4 5
Avatar
espie
In article <4c1f8aeb$0$8090$,
Samuel DEVULDER wrote:
Antoine Leca a écrit :

Reste le cas de EOF : il faut bien comprendre que si tu utilises
c = getc(FLUX);
if ( fin(FLUX) ) break;
/* ... */
en C, l'opération fin(FLUX) s'écrira
c == EOF



On peut aussi utiliser feof(FLUX) dans le cas présent, non?




Bof.

feof() ne renvoie vrai qu'une fois que tu as *atteint* la fin du fichier,
donc typiquement, uniquement quand tu as essaye de lire, et que ton getchar
t'a renvoye un EOF.

-> tu sais deja que tu es a la fin du flux.

-> feof() ne sert qu'a discerner feof() de ferror().
Avatar
Samuel DEVULDER
Marc Espie a écrit :

en C, l'opération fin(FLUX) s'écrira
c == EOF


On peut aussi utiliser feof(FLUX) dans le cas présent, non?




Bof.



Ce qui veut dire "oui éventuellement mais j'aime pas trop" :)

feof() ne renvoie vrai qu'une fois que tu as *atteint* la fin du fichier,
donc typiquement, uniquement quand tu as essaye de lire, et que ton getchar
t'a renvoye un EOF.

-> tu sais deja que tu es a la fin du flux.

-> feof() ne sert qu'a discerner feof() de ferror().



C'est pas faux, mais quand on voit l'écriture "fonctionnelle" d'Antoine,
avec une fonction fin prenant le flux en argument (et pas le char/int),
moi ça me fait penser immédiatement à feof().

Par ailleurs l'écriture suivante:

char c = (char)fgetc(FLUX);
if(feof(FLUX)) break;

Me semble claire, et assez proche des API des autres langages qui ont
une fonctionnalité type feof. L'avantage qu'on peut trouver à l'usage de
feof() c'est qu'il marche pour toutes les fonctions stdio de façon
homogène. Il est ainsi plus simple de lire un code où la fin de fichier
se détecte via feof() plutot que de tantôt comparer le code de retour à
EOF, à 0, à -1 ou à NULL.

Mais c'est probablement une question de gout et du style d'écriture
autour (une API homogène a son charme). D'un coté on a une fonction qui
indique clairement ce qu'elle fait, de l'autre on va être obligé de
mettre un commentaire /* EOF */ à coté du "==NULL" ou du "<0" pour
faciliter la relecture de code. A voir selon les critères de chacun.

sam.
Avatar
Jean-Marc Bourguet
Samuel DEVULDER writes:

Par ailleurs l'écriture suivante:

char c = (char)fgetc(FLUX);
if(feof(FLUX)) break;

Me semble claire, et assez proche des API des autres langages qui ont une
fonctionnalité type feof.



Quelques problèmes:

- c'est quand même différent des langages qui ont un feof prédictif qui ont
besoin de quelque chose du genre:

if FEOF(fl) then break;
c := FGETC(flux);

- ne permet pas de détecter une erreur de lecture (fgetc retourne EOF mais
feof est faux et ferror est vrai)

- si j'ai bonne mémoire, feof peut être vrai sans que le résultat de
fgetc() soit EOF (simplement l'entrée suivant échouera pour cause de fin
de fichier)

- cette forme ne s'etends pas aux autres fonctions d'I/O (pour lesquelles
je suis sûr du point précédent)

- ce n'est pas idiomatique et il faut donc réfléchir plus

A+

--
Jean-Marc
FAQ de fclc: http://www.levenez.com/lang/c/faq
Site de usenet-fr: http://www.usenet-fr.news.eu.org
Avatar
Samuel DEVULDER
Jean-Marc Bourguet a écrit :
Samuel DEVULDER writes:

Par ailleurs l'écriture suivante:

char c = (char)fgetc(FLUX);
if(feof(FLUX)) break;

Me semble claire, et assez proche des API des autres langages qui ont une
fonctionnalité type feof.



Quelques problèmes:

- c'est quand même différent des langages qui ont un feof prédictif qui ont
besoin de quelque chose du genre:

if FEOF(fl) then break;
c := FGETC(flux);



Un pseudo pascal?

Oui.. mais pas mal de langages ont un feof() issu de la sémantique du C
qui n'est pas prédictif. Le Pascal est connu pour avoir des pbs avec son
EOF() qui "lit un char en avant sans le manger".

- ne permet pas de détecter une erreur de lecture (fgetc retourne EOF mais
feof est faux et ferror est vrai)



Normal, ca ne testes que la fin de fichier. Une seule chose par fonction
me semble être un truc pas mal. Comme tu l'indiques, pour les erreurs
il y a ferror().

- si j'ai bonne mémoire, feof peut être vrai sans que le résultat de
fgetc() soit EOF (simplement l'entrée suivant échouera pour cause de fin
de fichier)



C'est pas logique, tu décris un feof() prédictif.

- cette forme ne s'etends pas aux autres fonctions d'I/O (pour lesquelles
je suis sûr du point précédent)



Les io ailleurs que stdio? Parce que feof() doit marcher sur tout FILE*,
donc ca marche avec fread() aussi par ex.

- ce n'est pas idiomatique et il faut donc réfléchir plus



A te lire, je me demande bien pourquoi ils ont crées feof() si il ne
faut pas trop l'utiliser. Bon c'est peut être une question de gout.

sam.
Avatar
bpascal123
A vrai dire, je prends le temps d'apprendre avec un tuto en ligne qui
contient des exercices de difficultés croissantes et qui suivent un
programme. Les exercices sont très accessibles car pour mon niveau,
j'estime le K&R au-delà de mes facultés même avec de l'entraînement .
Je trouve que le K&R demande un certain niveau d'abstraction (j'ai
passé un peu de temps à comprendre les exercices de push et pop du
stack) mais en surface seulement, je ne suis pas sûre de comprendre
quelque chose d'aussi abstrait que certaines des fonctions qu'ils
écrivent, j'ai déjà beaucoup de mal avec malloc et free...Si j'avais
eu à écrire le programme de conversion celsius-fahrenheit, j'aurais
fait quelque chose de plus long.

Seulement, j'essaie d'aller au-delà des exercices du tuto avec lequel
j'apprends (moyennant une petite participation financière car même si
c'est librement accessible, je considère que tout travail mérité
salaire...) surtout si je m'appuie sur un cours structurés avec des
exercices cohérents...

J'ajoute à ces exercices quelques difficultés et au delà de la
solution, je dois poser des questions sur des forums pour comprendre
pourquoi je n'y arrive pas. Mais je précise que mise à part la
fonction gets() qui est utilisée par l'auteur et que pour laquelle
j'ai appris à utiliser fgets pour être à jour et maintenant je
comprends que getchar() peut aussi s'employer à la place de fgets,
notamment avec realloc, je ne pense pas que j'ai rencontré d'autres
choses qui peuvent avoir un lien avec dos ou un système spécifique.

Autrement je fais beaucoup de recherches et peut-être, je peux tomber
sur quelque chose qui n'est pas très à jour. Mais je serais curieux de
savoir pourquoi ça n'a existé que sur un système et pourquoi ça
n'existe plus mais après c'est vrai que je m'éloigne du sujet.

-Merci
Avatar
Vivien Moreau
On 2010-06-22, wrote:

A vrai dire, je prends le temps d'apprendre avec un tuto en ligne qui
contient des exercices de difficultés croissantes et qui suivent un
programme. Les exercices sont très accessibles car pour mon niveau,
j'estime le K&R au-delà de mes facultés même avec de l'entraînement.
Je trouve que le K&R demande un certain niveau d'abstraction (j'ai
passé un peu de temps à comprendre les exercices de push et pop du
stack) mais en surface seulement, je ne suis pas sûre de comprendre
quelque chose d'aussi abstrait que certaines des fonctions qu'ils
écrivent, j'ai déjà beaucoup de mal avec malloc et free...Si j'avais
eu à écrire le programme de conversion celsius-fahrenheit, j'aurais
fait quelque chose de plus long.



Certes, le K&R n'est pas un bouquin pour apprendre à
programmer ( et de l'avis de pas mal ici et de moi, le C
n'est pas non plus un langage adapté, mais c'est une autre
histoire... )

Seulement, j'essaie d'aller au-delà des exercices du tuto avec lequel
j'apprends [...]



Oui, ça c'est très bien. Rien de mieux que la pratique, je
pense.

--
Vivien Moreau
Avatar
Jean-Marc Bourguet
Samuel DEVULDER writes:

Jean-Marc Bourguet a écrit :
> Samuel DEVULDER writes:
>
>> Par ailleurs l'écriture suivante:
>>
>> char c = (char)fgetc(FLUX);
>> if(feof(FLUX)) break;
>>
>> Me semble claire, et assez proche des API des autres langages qui ont une
>> fonctionnalité type feof.
> Quelques problèmes:
> - c'est quand même différent des langages qui ont un feof prédictif qui
> ont
> besoin de quelque chose du genre:
> if FEOF(fl) then break;
> c := FGETC(flux);

Un pseudo pascal?

Oui.. mais pas mal de langages ont un feof() issu de la sémantique du C qui
n'est pas prédictif. Le Pascal est connu pour avoir des pbs avec son EOF()
qui "lit un char en avant sans le manger".



La semantique du C, c'est on tente la lecture, si elle a echoue on
classifie avec feof/ferror. (C++ c'est la meme chose).

La semantique du Pascal, c'est on a un eof predictif -- c'est visiblement
plus intuitif que celle du C a voir le nombre de personnes qui essayent
d'utiliser feof avec cette semantique -- ca fonctionne pas mal sur les
fichiers, mais l'effet est perturbant dans le cas de peripherique
interactif.

> - ne permet pas de détecter une erreur de lecture (fgetc retourne EOF
> mais feof est faux et ferror est vrai)

Normal, ca ne testes que la fin de fichier. Une seule chose par fonction
me semble être un truc pas mal. Comme tu l'indiques, pour les erreurs il
y a ferror().

> - si j'ai bonne mémoire, feof peut être vrai sans que le résultat de
> fgetc() soit EOF (simplement l'entrée suivant échouera pour cause de fin
> de fichier)

C'est pas logique, tu décris un feof() prédictif.



Non, car si feof implique que la lecture qui suit va echouer pour cause de
fin de fichier, !feof n'implique pas que la lecture va reussir.

> - cette forme ne s'etends pas aux autres fonctions d'I/O (pour lesquelles
> je suis sûr du point précédent)

Les io ailleurs que stdio? Parce que feof() doit marcher sur tout FILE*,
donc ca marche avec fread() aussi par ex.



fgets() et fscanf() peuvent reussir et mettre feof() a vrai

> - ce n'est pas idiomatique et il faut donc réfléchir plus

A te lire, je me demande bien pourquoi ils ont crées feof() si il ne faut
pas trop l'utiliser. Bon c'est peut être une question de gout.



Je ne sais pas non plus. En pratique, chaque fois que je l'ai vu employe en
dehors de discussions sur son usage, c'etait une erreur.

A+

--
Jean-Marc
FAQ de fclc: http://www.levenez.com/lang/c/faq
Site de usenet-fr: http://www.usenet-fr.news.eu.org
Avatar
Antoine Leca
Samuel DEVULDER écrivit :
C'est pas faux, mais quand on voit l'écriture "fonctionnelle" d'Antoine,
avec une fonction fin prenant le flux en argument (et pas le char/int),
moi ça me fait penser immédiatement à feof().



Voilà. Et c'est d'ailleurs pour cela que j'ai écrit imméditement en
dessous qu'en C, cela ne s'écrivait pas comme une fonction arbitraire,
mais en utilisant EOF.


Par ailleurs l'écriture suivante:

char c = (char)fgetc(FLUX);
if(feof(FLUX)) break;

Me semble claire, et assez proche des API des autres langages qui ont
une fonctionnalité type feof.



... et ne marche pas en C parce qu'elle ne gère pas les cas d'erreurs
d'E/S, et qu'elle n'essaie pas réellement de demander au système si on
est à la fin du fichier (elle ne fait que relire l'état précédent).
De plus, fonctionnellement il manque quelque chose au code ci-dessus, il
lit le dernier caractère mais n'en fait rien et sort immédiatement de la
boucle.

Bref, c'est pas du C.


Il est ainsi plus simple de lire un code où la fin de fichier
se détecte via feof() plutot que de tantôt comparer le code de retour à
EOF, à 0, à -1 ou à NULL.



Si c'est pour faire une critique sur le manque d'orthogonalité de la
bibliothèque standard, je ne te contredirais pas, et cela ne s'arrête
pas à stdio d'ailleurs. Clairement la bibliothèque standard du C a été
écrite en marchant, au fur et à mesure des besoins ; l'inconvénient par
rapport à une bibliothèque parfaite inventée d'un coup par un aréopage
c'est le manque d'orthogonalité, l'avantage c'est que l'on est sûr que
cela peut fonctionner ; et avec le langage C tu as choisi ton camp.


Antoine
Avatar
Antoine Leca
écrivit :
Autrement je fais beaucoup de recherches et peut-être, je peux tomber
sur quelque chose qui n'est pas très à jour. Mais je serais curieux de
savoir pourquoi ça n'a existé que sur un système et pourquoi ça
n'existe plus mais après c'est vrai que je m'éloigne du sujet.



En supposant que tu fais référence aux fonctions "BIOS" du PC...
Cela n'existe plus car le BIOS et MS-DOS sont des systèmes mono-tâche :
pendant que ton programmes attend que tu appuies une touche sur le
clavier, l'ordinateur ne fait rien d'autre, même pas regarder le trafic
sur le réseau, pas même finir d'imprimer, etc. Et quand il s'agit de
lire une trame sur le réseau, il ne fait rien d'autre, pas même lire le
clavier pour voir si tu as tapé Ctrl-C pour l'empêcher d'attendre une
heure une trame qui ne viendra parce tu as arraché le câble par mégarde
(la seule solution dans ce cas, c'est de réinitialiser l'ordinateur).

Comme le BIOS est conçu uniquement pour démarrer l'ordinateur, ce n'est
pas un problème dans la pratique d'avoir à redémarrer en cas de problème
inattendu ; par contre dans la vie courante, c'est vite insupportable.


Antoine
Avatar
david.remacle
Antoine Leca wrote:

Bonjour,

[...]

En plus, il semble que bpascal étudie sur une machine Linux en s'aidant
d'un livre écrit pour MSDOS. J'ai donc essayer d'attirer son attention
sur le fait qu'il doive faire l'effort de s'abstraire à ce niveau.
Et se concentrer sur les seules choses qui importent, sans chercher à
essayer d'utiliser l'assembleur ou les tampons ou je-ne-sais-quoi.




Justement, quel livre (ou site) a par le K&R pour apprendre a programmer
en C sur Unix/Linux ?

Merci
1 2 3 4 5