OVH Cloud OVH Cloud

Vider le buffer associe a stdin

98 réponses
Avatar
korchkidu
Bonjour,

je me pose une question par rapport a la maniere classique de vider le
buffer associe a stdin:

c = getchar();
if (c != ’\n’)
while ( (getchar()) != ’\n’) {
};

Que se passe t-il si stdin ne contient aucun \n? (fichier contenant une
ligne mais aucun \n par exemple). Dans ce cas, il me semble que l'on
pourrait avoir un probleme non?

Comment feriez vous pour resoudre ce probleme? (J'ai bien une petite
idee mais je prefere savoir si c'est la bonne..;) )

Merci d'avance pour vos reponses,
K.

10 réponses

Avatar
K. Ahausse
"Antoine Leca" a écrit dans le message de
news:418a66e5$0$30221$
En 418a5531$0$23274$, K. Ahausse va escriure:
- pas de goto.




le PB en C++ le voilà :

int toto (void)
{
int A=0 ;
goto Fin ;

int B = 0 ;

Fin:
return A ;
}


C'est un problème ? Pour qui ?

Si un compilo C a mangé cela sans broncher, c'est qu'il est franchement
récent, donc le source l'est encore plus, ce qui n'est pas le cas évoqué
par

Jean-Marc.



Heu... c'est un peu confus comme fil, effectivement.

Je voulais apporter une précision sur l'utilisation de goto en C++ suite à
un post de Laurent Deniau, je cite :

"goto en C est un vrai saut, en C++ il fait des choses en plus (il ne
saute pas les initialisations presentent entre le goto et le label). Je
n'ai pas d'exemple en tete ou cela peut poser probleme, mais il y en a
surement (et des vicieux je pense)."

Donc cet exemple est compilé avec un compilateur C++.

Est-ce un problème ? A mon avis pas vraiment .





Avatar
Laurent Deniau
Gabriel Dos Reis wrote:
Laurent Deniau writes:

| Jean-Marc Bourguet wrote:
| > Laurent Deniau writes:
| >>Une question au hasard. Vous gerez comment les exceptions dans votre
| >>code C avec tous ses pointeurs et ses mallocs (ou wrapper
| >>equivalent) si vous avez du C++ comme couche bas niveau du C?
| > Simple: si des exceptions s'echappent de la couche d'interface, il y
| > a
| > un probleme dans celles-ci. Si le code qui se met a utiliser le
| > composant directement n'est pas modifie pour intercepter les
| > exceptions possibles, il y a un probleme dans la modif.
|
| Tu veux dire que toutes les methodes C++ de votre couche bas niveau
| sont qualifiees avec throw(). A ma connaissance ce n'est pas bon pour
| les perfs sauf compilo tres efficace sur un try.

Pardon ?

(Glibc est bourré de throw() et le compilateur optimise à base de ça).


tu veux dire que le cas particulier de throw() vide est mieux optimise
que de mettre le corps de la fonction dans un try{}catch(...){} ?

tu peux m'en dire plus (peut-etre sur f.c.l.c++)? je suis interesse...

a+, ld.

Avatar
Charlie Gordon
"Gabriel Dos Reis" wrote in message
news:
Jean-Marc Bourguet writes:

| Laurent Deniau writes:
|
| > int x[99];
| > void f()
| > {
| > struct x { int a; };
| > sizeof(x); /* size of the array in C, size of the struct in C++ */
| > }
|
| Ah oui. Apparemment ce n'est pas tombe. Faut dire qu'il doit pas y
| avoir beaucoup de definition de struct locales a des fonctions et
| que la plupart des utilisations doivent entrainer un diagnostic. (Si
| on utilise sizeof(x), il y a des chances qu'on utilise le x originel
| aussi et ca va clasher. Ok, il doit y avoir moyen de batir quelque
| chose de plus ou moins vraissemblable mais c'est rare).

Je crois que le fond de la question est pourquoi il y a cette
différence. Par exemple, les deux codes suivants ont la même
siginification en C et en C++.

struct x { int a; };
void f()
{
int x[99];
sizeof(x); // size of the array "x" in C and C++
}


void g()
{
int x[99];
struct x { int a; };
sizeof(x); // size of the array "x" in C and C++
}



C'est vraiment dégueu comme pratique, un compilateur décent devrait pouvoir être
configuré pour protester sur de telles horreurs (un warning, bien sûr).
D'ailleurs les compilateurs C++ sont-ils capables de détecter les constructions
dont la semantique diffère entre C et C++ et emettre au besoin un warning de
compatibilité ? Cela mettrait tout le monde d'accord et favoriserait la
portabilité entre C et C++.

Chqrlie.

Avatar
Gabriel Dos Reis
Laurent Deniau writes:

| Gabriel Dos Reis wrote:
| > Laurent Deniau writes:
| > | Jean-Marc Bourguet wrote:
| > | > Laurent Deniau writes:
| > | >>Une question au hasard. Vous gerez comment les exceptions dans votre
| > | >>code C avec tous ses pointeurs et ses mallocs (ou wrapper
| > | >>equivalent) si vous avez du C++ comme couche bas niveau du C?
| > | > Simple: si des exceptions s'echappent de la couche d'interface, il y
| > | > a
| > | > un probleme dans celles-ci. Si le code qui se met a utiliser le
| > | > composant directement n'est pas modifie pour intercepter les
| > | > exceptions possibles, il y a un probleme dans la modif.
| > | | Tu veux dire que toutes les methodes C++ de votre couche bas
| > niveau
| > | sont qualifiees avec throw(). A ma connaissance ce n'est pas bon pour
| > | les perfs sauf compilo tres efficace sur un try.
| > Pardon ?
| > (Glibc est bourré de throw() et le compilateur optimise à base de
| > ça).
|
| tu veux dire que le cas particulier de throw() vide est mieux optimise
| que de mettre le corps de la fonction dans un try{}catch(...){} ?

Si tu appelles une fonction avec throws(), tu sais qu'au site d'appel,
il n'y aura pas d'exception -- si la fonction essaie d'en lever une
(dans le corps de la fonction), il y a abort(). Donc, au site d'appel
le compilateur ne génère plus du code pour traiter les exceptions
inattendus (destruction des objets déjà construit et toussa).

Par contre si tu places l'appel explicitement dans try/catch, le
compilateur est obligé de dupliquer du code (tests et branchements)
au site d'appel -- et dans certains cas empêcher certaines
optimisations.

|
| tu peux m'en dire plus (peut-etre sur f.c.l.c++)? je suis interesse...
|
| a+, ld.

--
Gabriel Dos Reis

Texas A&M University -- Department of Computer Science
301, Bright Building -- College Station, TX 77843-3112
Avatar
Gabriel Dos Reis
"Charlie Gordon" writes:

| "Gabriel Dos Reis" wrote in message
| news:
| > Jean-Marc Bourguet writes:
| >
| > | Laurent Deniau writes:
| > |
| > | > int x[99];
| > | > void f()
| > | > {
| > | > struct x { int a; };
| > | > sizeof(x); /* size of the array in C, size of the struct in C++ */
| > | > }
| > |
| > | Ah oui. Apparemment ce n'est pas tombe. Faut dire qu'il doit pas y
| > | avoir beaucoup de definition de struct locales a des fonctions et
| > | que la plupart des utilisations doivent entrainer un diagnostic. (Si
| > | on utilise sizeof(x), il y a des chances qu'on utilise le x originel
| > | aussi et ca va clasher. Ok, il doit y avoir moyen de batir quelque
| > | chose de plus ou moins vraissemblable mais c'est rare).
| >
| > Je crois que le fond de la question est pourquoi il y a cette
| > différence. Par exemple, les deux codes suivants ont la même
| > siginification en C et en C++.
| >
| > struct x { int a; };
| > void f()
| > {
| > int x[99];
| > sizeof(x); // size of the array "x" in C and C++
| > }
| >
| >
| > void g()
| > {
| > int x[99];
| > struct x { int a; };
| > sizeof(x); // size of the array "x" in C and C++
| > }
| >
|
| C'est vraiment dégueu comme pratique, un compilateur décent devrait pouvoir être

Je ne dis pas que c'est une bonne pratique. Je montre ces exemples,
seulement parce que j'avais l'impression qu'il y avait une certaine
confusion en ce qui concerne la visibilité des noms de tag et des noms
de nontags.

| configuré pour protester sur de telles horreurs (un warning, bien sûr).

Dans ce cas, tu vas alors protester sur beaucoup de codes C. Un
certain nombre de programmeurs mettent un point d'honneur à écrire des
choses comme ça (tu te souviens de struct stat et de la fonction stat()?).

Dans GCC, j'ai dû batailler ferme -- mais il y a encore des restes :-(

| D'ailleurs les compilateurs C++ sont-ils capables de détecter les constructions
| dont la semantique diffère entre C et C++ et emettre au besoin un warning de
| compatibilité ?

Les compilateurs sont capables de le faire, dans la plupart des cas.
Mais est-ce que cela vaut vraiment la peine ?

| Cela mettrait tout le monde d'accord et favoriserait la
| portabilité entre C et C++.

-- Gaby
Avatar
Laurent Deniau
Gabriel Dos Reis wrote:
Laurent Deniau writes:

| Gabriel Dos Reis wrote:
| > Laurent Deniau writes:
| > | Jean-Marc Bourguet wrote:
| > | > Laurent Deniau writes:
| > | >>Une question au hasard. Vous gerez comment les exceptions dans votre
| > | >>code C avec tous ses pointeurs et ses mallocs (ou wrapper
| > | >>equivalent) si vous avez du C++ comme couche bas niveau du C?
| > | > Simple: si des exceptions s'echappent de la couche d'interface, il y
| > | > a
| > | > un probleme dans celles-ci. Si le code qui se met a utiliser le
| > | > composant directement n'est pas modifie pour intercepter les
| > | > exceptions possibles, il y a un probleme dans la modif.
| > | | Tu veux dire que toutes les methodes C++ de votre couche bas
| > niveau
| > | sont qualifiees avec throw(). A ma connaissance ce n'est pas bon pour
| > | les perfs sauf compilo tres efficace sur un try.
| > Pardon ?
| > (Glibc est bourré de throw() et le compilateur optimise à base de
| > ça).
|
| tu veux dire que le cas particulier de throw() vide est mieux optimise
| que de mettre le corps de la fonction dans un try{}catch(...){} ?

Si tu appelles une fonction avec throws(), tu sais qu'au site d'appel,
il n'y aura pas d'exception -- si la fonction essaie d'en lever une
(dans le corps de la fonction), il y a abort(). Donc, au site d'appel
le compilateur ne génère plus du code pour traiter les exceptions
inattendus (destruction des objets déjà construit et toussa).


Je dois avouez que ton explication me melange un peu les pinceaux. Donc
je vais developper:

cat g.cpp
void f() throw();


void g() { f(); } // site d'appel, pas d'exception possible ici

cat f.cpp
void f() throw();


void f() { // site appelle', possibilite d'une exception
func_qui_peut_lever_une_exception();
}

Je pensais (selon la description du TC++PL3 14.6) que le try-catch
equivalent etait dans le corp de f() autour de l'appel de
func_qui_peut_lever_une_exception(). C'est donc la declaration de void
f() throw() dans f.cpp qui penalise l'efficacite de f() de maniere
generale (pas visible par les autres TU). Je ne pensais pas que g()
aurait egalement du code de protection autour de f() (qui pourrait
effectivement etre optimise) dans g.cpp.

D'autre part, le abort() n'est pas assure si std::unexpected()
std::terminate() sont redefinis, notament si l'utilisateur veut mapper
une exception unexpected sur une exception "expected" (TC++PL3
14.6.3.2). Alors que veux-tu dire par "il y a abort()"?

Je suis d'accord que ce dont tu parles peut s'optimiser si tout est
connu dans la meme TU (f() et g() mais pas necessairement
func_qui_peut_lever_une_exception() par exemple), mais sinon?

Par contre si tu places l'appel explicitement dans try/catch, le
compilateur est obligé de dupliquer du code (tests et branchements)
au site d'appel -- et dans certains cas empêcher certaines
optimisations.


Je ne comprends peut-etre pas ce que tu veux dire par site d'appel. Tu
fais allusion a f() ou g() dans l'exemple ci-dessus.

a+, ld.

Avatar
Emmanuel Delahaye
Charlie Gordon wrote on 04/11/04 :
Au contraire. C'est un bon moyen d'éviter que du code C se retrouve par
erreur compilé en C++, ce qui n'est un giganteste UB.


Ton argument est completement tiré par les cheveux. En l'occurrence,
compiler en C++ est souvent un bon moyen de découvrir des problèmes.


Bof, je préfère un gcc bien reglé, ou un *Lint.

Portable avec quoi ?


Avec C++ justement! Si d'aventure tu devais porter des routines C dans une
appli C++, tu serais bien content de ne pas avoir à aller à la pêche aux
mots-clés.


Il y a de fortes chances que le code C++ soit écrit autrement. Il n'y a
aucun intérêt pratique à ecrire du C et à le faire compiler en C++, à
part créer des incompatibilités gratuites, ce qui amuse un moment... C
et C++ sont 2 langages différents.

Par contre, il m'est arrivé dans un même projet C++ d'utiliser du code
C, mais bien évidemment dans des sources différents, en en encadrant
les declarations de extern "C"...

Mais l'argument principal pour moi est la lisibilité : si le lecteur connait
et pratique le C et le C++, voire d'autres dialectes dérivés, l'utilisation
de


Considérer le C++ comme un dialecte dérivé du C est une grossière
erreur.

mots-clés pour un autre usage ralentit la lecture, voire engendre de
mauvaises interprétations. C est un langage déjà suffisament subtil pour ne
pas rajouter de pièges au lecteur futur.


Je ne connait pas la syntaxe des langages du futur, ta requête est donc
impossible, à moins d'écrire un source d'une taille de exactement 0
caractères, ce qui est d'un intérêt limité (et qui ne compile pas chez
moi). Je n'ai rien à faire des autres langages. Il ne doit y avoir
aucune interaction.

C'est le programmeur qui est beugué, pas la boucle... do-while a son
role (le repeat until du Pascal à une vache près). Il n'y a aucune
raison de ne pas l'utiliser quand c'est utile. Tu as de drôles de
préjugés parfois...


Je cite un exemple de la faq de developpez.com où tu sévis régulièrement
(mais dont tu n'es pas l'auteur) :


Je n'ai aucune responsabilité sur cette FAQ. J'ai commencé à relever
les bugs, et devant l'énormité de la tâche, j'ai créé mon propre site!

--
Emmanuel
The C-FAQ: http://www.eskimo.com/~scs/C-faq/faq.html
The C-library: http://www.dinkumware.com/refxc.html

"C is a sharp tool"


Avatar
Emmanuel Delahaye
K. Ahausse wrote on 04/11/04 :

<goto en C>

Entierement d'accord. Je l'utilise dans le seul cas de gestion d'erreur.


Pareil.

--
Emmanuel
The C-FAQ: http://www.eskimo.com/~scs/C-faq/faq.html
The C-library: http://www.dinkumware.com/refxc.html

"C is a sharp tool"

Avatar
Gabriel Dos Reis
Emmanuel Delahaye writes:

| > Mais l'argument principal pour moi est la lisibilité : si le lecteur
| > connait et pratique le C et le C++, voire d'autres dialectes
| > dérivés, l'utilisation de
|
| Considérer le C++ comme un dialecte dérivé du C est une grossière
| erreur.

C'est un dialecte dérivé directement de « Classic C », effectivement.
Tout comme C90 et C99.

-- Gaby
Avatar
drkm
Emmanuel Delahaye writes:

Par contre, il m'est arrivé dans un même projet C++ d'utiliser du code
C, mais bien évidemment dans des sources différents, en en encadrant
les declarations de extern "C"...


Avec des mots-clefs C++-iens ?

--drkm