Twitter iPhone pliant OnePlus 11 PS5 Disney+ Orange Livebox Windows 11

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
bpascal123
On 20 juin, 20:37, xtof pernod wrote:
Le 20/06/2010 20:53, a fait rien qu'à écrir e:

> Par hasard, ce code ne fonctionne pas sous linux distro ubuntu...

En effet, il est prévu pour MS-DOS.. aucune chance que ça passe --
même pas à la compil'. Pas de hasard là-dedans =)

> (j'essaie de m'intéresser à ce qui se passe "sous le rideau", la
> réponse précédente (Marc E.) est intéressante pour ça. Cdt.

Bon, Marc.. Tu as un double appel.

> #include <stdio.h>
> #include <bios.h>

            ^^^^^^^^

> main()
> {
>    unsigned int saisie;
>    int carlu, scancode;
>    printf ("Press a key:n");
>    saisie = _bios_keybrd(_KEYBRD_READ); // <- Hum. accès au bio s en mode réel/16 bits
>    carlu = saisie &  255;
>    scancode = saisie >>  8;,
>    printf("nScancode : %d Caractere : %cn", scancode, carlu);
> }

Je peux pas nier, c'est rafraîchissant & ça rappelle des vieux
souvenirs.. Tu l'as taupé dans quoi, franchement, dans "la Bible
de la progra. sous DOS" ?

Mais le fait est, tu mets de la verveine de 20 ans d'âge dans ta
limousine de l'année, et tu viens dire "-comprends pas, ça démarre
même pas"..

Si tu as internet, tu devrais pouvoir dégotter des examples plus réce nts
(et plus adaptés à Linux. Au moins du C standard)

--
christophe.



mdr...
cependant comme j'aime le dire, tu ajoutes de l'insulte à la douleur
(aucune idée ou j'ai trouvé ce code...peut-être vers
http://www.niouzes.org/comp-lang-c/292858-aux-contributeurs-5.html
Avatar
bpascal123
On 20 juin, 21:54, Benoit Izac wrote:
Bonjour,

le 20/06/2010 à 20:53, bpascal a écrit dans le message
:

> Je comprends que getchar() renvoie un entier. J'avais vu quelque part
> qu'en déclarant char c = getchar() et plus loin indiquer
> printf("%d",c) on pouvait voir la valeur de EOF...

On s'en fout de sa valeur. Sur tout les systèmes elle vaut « EOF »,
c'est la seule chose qu'il faut retenir.





> Par hasard, ce code ne fonctionne pas sous linux distro ubuntu...
> (j'essaie de m'intéresser à ce qui se passe "sous le rideau", la
> réponse précédente (Marc E.) est intéressante pour ça. Cdt.

> #include <stdio.h>
> #include <bios.h>

> main()
> {
>    unsigned int saisie;
>    int carlu, scancode;
>    printf ("Press a key:n");
>    saisie = _bios_keybrd(_KEYBRD_READ);
>    carlu = saisie & 255;
>    scancode = saisie >> 8;
>    printf("nScancode : %d Caractere : %cn", scancode, carlu);
> }

Tu t'éparpilles. Pourquoi cherches-tu à brûler les étapes ?

Tu devrais prendre le K&R, le lire chapitre par chapitre et faire les
exercices un par un. On peut dire ce que l'on veut à propos de ce livre ,
je pense qu'il est assez bien fait : il avance sur les concepts propres
au langage assez linéairement. Ce qui a été pour ma part le plus d élicat
concerne plus des problèmes de logique que mon cerveau n'était pas
habitué à utiliser mais qui sont indispensables en programmation.

Si tu as un problème pour comprendre un passage ou pour résoudre un
exercice, les intervenants de ce groupe se feront une joie de
t'éclaircir. Énonce clairement (c'est un de tes points faibles) ton
problème et tu verras que bien souvent juste le fait de réfléchir p our
rédiger ton message t'aidera à te poser les bonnes questions.

Une fois que tu auras fini ce livre (attention, ça risque déjà de t e
prendre un certain temps malgré qu'il n'y ai que 182 pages de cours dan s
la version française), tu verras que tu te poseras beaucoup moins de
questions, que tu pourras faire déjà pas mal de choses et tu sauras o ù
chercher pour utiliser des fonctions propres à ton système.

<élucubration>
Par la suite, il te prendra sans soute l'envie d'approfondir le langage
en lisant la norme ; tu pourras déjà venir troller^Wdiscuter ici des
points de détails que tu auras découverts. Tu t'apercevras d'ailleurs
que bien que tout le monde ai lu la même chose, chacun l'interprète
différemment.

Ensuite, tu chercheras à en savoir plus, tu t'attaqueras à un livre u n
peu plus conséquent. Comme tu hésiteras à approfondir tes connaissa nces
en programmation système ou en algorithmique, tu t'attaqueras à Steve n
et Knuth. Ça te demandera encore quelques années pour les assimiler.

À ce moment là, tu t'apercevra que tu ne sauras toujours pas capable
d'écrire ton pilote pour ton périphérique qui aura disparu du march é et
que tu ne souhaiteras plus utiliser. Tu liras LDD édition 7 qui te
permettra de combler tes lacunes. Et enfin tu te mettra à l'assembleur.

Au final, tu pourras te présenter sur le marché du travail. La gentil le
personne au guichet essaiera de t'expliquer avec tact qu'à ton âge et
avec ton expérience professionnelle, il te sera vraiment très diffici le
de trouver un emploi à quelques années de la retraite. Enfin tu
réaliseras (sans doute un peu trop tard) qu'au fond la comptabilité
c'était pas si mal.
</élucubration>

--
Benoit Izac



Pourquoi pas l'écriture d'un driver à titre posthume :) ?

-plus sérieursement : je me donne 2 ou 3 années avant de passer à un
langage "plus simple". Il se peut qu'essayer de comprendre un peu ce
qui se passe sous le capot quand j'appuie sur une touche du clavier ne
me servira pas à grand chose avec d'autres langages (avec des voitures
récentes, c'est inutile de tenter de faire soi-même la vidange) mais
je suis curieux.
Avatar
xtof pernod
Le 21/06/2010 01:23, a fait rien qu'à écrire:
On 20 juin, 20:37, xtof pernod wrote:
Le 20/06/2010 20:53, a fait rien qu'à écrire:
Par hasard, ce code ne fonctionne pas sous linux distro ubuntu...
(...)



Si tu as internet, tu devrais pouvoir dégotter des examples plus récents
(et plus adaptés à Linux. Au moins du C standard)
(...)


mdr...
cependant comme j'aime le dire, tu ajoutes de l'insulte à la douleur



Désolé pour la douleur, c'est pas le but visé; quant aux 'insultes', c'est
juste un retour de bâton: depuis le temps qu'on te dit d'ouvrir un
bouquin et de te focaliser sur un seul truc à la fois..

Tiens, rien que le message suivant () de ce fil:

Tu devrais prendre le K&R, le lire chapitre par chapitre et faire les
exercices un par un.



C'est pas plus compliqué que ça ! Et personne ne peut le faire pour toi.

On peut dire ce que l'on veut à propos de ce livre,
je pense qu'il est assez bien fait



+1


:
(aucune idée ou j'ai trouvé ce code...peut-être vers
http://www.niouzes.org/comp-lang-c/292858-aux-contributeurs-5.html



ah ben voila, si c'est daté du 28/29/58, ça explique tout. bon, ce site
ne répond pas, et n'est pas dans webarchive. Le prochain coup que tu
surfes: essaye de rajouter un autre mot clé, comme 'linux' par ex =)
(Et aussi pdt que j'y suis, apprends à quoter en éliminant le super-flux)

--
christophe.
Avatar
Ael Rowen TERENCE
Je me demande si un petit apprentissage de l'assembleur jusqu'à
comprendre ce code, ne serait pas utile dans ce cas?




T'es complètement à coté de la plaque.
L'assembleur est le langage que je préfère, ... mais ... pour comprendre
l'assembleur il te faudra comprendre un minimum de hard !

Je me range de l'avis de ceux qui te disent de prendre un bouquin sur le C,
et, simplement, de l'étudier.
Surtout : cesser de tout mélanger, le C, la POO, les mobiles, l'assembleur,
HTTP, les capots ...
Avatar
Ael Rowen TERENCE
-plus sérieursement : je me donne 2 ou 3 années avant de passer à un
langage "plus simple". Il se peut qu'essayer de comprendre un peu ce
qui se passe sous le capot quand j'appuie sur une touche du clavier ne
me servira pas à grand chose avec d'autres langages (avec des voitures
récentes, c'est inutile de tenter de faire soi-même la vidange) mais
je suis curieux.



Mais pour comprendre ce qu'il y a sous le capot, il faudrait déjà savoir le
soulever.
Or, toi, pour continuer l'analogie, tu n'as même pas acheter la voiture.

Désolé si je suis un peu brusque : tu me donnes l'idée du singe qui veut
voir derrière la glace.

Comprendre le C est déjà un projet ambitieux ( réalisable malgré tout ),
mais là en te dispersant c'est insensé (au propre comme au figuré).
Avatar
Antoine Leca
bpascal123 écrivit :
Je trouve getchar() assez difficile à comprendre.



Faut dire que tu ne cherches pas à simplifier.

Au lieu de saisir du clavier, getchar lit directement dans la mémoire?
Presser une touche du claver entraine un signal dans le bios qui
"renvoie" ce signal dans le kernel puis dans la mémoire (buffer)


[couic]
Je me demande si un petit apprentissage de l'assembleur jusqu'à
comprendre ce code, ne serait pas utile dans ce cas?



Mauvaise nouvelle : le 6845 qui pilote le clavier, et le 8042 qui pilote
la ligne entre le clavier et l'ordinateur, ne se programme pas en
assembleur mais directement en opérations élémentaires, des 0 et des 1.
En fait, on peut faire long comme ce fil rien qu'avec la description de
ce qui se passe réellement dans le « entraine un signal » ci-dessus !

Mais c'est totalement hors sujet dans ce groupe. Donc il va falloir se
passer de l'assembleur et se concentrer sur le C.


Donc : d'abord, getchar() est un raccourci pour getc(stdin) ; et dans ce
que tu décris, « lire la mémoire » etc., pour ce qui concerne le C il
n'y a pas de différence entre stdin ou un autre flux à ce niveau. Donc
si tu t'intéresses aux mécanismes derrière stdin (cf. description de
Marc), désolé mais les détails ne sont pas du ressort de ce groupe.
La seule chose qui importe, c'est que de ce fait, il n'y a pas en C (de
base) de fonction qui permette d'avoir des détails sur les
particularités liées à l'entrée au clavier, codes des touches, l'heure à
laquelle elles ont été pressées, si l'utilisateur a eu un retour à
l'écran ou pas, etc. : encore une fois, pour tout cela, il faut s'en
remettre à des spécificités du système sur lequel tu programmes
(et il y a là une grande diversité, y compris sur un PC il y a des
grosses différences à ce niveau entre MS-DOS et Linux).


Ensuite, getc() agit sur un tampon (dit de <stdio.h>), pour des raisons
de performances; un des autres avantages de ce mécanisme est la fonction
ungetc(), que ton ouvrage va certainement abordé bientôt (d'où les
notions de « partie ancienne ») mais qui n'est pas le sujet pour le
moment. Au final, le tampon d'entrée-sortie est transparent en lecture,
donc pour le moment on peut négliger totalement cet aspect.


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
C'est-à-dire, que l'on utilise une valeur de retour supplémentaire à la
fonction getc() pour indiquer la condition « fin(FLUX) ». Là, c'est du C
pur et dur, d'autres langages ont des manières de faire différentes.
De plus, cela oblige à utiliser un type de données pour le résultat de
getc() qui permet de distiguer la valeur EOF de toutes les valeurs
possibles pour le caractère suivant du flux : il est donc indispensable
d'utiliser le type int pour déclarer c.


Antoine
Avatar
espie
In article <hvni7k$fh4$,
Antoine Leca wrote:
Donc : d'abord, getchar() est un raccourci pour getc(stdin) ; et dans ce
que tu décris, « lire la mémoire » etc., pour ce qui concerne le C il
n'y a pas de différence entre stdin ou un autre flux à ce niveau. Donc
si tu t'intéresses aux mécanismes derrière stdin (cf. description de
Marc), désolé mais les détails ne sont pas du ressort de ce groupe.
La seule chose qui importe, c'est que de ce fait, il n'y a pas en C (de
base) de fonction qui permette d'avoir des détails sur les
particularités liées à l'entrée au clavier, codes des touches, l'heure à
laquelle elles ont été pressées, si l'utilisateur a eu un retour à
l'écran ou pas, etc. : encore une fois, pour tout cela, il faut s'en
remettre à des spécificités du système sur lequel tu programmes
(et il y a là une grande diversité, y compris sur un PC il y a des
grosses différences à ce niveau entre MS-DOS et Linux).



