Partage
  • Partager sur Facebook
  • Partager sur Twitter

[Atelier Quiz] Question pour un champion (C++)

Atelier du forum C++

2 septembre 2013 à 12:43:44

moi62100 a écrit:

Alors je reprend la main: quel sont les type de std::cout et std::cin ?


Des std::basic_(i/o)stream<char, ...> dont le streambuf est implementation defined (des __gnu_cxx::stdio_sync_filebuf<char, std::char_traits<char>> sur stdin/stdout dans le cas de GCC).
Ce qui est intéressant, c'est quand on veut détourner ou filtrer ces flux. Il suffit de changer le streambuf vers autre chose. Dans le cas de fichiers, vers des std::basic_filebuf<>. Le type des globales reste exactement i/ostream (et ne devient pas i/ofstream), mais le type du streambuf est autre.

Sinon, je trouve les questions très techniques (/ vérifiables en compilant). Ca manque de "soit une classe list<> comment écririez-vous sorted_list<> en exploitant la précédente ?". Ou des "comment feriez-vous évoluer blabla ? " (oui, je suis vicieux -> http://www.developpez.net/forums/d354056/c-cpp/cpp/questionnaire-connaissances-cpp/#post2163618)

-
Edité par lmghs 2 septembre 2013 à 12:48:29

  • Partager sur Facebook
  • Partager sur Twitter
C++: Blog|FAQ C++ dvpz|FAQ fclc++|FAQ Comeau|FAQ C++lite|FAQ BS| Bons livres sur le C++| PS: Je ne réponds pas aux questions techniques par MP.
2 septembre 2013 à 15:02:53

Pensée du jour : C'est avec des questions comme celles-ci que je me dits que le chemin qui me mènera à la connaissance du C++ est encore long !

:'(

  • Partager sur Facebook
  • Partager sur Twitter
2 septembre 2013 à 17:35:52

michej2 a écrit:

Pensée du jour : C'est avec des questions comme celles-ci que je me dits que le chemin qui me mènera à la connaissance du C++ est encore long !

:'(


Mais ce bon, Moi aussi je suis null dans la nouvelle norme C++11 ;) (pas encore saisie l'interret des nouvelles fonctionnalités :'( )

Alors qui a la main ? :D

  • Partager sur Facebook
  • Partager sur Twitter

Je suis juste un débutant expérimenté. RTFM | RTFD

2 septembre 2013 à 17:42:20

La réponse n'as pas été entièrement donnée, il faut laisser les gens réfléchir un peu non :p ?
  • Partager sur Facebook
  • Partager sur Twitter
2 septembre 2013 à 17:48:46

Cytosol a écrit:

La réponse n'as pas été entièrement donnée, il faut laisser les gens réfléchir un peu non :p ?


Ahh.... Mais ce pas un peu exagéré ta question a mon niveau :( ...Ok réfléchie..

(Pense :  En plus j'ai pas bien compris la question ....)

-
Edité par Mohack 2 septembre 2013 à 17:50:59

  • Partager sur Facebook
  • Partager sur Twitter

Je suis juste un débutant expérimenté. RTFM | RTFD

2 septembre 2013 à 18:25:51

C'est alors l'occasion de faire des recherches sur ce que tu ne comprends pas.
  • Partager sur Facebook
  • Partager sur Twitter
2 septembre 2013 à 18:29:22

La réponse est facile, c'est "beaucoup". Pas besoin d'avoir le décompte précis car on ne fait pas du C. Notre objectif ne sera jamais de suivre tous les chemins, mais toutes les ressources vu que l'on fait du C++. Cf l'article de Lahman traduit sur dvpz par alexandre laurent.

Sinon, en considérant qu'aucun accesseur ne pouvait partir en échec, j'ai:
- échec de la copie du paramètre entrant : 1
- + 2 chemins du if qui passent par le cout avant le return final
- + 1 chemin du if qui arrive direct au return final.

Le prix du return final est, où chaque + peut partir en échec, de même que chaque création d'objets (et que l'on reste en C++98/03), et qu'il n'y a pas de copy-elision possible
- échec first + " "
- échec return first + " "
- échec ... + last
- échec return ... + last
- échec return de notre fonction
- réussite de notre fonction
=>6

Le prix du cout: partons sur 5 échecs possibles (un par <<) + la réussite => 6
Que cout soit détourné ou qu'il parte en exception, c'est un nombre de chemins encapsulés qui va changer, et non celui qui nous intéresse. A la limite, si "cout <<" lève une exception, cela va encore changer la donne, car on ne passera plus par le return final et ses 6 chemins, j'ai la flemme là.

Au final, je compte donc: 1 + 2 * (6(cout) + 6(post-if)) + 6(post-if), soit: 31. (si on suppose des copy-ellisions possibles, cela fera beaucoup moins). Et je n'exclue pas m'être trompé. Loin de là.

Bref. "Beaucoup" donc.

EDIT: je n'ai pas trouvé comment avoir des réponses cachées avec la v4 du sdz.

-
Edité par lmghs 2 septembre 2013 à 18:37:57

  • Partager sur Facebook
  • Partager sur Twitter
C++: Blog|FAQ C++ dvpz|FAQ fclc++|FAQ Comeau|FAQ C++lite|FAQ BS| Bons livres sur le C++| PS: Je ne réponds pas aux questions techniques par MP.
2 septembre 2013 à 18:51:49

La solution (qui n'est pas de moi) compte 23 chemins. Les 3 du if(1), if(0 || 1), if(0)

plus 20 chemins d'execution liés aux exceptions :

4. Le constructeur par copie du paramètre e throw.

5. Title() throw / renvoie un objet par copie dont le constructeur par copie throw. 

6. "CEO" peut être converti en objet dont le constructeur throw

7. == peut throw si c'est une surcharge de operator==

8. Idem que 5. pour Salary()

9. Idem que 6. pour 10000 conversion implicite, le constructeur throw

10. Idem 7. , si operator> est surchargé il peut throw

11. le || pourrait aussi être une surcharge de operator|| et throw

12 - 16 : comme signalé par lmghs, chaque << de la ligne du cout peut throw

17 : e.First() peut throw comme 5. / ligne du cout

18: e.Last() peut throw comme 5. / ligne du cout

19 : comme 17. pour la ligne du return

20 : comme 18. pour la ligne du return

21 : Pour " " un objet pourrait etre construit et le constructeur throw

22 : operator+  entre e.First et " " est surchargé et throw

23 : idem que 22. entre " " et e.Last()

Par contre j'ai l'impression que cette correction ne prend pas en compte la définition donnée d'un chemin d'éxecution et que donc lmghs est plus proche du nombre.

Dans tous les cas, il prend la main.

PS : Arretez s'il vous plaît de reprendre la main trop vite. Ok, si ce sujet n'a pas été relancé par lmghs dans 1 semaine c'est bon. Mais si il ne pose pas de sujet dans la soirée, et bah prenez votre mal en patience. Pareil, attendez que celui qui poste la question transmette officiellement la main à quelqu'un. Sinon, on se retrouve avec un bordel monstre, 4 questions en même temps et c'est ingérable. et oui il faut mettre des règles sinon...

-
Edité par Cytosol 2 septembre 2013 à 18:57:39

  • Partager sur Facebook
  • Partager sur Twitter
2 septembre 2013 à 18:56:34

En prenant en compte les exceptions données ci dessus multipliées par le nombre de chemins par exceptions, je compte 40

  • Partager sur Facebook
  • Partager sur Twitter
Rerum cognoscere causas
2 septembre 2013 à 19:21:58

Disons, que avec la notion de "fonctions atomiques" qui a un sens très précis pour moi (et totalement HS avec la question), je suis parti sur des accesseurs qui ne lèvent pas d'exceptions, et retourneraient des références constantes.

Je ne suis pas d'accord sur la comparaison qui peut lever une exception. Elles sont toutes noexcept en C++11. Dans les faits elles devaient déjà l'être en C++98/03 (je n'ai pas le temps de chercher si c'était explicitement garanti ou pas).

Quant à operator||(bool, bool), il ne peut pas être surchargé. Sauf si on sort des types à noix tels que pas des std::string, et que l'opérateur de comparaison serait alors surchargé pour renvoyer autre chose qu'un bool. Dans ces cas là ... effectivement, on peut exploser.

Effectivement, la solution que tu as recopiée compte les points de création de départ des chemins, et non les chemins.

----------------------

Devant filer, je n'ai qu'un problème high-level sous le coude. Je verrai à en pondre un plus abordable la prochaine fois.

Soit ce code de string-concatenator en C++11: http://ideone.com/WTEzbt. Certains connaissent déjà les variadic-template et connaissent probablement le principe d'implémenation : par récursion jusqu'à plus d'argument. Voici une approche non-récursive pour réaliser un concatenator. Seriez-vous me dire quels sont les principes à l’œuvre dans la macro UNPACK et comment ça marche au final.

NB: les implémentations C++98/03 de string-concatenator ressemblaient plutôt à ça: http://cdmh.co.uk/papers/exptempl/

-
Edité par lmghs 2 septembre 2013 à 19:22:57

  • Partager sur Facebook
  • Partager sur Twitter
C++: Blog|FAQ C++ dvpz|FAQ fclc++|FAQ Comeau|FAQ C++lite|FAQ BS| Bons livres sur le C++| PS: Je ne réponds pas aux questions techniques par MP.
2 septembre 2013 à 20:21:53

J'ai déjà vu passer des morceaux de cette technique, par contre je crois pas l'avoir vu résumée en une seule macro. Les éléments clés que je vois :

  • (__VA_ARGS__) Pour évaluer l'ensemble des expressions de UNPACK comme la première utilisation qui en est faite.
  • (void((__VA_ARGS__)), '\0')... Utilisation de l'opérateur virgule pour évaluer l'ensemble des instructions résultantes du variadic, on a donc une séquence de '\0'.
  • void(::unpack{}) Pour avoir un prétexte à l'évaluation de plusieurs instructions via une list d'initialisation (initializer-list).
  • La technique est ici très travaillée, pas mal d'éléments pour faire attention au typage (les void pas nécessairement indispensable dans des cas simples, c'est le cas de cet exemple).
  • Il y a quand même des éléments dont l'utilitée m'échappe un peu : le premier '\0' me semble inutile, le second void, le double parenthèsage. Je vois peut-être une utilité pour le double parenthèsages (prévention d'effet de bord à cause des remplacements textuels des macro) peut-être, mais les autres pas trop.

-
Edité par Freedom 2 septembre 2013 à 20:22:36

  • Partager sur Facebook
  • Partager sur Twitter
FaQ : Fr | En 1 2 | C++11 | Template || Blog : Deloget | C++|Boost--Dev | C++Next | GotW || Installer Boost
2 septembre 2013 à 22:34:43

J'imagine que le premier '\0' est là pour empêcher un tableau vide. Et le double parenthèse pour ne mettre qu'un paramètre dans le void (void(a,b) ne fonctionne pas contrairement à void((a,b))). Au début j'ai crut que le second void permettait d'empêcher le cast size_t -> char et éventuellement un warning du compilo. Mais comme au final, il y a , \0c'est toujours un char qui est ajouté dans le tableau... alors je n'en sais rien.

  • Partager sur Facebook
  • Partager sur Twitter
3 septembre 2013 à 8:13:56

@jo_link_noir> En effet, j'avais dissocier le double parenthésage du second void (donc son utilité est lié à celle du second void, qui m'échappe toujours pour le moment). Je vois pas ce que tu veux dire pour le premier '\0', en quoi un tableau vide est problématique ? Au final on s'en moque du char[] "construit", donc qu'il soit vide ou que ce soit "\0" la différence importe peu.

-
Edité par Freedom 3 septembre 2013 à 8:31:18

  • Partager sur Facebook
  • Partager sur Twitter
FaQ : Fr | En 1 2 | C++11 | Template || Blog : Deloget | C++|Boost--Dev | C++Next | GotW || Installer Boost
3 septembre 2013 à 9:27:58

Le premier '\0' est clairement pour prévenir des 0-size array. Mon gcc 4.6.3 laisse passer, mais pas clang qui me répond un

string-concatenator-cpp11.cpp|37 col 5| warning: zero size arrays are an extension [-Wzero-length-array]

sur join().

Par contre, les void, je ne les explique pas non plus.

Sinon, je rajouterai :

  • Même si ça peut nous paraitre évident, le tableau construit est un tableau statique. La taille est connue à la compilation, c'est le nombre de paramètres passés à la fonction variadique + 1.
  • J'ai découvert à cette occasion là que nawak... est remplacé par le mécanisme d'expansion lié aux variadic-templates. Ainsi, l'expression nawak sera reproduite pour chaque paramètre de la fonction variadique. Cela s'applique donc à l'expression parenthésée: (void((__VA_ARGS__)), '\0'). Pour chaque paramètre strs[i], on va ainsi avoir pour intr1(strs), instrn(strs):
    -> (void(intr1(strs[1]), instrn(strs[1])), '\0'), ..., (void(intr1(strs[n]), instrn(strs[n])), '\0')
    J'avoue que c'est cette expansion qui m'avait laissé le plus perplexe au début.
  • Le coup du using qui permet de définir un type tableau. Avec un typedef ça compile aussi -> typedef char unpack[];
    Je n'ai pas fouillé pourquoi le using était "mieux".
Je pense pouvoir passer la main à freedom qui a eu les éléments clés de cette technique permettant d'écrire de façon non-récursive des fonctions templates variadiques.

-
Edité par lmghs 3 septembre 2013 à 9:30:08

  • Partager sur Facebook
  • Partager sur Twitter
C++: Blog|FAQ C++ dvpz|FAQ fclc++|FAQ Comeau|FAQ C++lite|FAQ BS| Bons livres sur le C++| PS: Je ne réponds pas aux questions techniques par MP.
3 septembre 2013 à 9:45:03

Je laisse la main. J'oublie toujours le zero-size array.

  • Partager sur Facebook
  • Partager sur Twitter
FaQ : Fr | En 1 2 | C++11 | Template || Blog : Deloget | C++|Boost--Dev | C++Next | GotW || Installer Boost
3 septembre 2013 à 10:05:13

Freedom a écrit:

@jo_link_noir> Je vois pas ce que tu veux dire pour le premier '\0', en quoi un tableau vide est problématique ?

Je me le demande aussi.

@lmghs: tout à une raison ?

EDIT: J'évite toujours de faire des tableaux de taille zéro mais que dit le standard dessus ? Parsqu'avec gcc, il n'y a jamais d'erreur :/.

Faut aussi que j'arrête de regarder des séries en même temps que je poste...

-
Edité par jo_link_noir 3 septembre 2013 à 10:12:38

  • Partager sur Facebook
  • Partager sur Twitter
3 septembre 2013 à 10:35:33

norme §8.3.4/1 dit:

If the constant-expression (5.19) is present, it shall be an integral constant expression and its value shall be greater than zero.

Après, GCC les accepte comme une extension pour les raisons exposées ici, j'imagine: http://gcc.gnu.org/onlinedocs/gcc/Zero-Length.html

Pour les autres raisons, si tu veux parler de void, j'avoue ne pas avoir trouvé. En C, il faudrait écrire, (void)printf("arguments"); quand on ignore volontairement les valeurs de retour d'une expression et que l'on veut éviter les warnings liés à des variables ignorées. Je ne saurais pas dire si c'est la même chose ici. A priori non, j'ai tenté d'appeler une fonction marquée avec l'attribut __attribute_warn_unused_result__, et les voids sont sans effets.

  • Partager sur Facebook
  • Partager sur Twitter
C++: Blog|FAQ C++ dvpz|FAQ fclc++|FAQ Comeau|FAQ C++lite|FAQ BS| Bons livres sur le C++| PS: Je ne réponds pas aux questions techniques par MP.
3 septembre 2013 à 11:11:32

Merci pour le § de norme et la page sur gcc (je suis tombé sur cette page entre temps). Du coup avec l'option -pedantic j'ai un warning \o/.

Concernant le void, c'est peut-être inutile du coup.

À qui le tour ? Je laisse la main.

  • Partager sur Facebook
  • Partager sur Twitter
3 septembre 2013 à 16:10:28

J'ai du mal à suivre. C'est revenu à moi de vous proposer autre chose ?
  • Partager sur Facebook
  • Partager sur Twitter
C++: Blog|FAQ C++ dvpz|FAQ fclc++|FAQ Comeau|FAQ C++lite|FAQ BS| Bons livres sur le C++| PS: Je ne réponds pas aux questions techniques par MP.
3 septembre 2013 à 19:00:04

@lmghs> jo_link_noir et moi avons laissé, donc c'est à qui veut ^^

Pour revenir sur ta question d'avant (j'ai revérifié quelques éléments dans la norme) :

- Pour le zero-size array, en complément du passage que tu cites, il y a aussi le 8.5.1 §4 (le passage que tu cites interdit T a[0] mais pas explicitement T a[] = {}, même si ça peut paraître évident, avec la norme on sait jamais  ^^)

- L'initializer-list est un prétexte pour l'appel (en soit il sert à rien), mais il a la force (nécessaire ici, et on a pas insisté dessus je crois encore) d'imposer l'ordre des appels (ce qui ne serait pas le cas d'une fonction dummy par exemple).

Personnelement je l'écrirais comme ceci :

#define UNPACK(...) static_cast<void>(::std::initializer_list<char>{(__VA_ARGS__,char())...})

Je pense que c'est équivalent (et peut être plus lisible ? même si c'était pas le but dans un quizz).

Pour le choix using/typedef, j'ai cherché si il y avait des différences (d'après la norme) mais j'en ai pas trouver (sauf la différence évidente que using prend des cas en plus). J'avais le souvenir d'une situation ou using fonctionnait pas, mais c'était il y a pas mal de temps (au début de son introduction dans gcc), et j'ai pas réussi à reproduire la différence.

