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

1 2 3 4 5
Avatar
Laurent Deniau
Jean-Marc Bourguet wrote:
Laurent Deniau writes:


En l'occurrence, compiler en C++ est souvent un bon moyen de
découvrir des problèmes.


Alors je crois que tu t'avances un peu.



Nous venons de recompiler un gros programme (plusieurs dizaines de
millions de ligne de code) mixte fortran, c, c++ en compilant le c et
le c++ avec le compilateur c++. A ma connaissance, aucun probleme n'a
ete du a un changement de comportement silencieux entre c et c++.

Il a fallu changer des noms, utiliser const de maniere plus rigoureuse
(le C date parfois d'avant 89), etre plus rigoureux dans les pointeurs
sur fonction,... Mais aucun changement de comportements silencieux


Tu veux dire que:

- pas de struct qui porte le meme nom qu'une variable ou un typedef (le
probleme peut etre silencieux et tres vicieux).
- pas de reutilisation de struct declaree dans une struct.
- vous n'avez aucune fonction sans argument (void).
- pas d'enum.
- pas de goto.
- pas de variable const globale.
- pas de void*.
- ...

Vous devez avoir un standard de codage tres tres strict. Ils ont ete
testes dans le details ces millions de lignes de code? Honnetement, si
tout marche bien j'aimerais savoir pour ma culture combien de mois/homme
ont ete necessaires (inclus le developpement d'outils de conversion le
cas echeant).

(quelques problemes a cause de changements faits trop vite -- scripts
ne prevoyant pas certains cas principalement -- mais c'est autre
chose) et quelques problemes existants reveles.


Ce qui revient a ce que je disais.

Question stupide. Pourquoi prendre le risque de compiler la partie C
d'un projet de cette taille avec un compilateur C++?

a+, ld.



Avatar
Charlie Gordon
"Laurent Deniau" wrote in message
news:cmd5a5$hgm$

Tu veux dire que:

- pas de struct qui porte le meme nom qu'une variable ou un typedef (le
probleme peut etre silencieux et tres vicieux).


l'utilisation d'une syntaxe spécifique pour les tags de structure évite ce genre
de choses.
pour ma part, il m'arrive souvent d'écrire :
typedef struct toto { ... } toto;
est-ce incorrect en C++ ?

- pas de reutilisation de struct declaree dans une struct.
- vous n'avez aucune fonction sans argument (void).


quel est le problème ?

- pas d'enum.


pareil ?

- pas de goto.


s'il y a que le compilateur C++ rejette, c'est sans doute qu'il faut fixer le
code C aussi.

- pas de variable const globale.


en C il est plus courant de faire des macros ou des enums justement.

- pas de void*.


ou alors proprement castés ? Le C++ fait bien chier avec ça !

Question stupide. Pourquoi prendre le risque de compiler la partie C
d'un projet de cette taille avec un compilateur C++?


Il n'y a pas de risques à compiler, au pire on perdra un peu de temps avec des
warnings ou des erreurs imaginaires, mais il est probable que certains d'entre
eux seront utiles. Quant à utiliser le code produit, ce qui est risqué, c'est
de ne pas avoir de procédure de validation sérieuse qui bien que sans doute
imparfaite permettra de détecter les problèmes graves.

Chqrlie.

Avatar
Jean-Marc Bourguet
Laurent Deniau writes:

Jean-Marc Bourguet wrote:
Laurent Deniau writes:

En l'occurrence, compiler en C++ est souvent un bon moyen de
découvrir des problèmes.