Oui, et non.

De mon point de vue, pedagogiquement, c'est difficile de comprendre le C
en le separant de ses origines, donc d'Unix. Il y a des tares genre Candide
qui voient ca comme un jeu de logique abstraite, et qui s'amusent a faire
des trucs rien qu'a partir de la norme, mais pour comprendre les choix de
design, c'est vachement utile de savoir que ca a ete fait comme ca parce
qu'au depart, c'etait le langage de base d'Unix.

Apres, bien sur, ca s'est complique, c'est devenu portable ailleurs, et ca
a envahi la planete, mais je pense que le C (et la bibliotheque *STANDARD*)
auraient ete pas mal differents s'ils etaient nes sous dos ou sur amiga.

Evidemment, avec de l'experience, on se refere plus a la norme et un modele
abstrait de la machine. Mais in fine, il y a des tonnes de trucs qui sont
comme ca dans la norme parce que c'etait comme ca sous Unix au depart...
Avatar
Antoine Leca
Marc Espie écrivit :
Oui, et non.

De mon point de vue, pedagogiquement, c'est difficile de comprendre le C
en le separant de ses origines, donc d'Unix.



Je suppose que tu écris cela en référence à
In article <hvni7k$fh4$,
Antoine Leca wrote:
si tu t'intéresses aux mécanismes derrière stdin (cf. description de
Marc), désolé mais les détails ne sont pas du ressort de ce groupe.