-
Edité par Freedom 3 septembre 2013 à 19:05:09

  • Partager sur Facebook
  • Partager sur Twitter
FaQ : Fr | En 1 2 | C++11 | Template || Blog : Deloget | C++|Boost--Dev | C++Next | GotW || Installer Boost
4 septembre 2013 à 17:24:14

Très bien alors je reprend la main.

Je vais essayer d'aller dans le sens proposé par lmghs, avec une question assez triviale, n'acceptant pas une bonne réponse précise, mais étant élaborée à partir d'avis. C'est donc une question qui peut ouvrir au débat sur les choix proposés en solution.

Supposez ce code :

//...

float divide(int a, int b)
{
    return a/b;
}

int main(void)
{
    int a, b;
    
    std::cin >> a >> b;

    float res = divide(a, b);   
 
    std::cout << "Resultat de " << a << "/" << b << ": " << res << std::endl;

return 0;
}
Proposer une solution pour améliorer/corriger ce code.
  • Partager sur Facebook
  • Partager sur Twitter
Anonyme
4 septembre 2013 à 17:36:36

  • Ne pas utiliser de variable temporaire res
  • std::cout << "Resultat de " << a << "/" << b << ": " << res << std::endl;
    ->
    std::cout << "Resultat de " << a << '/' << b << ": " << res << std::endl;
  • Ne pas utiliser la fonction divide, qui ne sert à rien (la division est "fournie" avec le C++), et ça évite des instructions supplémentaires.
  • Bien indenter le return 0 final. :p
  • Changer le type de a et b en float pour une meilleur concordance des types.
  • Utiliser le prototype int main() (la forme que tu utilises n'est pas mentionnée dans la norme C++98)
  • N'afficher le résultat que si il a correctement été lu.

Au final:

int main()
{
    float a, b;
    std::cin >> a >> b;
    if(std::cin.good())
    {
        std::cout << "Resultat de " << a << '/' << b << ": " << a / b << std::endl;
    }
    return 0;
}

-
Edité par Anonyme 4 septembre 2013 à 17:42:30

  • Partager sur Facebook
  • Partager sur Twitter
4 septembre 2013 à 17:56:31

ameliorer/corriger ce bon ! Mais t'aurais pas oublier simplifier par hazard .

int main(void)
{
    int a, b;
    cin >> a >> b;
    cout << "Resultat de " << a << "/" << b << ": " << a/b << endl;

return 0;
}



  • Partager sur Facebook
  • Partager sur Twitter

Je suis juste un débutant expérimenté. RTFM | RTFD

Anonyme
4 septembre 2013 à 18:01:51

De mon côté je préfère toujours chercher le meilleur rapport gestion des erreurs / complexité. ;)

