#1 Le 16/07/2011, à 21:29
- Destroyers
C++ questions sur: system(), le bloc try et des méthodes de iostream
Bonjour à tous,
encore plein de nouvelles questions dont j'ai du mal a trouver les réponses en cherchant
question n°1:
Ce tutoriel dit qu'il faut utiliser le moins possible la fonction system(); (je parle surtout de system("pause"); car je ne connais pas les autres utilités de cette fonction)
Pourquoi cette fonction est elle déconseillée ?
question n°2:
voici 2 codes:
int division(int a,int b)
{
try
{
if(b == 0)
throw string("Division par zéro !");
else
return a/b;
}
catch(string const& chaine)
{
cout<<chaine<<endl;
}
}
et:
int division(int a, int b)
{
if(b == 0)
std::cout<<"Division par zéro !"<<'\n';
else
return a/b;
}
}
ne me reprochez rien sur les endl et les espaces de nommage de 1er code, c'est celui du tutoriel
la question est: quelle est la différence entre les deux codes ! sa donne le même resultat si on met 0...
si la réponse est "aucune", alors dites moi à quoi sert le bloc try (et ce qui va avec(throw/catch)).
question n°3:
soit le code suivant:
#include <iostream>
#include "fonctions_saisie.hpp" // Ce fichier contient le prototype de la fonction vider_buffer()
using namespace std;
int main()
{
unsigned short int age;
cout << "Entrez votre âge : ";
cin >> age;
if(cin.eof() || cin.bad()) // S'il y a une erreur interne au flux, qui n'est pas provoqué par l'utilisateur
{
cerr << "Une erreur interne est survenue." << endl;
}
else if(cin.fail()) // Si fail() retourne true
{
cerr << "Erreur, saisie incorrecte." << endl;
}
vider_buffer(); // On remet cin dans un état valide et vide le buffer
return 0
}
ci-joint la fonction vider_buffer():
void vider_buffer()
{
cin.clear();
cin.seekg(0, ios::end);
if(!cin.fail())
{
cin.ignore(numeric_limits<streamsize>::max(),'\n');
}
else
{
cin.clear();
}
}
la question est la suivante:
je ne comprend pas la ligne:
if(cin.eof() || cin.bad()) // S'il y a une erreur interne au flux, qui n'est pas provoqué par l'utilisateur
car eof() retourne true si la fin du flux a été rencontrée lors d'une opération d'extraction,
or je ne vois pas en quoi trouver la fin du flux représente une erreur, il faut bien qu'il est une fin ...
ensuite je ne vois pas en quoi le fait que bad() retourne true veut dire qu'il y a une erreur INTERNE...
question n°4:
je ne comprend pas la différence entre bad(); et fail();
car si la dernière opération à échouée, bad() et fail() retournent la même chose puisque cela veut dire qu'il y a eu une erreur sur le flux.
de plus, si il y a une erreur sur le flux, la dernière opération a forcément échouée, donc bad(); et fail(); devraient retourner encore une fois le même chose ...
moi c'est comme sa que je le comprend donc il me fraudais une petite explication
je pense vous donner pas mal de travail là donc je vais m'arrêter pour le moment et vous remercier infiniment si vous résolvez mes problèmes ^^
Merci d'avance.
Dernière modification par Destroyers (Le 16/07/2011, à 21:35)
Hors ligne
#2 Le 17/07/2011, à 01:27
- grim7reaper
Re : C++ questions sur: system(), le bloc try et des méthodes de iostream
Salut,
question n°1:
Ce tutoriel dit qu'il faut utiliser le moins possible la fonction system(); (je parle surtout de system("pause"); car je ne connais pas les autres utilités de cette fonction)
Pourquoi cette fonction est elle déconseillée ?
Principalement pour deux raisons :
- portabilité : les commandes lancées par système sont des commandes du système (donc en général propre au système, peu de chance de les retrouver ailleurs). Par exemple, pause est une commande DOS.
Un code avec
system("pause");
Ne fonctionneras pas correctement sous Linux, BSD, Hurd ou que sais‑je encore.
- sécurité : Cf. ici
question n°2:
[…]
la question est: quelle est la différence entre les deux codes ! sa donne le même resultat si on met 0...
si la réponse est "aucune", alors dites moi à quoi sert le bloc try (et ce qui va avec(throw/catch)).
Dans le cas présent, il n'y a en effet aucune différence.
Le code exemple n'est pas très démonstratif de l'intérêt des exceptions.
Pour ce qui est de l'utilité des blocs try/catch (et des exceptions en général), je te renvoie ici.
question n°3:
[…]
la question est la suivante:
je ne comprend pas la ligne:if(cin.eof() || cin.bad()) // S'il y a une erreur interne au flux, qui n'est pas provoqué par l'utilisateur
car eof() retourne true si la fin du flux a été rencontrée lors d'une opération d'extraction,
or je ne vois pas en quoi trouver la fin du flux représente une erreur, il faut bien qu'il est une fin ...
Oui, moi aussi je ne trouve pas très correct de considérer EOF comme une erreur interne non provoqué par l'utilisateur…
D'ailleurs, avec ce programme exemple il suffit de frapper Ctrl+D lorsqu'il demande l'âge pour envoyer un EOF au programme.
C'est bien provoqué par l'utilisateur et non pas une erreur interne.
ensuite je ne vois pas en quoi le fait que bad() retourne true veut dire qu'il y a une erreur INTERNE...
En fait, le flag bad indique le flux est corrompu et qu'il y a eu ou qu'il risque d'y avoir des pertes de données si on essaye encore de s'en servir.
question n°4:
je ne comprend pas la différence entre bad(); et fail();
C'est une différence assez subtil en fait
Si je dis des bêtises, le Farfadet Spatial corrigera.
Le flag fail signifie que le flux est dans un état invalide (par exemple, la dernière lecture s'est mal déroulée car on voulait lire un int et l'utilisateur a entré une chaîne) mais il n'est pas corrompu, aucune donnée (aucun caractère en fait) n'a été perdu.
Le flag bad, c'est comme je l'ai expliqué plus haut (flux corrompu et éventuelles pertes de données).
Enfin, de manière générale, les tutoriels sur le Site du Zéro sont de qualités très inégales (en particulier sur le C++).
Hors ligne
#3 Le 17/07/2011, à 11:45
- Le Farfadet Spatial
Re : C++ questions sur: system(), le bloc try et des méthodes de iostream
Salut à tous !
Enfin, de manière générale, les tutoriels sur le Site du Zéro sont de qualités très inégales (en particulier sur le C++).
Sur le C++, le Site du zéro est très mauvais. Ici, on a un exemple qui montre bien qu’il ne faut surtout pas suivre ce qui est indiqué sur ce site, sauf à vouloir prendre de très mauvaises habitudes sur lesquelles on aura du mal à revenir et probablement comprendre les choses de travers.
Juste une précision sur l’intervention de Grim7reaper :
int division(int a,int b) { try { if(b == 0) throw string("Division par zéro !"); else return a/b; } catch(string const& chaine) { cout<<chaine<<endl; } }
Là, c’est utiliser les exceptions n’importe comment.
Le mécanisme d’exception est un mécanisme important qu’il convient de maîtriser et d’utiliser. La façon la plus efficace de le faire, c’est d’utiliser une hiérarchie de classe, ce qui n’est absolument pas fait dans le cas présent.
De plus, les exceptions sont là pour permettre de gérer des situations qui ne peuvent pas l’être à l’endroit du code où elles ont été générées. Par exemple, imaginons le cas d’une division par zéro. Au point de calculer la division, on ne peut pas savoir s’il est préférable de renvoyer une valeur arbitraire ou bien s’il vaut mieux interrompre le programme, entre autres possibilités. Un bon moyen est de générer une exception et de laisser par ailleurs le programmeur décider de la marche à suivre.
Dans l’exemple donné, la gestion de l’exception est réalisée à l’endroit même où elle a eu lieu. On met donc en place un mécanisme complexe et qui peut fortement impacter les performances dans un cas où ce n’est pas du tout nécessaire. En conclusion, l’exemple montre une mauvaise façon de gérer les exceptions et en plus c’est fait à un mauvais moment. Plutôt de regarder quelque chose qu’il ne faut pas faire, il vaut mieux oublier cet exemple.
À bientôt.
Le Farfadet Spatial
Hors ligne
#4 Le 17/07/2011, à 13:10
- Rafbor
Re : C++ questions sur: system(), le bloc try et des méthodes de iostream
Salut,
Là, c’est utiliser les exceptions n’importe comment
j'ai déjà vu pire, et dans un programme que j'ai fait sous-traiter à une SSII..
Notre acheteur avait tellement tiré les prix vers le bas en mettant en concurrence 2 sociétés de dev, que celle qui a été retenue a fait faire le boulot par un jeune pas très doué. Quand j'ai récupéré les sources, j'avais plus de 150 warnings à la compilation à cause de blocs 'catch' vides, comme ceci:
catch (Exception ex)
{}
Bien sur, le programme ne plantait jamais, toutes les erreurs étaient interceptées, mais comme elles n'étaient pas traitées dans le 'catch', le programme continuait avec des résultats erronés...
Xubuntu 24.04 - Mes projets sur Github
Hors ligne
#5 Le 17/07/2011, à 13:14
- Destroyers
Re : C++ questions sur: system(), le bloc try et des méthodes de iostream
En fait ce que j'essaie de chercher, en lisant La saisie sécurisée du Site du 0, c'est comment régler le problème de la boucle infinie quand on rentre des caractères alphabétiques dans une variable type int. Malheureusement je ne trouve pas un amis m'a conseillé de déclarer un string, de le mettre dans un fichier et de le mettre dans un int si c'est un nombre... sa marche surement mais sa ne me plait pas ^^
qui aurait une solution ?
Hors ligne
#6 Le 17/07/2011, à 14:58
- omc
Re : C++ questions sur: system(), le bloc try et des méthodes de iostream
J'ai pas compris.
Quelle boucle infinie ?
Hors ligne
#7 Le 17/07/2011, à 15:01
- Destroyers
Re : C++ questions sur: system(), le bloc try et des méthodes de iostream
int chiffre;
std::cin>>chiffre;
si tu entres autre chose que des chiffres, il y aura une boucle infinie
Hors ligne
#8 Le 17/07/2011, à 15:28
- omc
Re : C++ questions sur: system(), le bloc try et des méthodes de iostream
Ha bon, je ne le savais pas.
Je ferais un truc assez simple : cin → string → entier.
La conversion du string en entier se fait à l'aide de boost::lexical_cast (la librairie boost est dans les paquets) qui présente l'avantage de lever une exception
si la conversion n'est pas possible.
#include <boost/lexical_cast.hpp>
.....
.....
std::string ageStr;
std::cin >> ageStr;
//Conversion avec boost::lexical_cast
unsigned int age = 0;
try
{
age = boost::lexical_cast<unsigned int>(ageStr);
}
catch(boost::bad_lexical_cast &)
{
std::cout << "ha non, " << ageStr << " n'est pas un age possible !" << '\n';
std::cout << "Allez recommence :)" << std::endl;
}
....
Attention code pas testé !
Dernière modification par omc (Le 17/07/2011, à 15:30)
Hors ligne
#9 Le 17/07/2011, à 17:47
- Destroyers
Re : C++ questions sur: system(), le bloc try et des méthodes de iostream
il n'y a aucun moyen en utilisant uniquement la bibliothèque standard ?
Hors ligne
#10 Le 17/07/2011, à 18:06
- grim7reaper
Re : C++ questions sur: system(), le bloc try et des méthodes de iostream
il n'y a aucun moyen en utilisant uniquement la bibliothèque standard ?
Si.
Je pense que le code suivant fait ce que tu attends (code pondu rapidement, il peut manquer 2-3 trucs…)
#include <iostream>
#include <sstream>
#include <string>
int main()
{
int i;
bool ok = false;
std::cout << "Veuillez entrer un entier : ";
do
{
std::string s;
std::cin >> s;
std::istringstream iss(s);
ok = (iss >> i != 0);
if(!ok)
{
std::cerr << "Erreur de conversion\n";
std::cout << "Veuillez entrer un entier : ";
}
} while(!ok);
std::cout << "Entier lu = " << i << '\n';
return 0;
}
Hors ligne
#11 Le 18/07/2011, à 14:07
- Luc Hermitte
Re : C++ questions sur: system(), le bloc try et des méthodes de iostream
Pour la saisie "sécurisée" (je n'aime pas ce terme), il y a tout ce qu'il faut dans la FAQ C++ de dvpz -> #cin_verify
Concernant les exceptions et la division par zéro, j'en avais parlé dans les commentaires du tuto v2.
Ce n'est pas un truc simple qui s'explique en 1 page. Il y a diverses choses à comprendre :
- différence entre erreur de prog et erreur de contexte (utilisateur boulet)
- les diverses couches d'un soft, etc
-> http://www.siteduzero.com/forum-83-6111 … l#r6273692 (point e-)
(et plus ça va, moins je vois l'intérêt de les mettre dans une hiérarchie -- peut-être que mes découpages des parties métiers fait que ce besoin n'a jamais pointé le bout de son nez, je ne sais pas)
Dernière modification par Luc Hermitte (Le 18/07/2011, à 14:09)
Hors ligne
#12 Le 18/07/2011, à 19:29
- Le Farfadet Spatial
Re : C++ questions sur: system(), le bloc try et des méthodes de iostream
Salut à tous !
il n'y a aucun moyen en utilisant uniquement la bibliothèque standard ?
Bien entendu, lorsque l’on débute, il convient de ne pas mettre la charrue avant les bœufs, notamment en s’égarant sur des bibliothèques qui ne forment pas le cœur du langage. Toutefois, on peut pour ainsi dire considérer Boost comme faisant partie de la bibliothèque standard.
il y a tout ce qu'il faut dans la FAQ C++ de dvpz -> #cin_verify
Je suis trop bon, cela me perdra : http://cpp.developpez.com/faq/cpp/?page … cin_verify.
Si Luc HERMITTE conseille régulièrement d’aller sur Développez.com, ce n’est pas uniquement parce qu’il en est l’un des contributeurs. C’est aussi parce que c’est une des références les plus complètes en français.
Ce n'est pas un truc simple qui s'explique en 1 page.
C’est tout à fait vrai. Pour ma part, avant d’aborder les exceptions, je m’assure que les bases des classes et des espaces de nommages sont bien maîtrisées.
et plus ça va, moins je vois l'intérêt de les mettre dans une hiérarchie -- peut-être que mes découpages des parties métiers fait que ce besoin n'a jamais pointé le bout de son nez, je ne sais pas
Cela dit, je pense que tu les gères avec des classes, pas sauvagement avec des chaînes de caractères. Toutefois, il est vrai que globalement les cas où j’ai relevé le besoin d’une hiérarchie développée c’est avec de nombreuses opérations d’entrées-sorties avec plusieurs types créés par le développeur. Quand je parlais de hiérarchie de classes, je voulais dire à tout le moins des classes dédiées aux exceptions – et, souvent, héritant de « std::exception ».
À bientôt.
Le Farfadet Spatial
Hors ligne
#13 Le 19/07/2011, à 11:38
- Luc Hermitte
Re : C++ questions sur: system(), le bloc try et des méthodes de iostream
Je conseille la FAQ, effectivement parce qu'elle est de qualité, mais aussi et surtout c'est que l'on finit à force par devenir fainéant et que l'on perd l'envie de toujours répéter les mêmes choses ^^'
Concernant, les exceptions, je travailles toujours avec des std::exceptions ou des (enfin ... "un") trucs qui en dérivent. Généralement, il s'agit d'une exception qui ressemble à std::runtime_error.
Hors ligne
#14 Le 20/07/2011, à 14:45
- Destroyers
Re : C++ questions sur: system(), le bloc try et des méthodes de iostream
Merci beaucoup:)
Hors ligne
#15 Le 21/07/2011, à 19:20
- Destroyers
Re : C++ questions sur: system(), le bloc try et des méthodes de iostream
Luc Hermite a écrit :il y a tout ce qu'il faut dans la FAQ C++ de dvpz -> #cin_verify
Je suis trop bon, cela me perdra : http://cpp.developpez.com/faq/cpp/?page … cin_verify.
Si Luc HERMITTE conseille régulièrement d’aller sur Développez.com, ce n’est pas uniquement parce qu’il en est l’un des contributeurs. C’est aussi parce que c’est une des références les plus complètes en français.
Moi se que je vois c'est que sur ce site, ils n'utilisent pas non plus les espaces de nommages
Dernière modification par Destroyers (Le 21/07/2011, à 19:21)
Hors ligne
#16 Le 21/07/2011, à 19:30
- Destroyers
Re : C++ questions sur: system(), le bloc try et des méthodes de iostream
std::istringstream iss(s); ok = (iss >> i != 0); if(!ok) { std::cerr << "Erreur de conversion\n"; std::cout << "Veuillez entrer un entier : "; } } while(!ok);
je ne comprend pas vraiment ... d'une part par ce que je ne connais pas l'utilité de la classe istringstream,
d'autre part car:
while(!ok)
tant que ok est différent de quoi ! =O
et le pire du pire ... c'est sa:
ok = (iss >> i != 0);
car la je ne comprend rien ... ok est un bool ... comment on peut lui donner cette valeur ... bizaroïde que j'aimerai bien qu'on m'explique aussi
Hors ligne
#17 Le 21/07/2011, à 20:17
- Le Farfadet Spatial
Re : C++ questions sur: system(), le bloc try et des méthodes de iostream
Salut à tous !
d'une part par ce que je ne connais pas l'utilité de la classe istringstream,
Le nom est signifiant : « stream » signifie flux, « string », chaîne (de caractère) et « i » signifie « input », soit entrant. Il s’agit donc d’un flux entrant sur une chaîne de caractère. Tu connais les flux vers la sortie standard (« std::cout »), il en existe vers des fichiers. Un flux sur une chaîne permet d’orienter un flux vers ou à partir d’une chaîne : on peut utiliser les opérations sur les flux pour traiter une chaîne.
while(!ok)
tant que ok est différent de quoi ! =O
Ce qui se trouve entre parenthèses après « while » doit être un booléen. Tant que sa valeur est vraie, alors ce qui se trouve dans le bloc d’instruction qui suit immédiatement après la parenthèse fermante est exécuté, on passe à la suite dès que la valeur est fausse. Donc, cela signifie « faire tant que la valeur de la variable ok est "faux" ».
ok = (iss >> i != 0);
car la je ne comprend rien ... ok est un bool ... comment on peut lui donner cette valeur ... bizaroïde que j'aimerai bien qu'on m'explique aussi
Il faut décomposer un peu.
« iss >> i », tu connais déjà, car tu as déjà dirigé un flux entrant vers une variable :
std::cin >> i;
En l’occurrence, la source n’est pas l’entrée standard (le clavier), mais la chaîne (« s ») à laquelle est associé « iss ». Donc, il s’agit simplement de prendre le prochain élément du flux et le stocker dans un entier.
« iss >> i != 0 » demande de connaître un peu plus profondément les flux. Un flux retourne une valeur correspondant à son état. Il s’agit d’une série de bits, qui indiquent si on a atteint la fin du flux, si le transfert s’est mal passé et ainsi de suite. Si tout va bien, tous ces bits sont positionnés à 0 et donc la valeur est 0. On test si la valeur du flux est différente de zéro, c’est-à-dire si le transfert s’est mal déroulé – dans ce cas, si la valeur était différente d’un entier. Il s’agit d’un test, qui renvoie vrai ou faux, c’est-à-dire un booléen.
« ok = (iss >> i != 0); » place la valeur du test dans une variable booléenne.
À bientôt.
Le Farfadet Spatial
Hors ligne
#18 Le 21/07/2011, à 20:29
- Destroyers
Re : C++ questions sur: system(), le bloc try et des méthodes de iostream
Merci beaucoup, tout est tellement claire avec toi
Hors ligne