Mon propos n'était pas du tout de critiquer ton excellent article dans
le même fil, que d'ailleurs je recommande --dont acte:
<msgid:hvi0lp$1rvp$, ou
<http://groups.google.com/groups?selm=hvi0lp$1rvp$
J'aurais d'ailleurs mauvais gré à le faire, étant souvent coutumier des
dérives hors sujet :-(

Non, mon intention était de préciser les éléments importants à
l'attention de bpascal. Par tant, pour manipuler les entrées en C (au
sens de la norme, pas au sens Posix), il n'y a que <stdio.h>, et le flux
stdin n'a pas de caractéristique particulière. Il n'y a pas de read(),
pas de ioctl(), pas de curses. Et le mécanisme de tampon de stdio est le
plus souvent invisible.

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.


Antoine
Avatar
Samuel DEVULDER
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?

Je pense que bpascal a des pbs pour comprendre l'abstraction. Quand on
programme, et cela quelque que soit le langage on se se preoccupe
quasiment pas de savoir ce qui se passe sous le capot (à part pour la
curiosité intellectuelle).

On utilise ce que fourni le langage et on fait avec l'abstraction du
matériel qu'il présente. Parce que le coup du bios pour lire le clavier
ne marchera pas si tu est dans un contexte qui ne fonctionne pas ainsi
(une applis graphique par exemple ou un telephone portable, ou autre).
Pourtant le code C sera le même dans tous les cas. C'est ton compilo qui
te fourni les implementations de stdio qui vont bien pour le materiel/os
correspondant.