-
Edité par Anonyme 4 septembre 2013 à 18:03:46

  • Partager sur Facebook
  • Partager sur Twitter
4 septembre 2013 à 18:17:18

moi62100, tu es sur une bonne piste (test de cin ; bien que good soit superflux, if (cin), ou if (cin >> a) sont parfaitement idiomatiques ; la division entière).

Cependant, virer div n'est pas dans l'esprit de la question. Car cette fonction est là comme piste pour réfléchir aux responsabilités dans le cadre de la Programmation par Contrat.

Quant à la variable temporaire, son retrait n'apporte rien, pas même une optimisation. On perd en revanche en débuggabilité.

BTW, Dans les trucs mineurs, je préfère "return EXIT_SUCCESS"  à "return 0".

  • Partager sur Facebook
  • Partager sur Twitter
C++: Blog|FAQ C++ dvpz|FAQ fclc++|FAQ Comeau|FAQ C++lite|FAQ BS| Bons livres sur le C++| PS: Je ne réponds pas aux questions techniques par MP.
Anonyme
4 septembre 2013 à 18:39:34

La programmation par contrat je ne connais pas.^^

La variable temporaire, c'est pour avoir une ligne en moins, dans ce code ci ça donne un code plus court, c'est tout (mais si on demandait un code plus évolutif je l'aurai laissé;)).

Sinon, merci pour l'astuce pour le test de cin.

  • Partager sur Facebook
  • Partager sur Twitter
4 septembre 2013 à 19:18:35

lmghs a très bien compris ou je voulais en venir, ça en fait au moins 1 :p (La faute à mon énoncé très vague).

Je vais tenter de répondre à ceux qui ont déja posté :

  • Bien indenter le return 0 final. :p
 du détail, pas super simple d'indenter avec l'éditeur du sdz.
  • Ne pas utiliser la fonction divide, qui ne sert à rien (la division est "fournie" avec le C++), et ça évite des instructions supplémentaires.  
Le but est de travailler la fonction divide. Elle sert ici à comprendre une notion fondamentale sur un problème très simple, et permet de se concentrer uniquement sur les améliorations, et non sur de la simplification ou autres
  • Changer le type de a et b en float pour une meilleur concordance des types. 

a et b restent des int, dans le main comme dans divide, même si c'est discutable. Il y a donc quand même quelque chose à faire pour obtenir un résultat correct dans divide (c'est pour faire travailler l'utilisation d'un certain opérateur).

  • N'afficher le résultat que si il a correctement été lu.