Alors je crois que tu t'avances un peu.
Nous venons de recompiler un gros programme (plusieurs dizaines de

millions de ligne de code) mixte fortran, c, c++ en compilant le c et
le c++ avec le compilateur c++. A ma connaissance, aucun probleme n'a
ete du a un changement de comportement silencieux entre c et c++. Il a
fallu changer des noms, utiliser const de maniere plus rigoureuse
(le C date parfois d'avant 89), etre plus rigoureux dans les pointeurs
sur fonction,... Mais aucun changement de comportements silencieux


Tu veux dire que:

- pas de struct qui porte le meme nom qu'une variable


Je ne vois pas de probleme silencieux.

ou un typedef (le probleme peut etre silencieux et tres vicieux).


Quand un typedef avait le meme identifieur que le tag d'une struct,
c'etait un typedef sur la struct. Donc pas de probleme.

- pas de reutilisation de struct declaree dans une struct.


Non.

- vous n'avez aucune fonction sans argument (void).
- pas d'enum.
- pas de goto.
- pas de variable const globale.
- pas de void*.
- ...


A quels problemes *silencieux* fais-tu allusion?

Vous devez avoir un standard de codage tres tres strict.


Malheureusement non.

Ils ont ete testes dans le details ces millions de lignes de code?


Pas mal. Nos tests (ceux de la R&D) ne couvrent certainement pas
assez, mais quand meme pas mal. Plus les tests de la validation, plus
les tests de beta (mais on n'y est pas encore, le changement a ete
fait il y a 4 ou 5 mois et le produit ne sera pas chez les clients
avant 6 mois -- c'est naturellement quelque chose qui a ete fait au
debut d'un cycle).

Honnetement, si tout marche bien j'aimerais savoir pour ma culture
combien de mois/homme ont ete necessaires (inclus le developpement
d'outils de conversion le cas echeant).


Aucune idee.

(quelques problemes a cause de changements faits trop vite --
scripts ne prevoyant pas certains cas principalement -- mais c'est
autre chose) et quelques problemes existants reveles.


Ce qui revient a ce que je disais.



Question stupide. Pourquoi prendre le risque de compiler la partie C
d'un projet de cette taille avec un compilateur C++?


Pas ma decision et je n'etais pas implique. De plus les gens que je
frequente et qui etaient impliques n'etaient pas d'accord. Une
presentation des arguments par quelqu'un qui n'est pas convaincu et
qui n'a eu connaissance de ces arguments que par des gens non
convaincus n'est vraissemblablement pas significative. Une des
raisons donc est qu'on a remplace un composant d'assez bas niveau par
quelque chose ecrit en C++ et qu'il y a un desir de se passer de la
couche presentant l'interface C du composant precedant (pour des
raisons de perf et d'acces a des possibilites supplementaires). Il y
a aussi un desir de restructurer des choses en utilisant les
possibilites d'abstraction supplementaires du C++.

Ce que je voulais souligner c'est que le nombre des constructions
valides C aussi valides en C++ avec un sens different est en pratique
bien inferieur au nombre de problemes qu'on trouve faisant passer le
code avec un compilateur C++ et en corrigeant les incompatibilites
qu'il signale. Il est possible qu'il y en ait que je n'ai pas sur --
nous sommes trop nombreux apres tout pour que tout me revienne surtout
que j'etais pas implique -- mais je suis suffisemment proche de gens
impliques pour que si ca avait ete l'inverse j'ai ete mis au courant
-- au pire par des avertissements d'eviter d'utiliser certaines choses
quand on touche a la version qui est encore en C.

A+

--
Jean-Marc
FAQ de fclc: http://www.isty-info.uvsq.fr/~rumeau/fclc
Site de usenet-fr: http://www.usenet-fr.news.eu.org




Avatar
Laurent Deniau
Charlie Gordon wrote:
"Laurent Deniau" wrote in message
news:cmd5a5$hgm$


Tu veux dire que:

- pas de struct qui porte le meme nom qu'une variable ou un typedef (le
probleme peut etre silencieux et tres vicieux).



l'utilisation d'une syntaxe spécifique pour les tags de structure évite ce genre
de choses.


Oui, c'est ce que j'inclus dans le standard de codage "strict".

pour ma part, il m'arrive souvent d'écrire :
typedef struct toto { ... } toto;


mon prefere ;-)

est-ce incorrect en C++ ?


Oui. struct toto; fait deja de toto un type global a la TU au meme titre
que class toto;. Le typedef est redondant.

- pas de reutilisation de struct declaree dans une struct.
- vous n'avez aucune fonction sans argument (void).



quel est le problème ?


parce que int f(void) se declare int f() en C++.



- pas d'enum.



la semantique differe (taille et type).

- pas de goto.



s'il y a que le compilateur C++ rejette, c'est sans doute qu'il faut fixer le
code C aussi.


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

- pas de variable const globale.



en C il est plus courant de faire des macros ou des enums justement.


question de gout. les macros beaucoup n'aime pas (ce n'est pas mon
cas!), les enum posent d'autres problemes.