Comprendre ce mécanisme d'abstraction est je crois assez important.
L'idée est de masquer les trucs hyper complexes qui se passent sous le
capots en fournissant une version simplifiée mais largement suffisante
pour faire ce qu'on veut faire au quotidien.

sam.
Avatar
Jean-Marc Bourguet
Samuel DEVULDER writes:

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?



Utiliser feof() n'a guere de sens qu'apres avoir constate qu'une entree a
echoue (donc en ayant compare de resultat de fgetc() a EOF ou de fgets() a
NULL) pour voir si la cause de l'echec est une erreur d'IO ou la fin de
fichier. Et alors, comme on peut avoir les deux ensembles, il vaut mieux
utiliser ferror() qui indiquera s'il s'agit d'une erreur. Donc j'attends
toujours de voir dans quel contexte feof() a du sens.

Lecture par ligne:

while (fgets(s, sizeof s, is) != NULL) {

}
if (ferror(is)) {
/* erreur d'IO */
} else {
assert(feof(is));
/* fin de fichier */
}

Lecture par caractere:

while ( (c = fgetc(is)) != EOF) {
...
}
if (ferror(is)) {
/* erreur d'IO */
} else {
assert(feof(is));
/* fin de fichier */
}

(Et c'est volontairement que je ne propose pas le cas de fscanf()).

A+

--
Jean-Marc
FAQ de fclc: http://www.levenez.com/lang/c/faq
Site de usenet-fr: http://www.usenet-fr.news.eu.org
1 2 3 4 5