C'est pas l'affichage qui est important ici ;)

  • Mais t'aurais pas oublier simplifier par hazard

Non je n'ai pas oublié simplifier, du coup il ne faut pas le faire, c'est le but de l'exo. A la fin, divide() devrait même comporter 2 ou 3 lignes de plus.

 Pour le test de l'entrée, on est pas loin. Il manque quand même un truc, ce que tu proposes contient un bug moi62100. Même en ayant viré divide. Le but de l'exo est de détecter ce bug dans divide, et de le prévenir dans le main.

Maintenant que vous avez amené le problème d'entrée invalide, il faut rajouter une contrainte : on va redemander a l'utilisateur d'entrer quelque chose, tant que c'est invalide. Sans prompt, ça n'apporte rien de concret. Le but n'étant pas de faire des tests en compilant, mais d'essayer de réfléchir avant d'écrire du code, et de visualiser ce qu'il se passe. L'utilisateur étant fictif on peut se passer de prompt ici.

-
Edité par Cytosol 4 septembre 2013 à 19:24:54

  • Partager sur Facebook
  • Partager sur Twitter
4 septembre 2013 à 20:19:11

Bon ben je vais me jeter à l'eau même si me connaissant je vais oublier la moitié des cas ...

float divide(int a, int b)
{
  assert(b != 0);
  return static_cast<float>(a)/static_cast<float>(b);
}