- pas de void*.



ou alors proprement castés ? Le C++ fait bien chier avec ça !


Yep. Donc tu as programme dans l'optique d'etre compatible C++ et tu
perds de l'info en C. Ce n'est pas mon propos.

Question stupide. Pourquoi prendre le risque de compiler la partie C
d'un projet de cette taille avec un compilateur C++?



Il n'y a pas de risques à compiler, au pire on perdra un peu de temps avec des
warnings ou des erreurs imaginaires, mais il est probable que certains d'entre
eux seront utiles. Quant à utiliser le code produit, ce qui est risqué, c'est


Meme si BS dit que le compilateur devrait detecter la majeure partie des
problemes (et donc il ne faut surtout pas ignorer les warnings), je ne
suis pas sur que ce soit si simple. En plus la semantique des
temporaires est differente en C et en C++ et tu pourrais avoir des
surprises sur des rvalues en C qui peuvent devenir des lvalues en C++
(la non plus je n'ai pas d'idee de cas).

de ne pas avoir de procédure de validation sérieuse qui bien que sans doute
imparfaite permettra de détecter les problèmes graves.


Je ne comprends toujours pas pourquoi il ne compile pas le code C avec
un compilateur C. Pourquoi n'utiliserait-il pas aussi un compilateur
Objective-C dans ce cas (qui est encore plus compatible et possede moins
de mot clef reserve)?

a+, ld.


Avatar
K. Ahausse
"Jean-Marc Bourguet" a écrit dans le message de
news:
Laurent Deniau writes:

Jean-Marc Bourguet wrote:

- pas de struct qui porte le meme nom qu'une variable
ou un typedef (le probleme peut etre silencieux et tres vicieux).



L'horreur ! Même en C, AMHA, c'est une pratique à déconseiller.


- pas de reutilisation de struct declaree dans une struct.


Non.

- vous n'avez aucune fonction sans argument (void).
- pas d'enum.
- pas de goto.
- pas de variable const globale.
- pas de void*.
- ...


A quels problemes *silencieux* fais-tu allusion?


Et même les non-silencieux ! J'aimerais bien en savoir plus sur les PB qui
sont évoqués.


Avatar
Anthony Fleury
Charlie Gordon wrote:

"Laurent Deniau" wrote in message
news:cmd5a5$hgm$

Tu veux dire que:

- pas de struct qui porte le meme nom qu'une variable ou un typedef (le
probleme peut etre silencieux et tres vicieux).



Il sera pas silencieux longtemps à mon avis.

l'utilisation d'une syntaxe spécifique pour les tags de structure évite ce
genre de choses.
pour ma part, il m'arrive souvent d'écrire :
typedef struct toto { ... } toto;
est-ce incorrect en C++ ?


Non ce n'est pas incorrect. C'est par contre inutile étant donné que dans un
programme C++ une fois définie :

struct toto { ... };
On peut directement utiliser toto comme type. Pas la peine de passer par le
typedef.

- pas de reutilisation de struct declaree dans une struct.



Déjà en C je le fais pas personnellement... Mais c'est peut être par
habitude à la notion d'objet, je considère que la structure interne est un
objet donc je la définis avant et ensuite je l'utilise par son ptit nom.
Et pour le problème c'est celui ci :

struct A {
...
struct B {
...
};
...
};

struct B une_variable_de_type_B;

Ce code est valide en C mais pas en C++. En C++ on devrait écrire :
A::B une_variable_de_type_B;

- vous n'avez aucune fonction sans argument (void).


quel est le problème ?