int main()
{
  int a, b;
  std::cin >> a;
  do{
    if(! (cin>>b)){
      b = 0;
      cin.clear();
    }
  } while(b == 0);       
        
  float res = divide(a, b);   
  std::cout<<"Resultat de "<<a<<"/"<<b<<":"
           <<res<<std::endl;

  return EXIT_SUCCESS;
}


A noter : on peut décider de ne pas tester la division par 0 étant donné que c'est un comportement défini en flottant.

-
Edité par Ksass`Peuk 4 septembre 2013 à 20:21:37

  • Partager sur Facebook
  • Partager sur Twitter

Posez vos questions ou discutez informatique, sur le Discord NaN | Tuto : Preuve de programmes C

5 septembre 2013 à 13:54:38

J'aime beaucoup la solution de Kass'Peuk d'un point de vue PpC. Je la décrypterai plus tard, car le choix n'est pas si trivial, même s'il est je pense ce qui peut se faire de mieux.

Seul détail, clear() n'est pas suffisant si le flux est KO. Il faut aussi un ignore pour nettoyer les résidus. Et si le flux a été fermé, il faut tester eof. La solution pour l'aspect erreur d'I/O est dans la FAQ C++ de dvpz. Si je ne me trompe pas, >> va laisser b inchangé si l'extraction ne peut se faire. Il suffit alors de le mettre à 0 avant le do, et de remettre le flux en état s'il est KO.

  • Partager sur Facebook
  • Partager sur Twitter
C++: Blog|FAQ C++ dvpz|FAQ fclc++|FAQ Comeau|FAQ C++lite|FAQ BS| Bons livres sur le C++| PS: Je ne réponds pas aux questions techniques par MP.
5 septembre 2013 à 15:08:59

j'ai beau beau cherché sur les flux cin cout et j'ai trouvé un ligne pour ignoré :

	float divide(int a, int b)
{
  assert(b != 0);
  return static_cast<float>(a)/static_cast<float>(b);
}
 
int main()
{
  int a, b;
  std::cin >> a;
  do{
    if(! (cin>>b)){
      b = 0;
      cin.clear();
	  cin.ignore( numeric_limits<streamsize>::max(), '\n' );// ce celle-ci pour encore vraiment compris 
    }
  } while(b == 0);      
         
  float res = divide(a, b);  
  std::cout<<"Resultat de "<<a<<"/"<<b<<":"
           <<res<<std::endl;
 
  return EXIT_SUCCESS;
}

Et oui ce le code kass met j'ai seulement rejouter un ligne :p .

C'est pas une question mais j'aimerais savoir comment passer une fonction un parametre qu'elle ne connais pas le type .

Par exemple : 

void myfunction(int param);

Comme vous voyez cette fonction prend un int ,mais moi j'aimerais quel accepte n'importe quoi ? o_O 

Comme un float ,double, long,struct meme un objet !! Vous me suivez hein... :o 

Bon moi j'ai un peu pensé a la nouvel norme C++11, j'ai obtenu :

void myfunction(auto param);

Bon ca marche... mais comment faire sans auto

Je rapelle que ce n'est pas un question à repondre donc ne m'aggacé pas ,je sais qu'il y'a une question en cours mais ce du HELP !!

  • Partager sur Facebook
  • Partager sur Twitter

Je suis juste un débutant expérimenté. RTFM | RTFD