Je n'en vois pas vraiment mis à part pour le contrôle des types. Le C
considérera par exemple si il a un prototype T foo(); que foo peut recevoir
un nombre non indiqué d'argument, et T foo(void); est requis pour que la
fonction ne prenne aucun argument. C'est pas le cas en C++, T foo(); ne
pourra recevoir aucun argument. (Mais de toute facon c'est déjà pas beau en
C alors pourquoi l'autoriser en C++ ?)

- pas d'enum.


pareil ?


Contrôle de type plus sévère. Exemple :

enum A { B = 0, C = 1, D = 42 };

int main() {
A a;
a = 42;
}

est invalide en C++ car la dernière ligne tente une conversion de int vers A
qui n'est pas définie. Faut donc utiliser les symboles et non les valeurs.
En C par contre on a le droit. Par contre en C on devra écrire enum A a; ou
mettre un typedef. Le seul autre truc que je vois avec enum c'est la taille
d'une enum qui est int en C et au choix du compilateur en C++, mais ca
c'est pas un problème à ma connaissance.

- pas de goto.
s'il y a que le compilateur C++ rejette, c'est sans doute qu'il faut fixer

le code C aussi.


Oui et de toute facon les goto en C[++] c'est mal © ® (TM)

- pas de void*.
ou alors proprement castés ? Le C++ fait bien chier avec ça !



Ca c'est clair ! En C (cf malloc) il est rare de mettre le cast.

Anthony
--
Alan Turing thought about criteria to settle the question of whether
machines can think, a question of which we now know that it is about as
relevant as the question of whether submarines can swim.
-- Dijkstra


Avatar
Jean-Marc Bourguet
Laurent Deniau writes:

est-ce incorrect en C++ ?


Oui. struct toto; fait deja de toto un type global a la TU au meme titre
que class toto;. Le typedef est redondant.


Ce n'est pas idiomatique, c'est du C++ correct.

- pas de reutilisation de struct declaree dans une struct.
- vous n'avez aucune fonction sans argument (void).
quel est le problème ?



parce que int f(void) se declare int f() en C++.


A nouveau, pas idiomatique mais correct.

A+

--
Jean-Marc
FAQ de fclc: http://www.isty-info.uvsq.fr/~rumeau/fclc
Site de usenet-fr: http://www.usenet-fr.news.eu.org



Avatar
Laurent Deniau
Jean-Marc Bourguet wrote:
Laurent Deniau writes:
Jean-Marc Bourguet wrote:
Laurent Deniau writes:
En l'occurrence, compiler en C++ est souvent un bon moyen de
découvrir des problèmes.


Alors je crois que tu t'avances un peu.


Nous venons de recompiler un gros programme (plusieurs dizaines de
millions de ligne de code) mixte fortran, c, c++ en compilant le c et
le c++ avec le compilateur c++. A ma connaissance, aucun probleme n'a
ete du a un changement de comportement silencieux entre c et c++. Il a
fallu changer des noms, utiliser const de maniere plus rigoureuse
(le C date parfois d'avant 89), etre plus rigoureux dans les pointeurs
sur fonction,... Mais aucun changement de comportements silencieux


Tu veux dire que:

- pas de struct qui porte le meme nom qu'une variable
Je ne vois pas de probleme silencieux.



Extrait du TC++PL3:

A structure name declared in an inner scope can hide the name of an
object, function, enumeration, or type in an outer scope. For example:

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

ou un typedef (le probleme peut etre silencieux et tres vicieux).



Quand un typedef avait le meme identifieur que le tag d'une struct,
c'etait un typedef sur la struct. Donc pas de probleme.


Si ca compile pas en C++ et c'est legal (voir courant) en C.

- pas de reutilisation de struct declaree dans une struct.



Non.


normal, c'est de mauvais gout ;-)

- vous n'avez aucune fonction sans argument (void).
- pas d'enum.
- pas de goto.
- pas de variable const globale.
- pas de void*.
- ...



A quels problemes *silencieux* fais-tu allusion?


Pour la plupart ils ne sont pas silencieux mais demande du travail.

cf mon autre post pour les problemes

Vous devez avoir un standard de codage tres tres strict.



Malheureusement non.


Ils ont ete testes dans le details ces millions de lignes de code?



Pas mal. Nos tests (ceux de la R&D) ne couvrent certainement pas
assez, mais quand meme pas mal. Plus les tests de la validation, plus
les tests de beta (mais on n'y est pas encore, le changement a ete
fait il y a 4 ou 5 mois et le produit ne sera pas chez les clients
avant 6 mois -- c'est naturellement quelque chose qui a ete fait au
debut d'un cycle).


Donc c'est un processus long et lourd. Ce n'est pas une recompilation a
la legere...

Question stupide. Pourquoi prendre le risque de compiler la partie C
d'un projet de cette taille avec un compilateur C++?



Pas ma decision et je n'etais pas implique. De plus les gens que je
frequente et qui etaient impliques n'etaient pas d'accord. Une


Arf, j'imagine.

presentation des arguments par quelqu'un qui n'est pas convaincu et
qui n'a eu connaissance de ces arguments que par des gens non
convaincus n'est vraissemblablement pas significative. Une des
raisons donc est qu'on a remplace un composant d'assez bas niveau par
quelque chose ecrit en C++ et qu'il y a un desir de se passer de la


Il aurait ete peut-etre moins couteux de faire une interface au code C++
specialisee pour le C. Apres tout, votre code C n'utilise pas des
templates C++, il faut donc une specialisation qque part. Ou alors vous
incluez des headers C++ dans le TU ecrite en C et vous compilez le tout
en C++. C'est encore plus dangereux alors (notament cas du goto)...

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?

couche presentant l'interface C du composant precedant (pour des
raisons de perf et d'acces a des possibilites supplementaires). Il y


perf? restructuration et simplication surement.

a aussi un desir de restructurer des choses en utilisant les
possibilites d'abstraction supplementaires du C++.


il n'y aurait pas un facteur marketing derriere tout ca?

a+, ld.





Avatar
Anthony Fleury
Laurent Deniau wrote:

Jean-Marc Bourguet wrote:

Quand un typedef avait le meme identifieur que le tag d'une struct,
c'etait un typedef sur la struct. Donc pas de probleme.


Si ca compile pas en C++ et c'est legal (voir courant) en C.


Ca m'a pourtant l'air de compiler en C++. En fait je suis dans ma tête
pratiquement sûr que c'est légal, mais je n'ai pas la norme et je ne vois
aucune ligne dans TC++PL qui l'interdit ou le légalise. Typedef est
présenté avant struct dans TC++PL et comme de toute facon ce typedef est
inutile, il n'a pas de raisons de le mentionner.

J'ai donc testé avec Comeau Online en mode strict C++ qui ne me dit rien. Ca
m'a donc l'air légal !

A quels problemes *silencieux* fais-tu allusion?


Pour la plupart ils ne sont pas silencieux mais demande du travail.
cf mon autre post pour les problemes



Je ne sais pas si c'est parce que je me suis mis au C++ un peu plus
sérieusement et donc ne suis plus vraiment objectif sur ce sujet, mais je
trouve que tous les exemples de codes qui ne fonctionnent pas en C++ et
fonctionnent en C sont du « mauvais C ». (mis à part le cast des void*
forcé par le C++)

Anthony
--
Alan Turing thought about criteria to settle the question of whether
machines can think, a question of which we now know that it is about as
relevant as the question of whether submarines can swim.
-- Dijkstra


Avatar
Laurent Deniau
Jean-Marc Bourguet wrote:
Laurent Deniau writes:


est-ce incorrect en C++ ?


Oui. struct toto; fait deja de toto un type global a la TU au meme titre
que class toto;. Le typedef est redondant.



Ce n'est pas idiomatique, c'est du C++ correct.


oui, c'est ce que je veux dire par "silencieux". Je viens de
m'appercevoir que mon "Oui" disait "Oui c'est incorrect".

- pas de reutilisation de struct declaree dans une struct.
- vous n'avez aucune fonction sans argument (void).


quel est le problème ?


parce que int f(void) se declare int f() en C++.



A nouveau, pas idiomatique mais correct.


juste.

a+, ld.




1 2 3 4 5