Bonjour,
J'ai réalisé une fonction pour sécuriser les saisies en console. J'ai essayé qu'elle soit la plus générique possible. Il y a en fait 4 fonctions, leur déclaration :
1 2 3 4 5 6 7 8 9 10 11 12 13 | template<typename T> bool sInStream(std::istream &stream, T &data); template<typename T, typename Function> bool sInStream(std::istream &stream, T &data, Function const& function); //Spécialisations pour std::string : template<> bool sInStream<std::string>(std::istream &stream, std::string &str); template<typename Function> bool sInStream(std::istream &stream, std::string& str, Function const& function);~~~ |
La fonction prend en prend en paramètre un flux qui hérite de std::istream
, la variable dans laquelle sera stockée la saisie et, optionnel, un prédicat qui vérifie que la valeur saisie respecte bien certaines contraintes. Si la fonction possède une spécialisation pour le type std::string
, c'est parce qu'elle utilise std::getline()
en interne. La fonction renvoie true
si tout c'est bien déroulé et si le prédicat renvoie true
aussi. Sinon la fonction renvoie false
. Cela permet de l'utiliser dans une boucle.
Si je la poste ici c'est pour que vous me donniez votre avis, si c'est une bonne solution ou si la fonction n'est en fait pas du tout sécurisée, si c'est mal conçus,… bref, vos conseils. Merci d'avance !
Le code :
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 | #ifndef S_IN_STREAM_H #define S_IN_STREAM_H #include <iostream> #include <limits> #include <string> template<typename T, typename Function> bool sInStream(std::istream &stream, T &data, Function const& function) { if (!(stream >> data)) { stream.clear(); stream.ignore(std::numeric_limits<std::streamsize>::max(), '\n'); return false; } if (function(data)) { stream.clear(); stream.ignore(std::numeric_limits<std::streamsize>::max(), '\n'); return true; } else stream.clear(); stream.ignore(std::numeric_limits<std::streamsize>::max(), '\n'); return false; }; template<typename T> bool sInStream(std::istream &stream, T &data) { if (!(stream >> data)) { stream.clear(); stream.ignore(std::numeric_limits<std::streamsize>::max(), '\n'); return false; } stream.clear(); stream.ignore(std::numeric_limits<std::streamsize>::max(), '\n'); return true; }; template<> bool sInStream<std::string>(std::istream &stream, std::string &str) { std::getline(stream, str); stream.clear(); stream.ignore(std::numeric_limits<std::streamsize>::max(), '\n'); return true; }; template<typename Function> bool sInStream(std::istream &stream, std::string& str, Function const& function) { std::getline(stream, str); stream.clear(); stream.ignore(std::numeric_limits<std::streamsize>::max(), '\n'); if (function(str)) { return true; } else return false; }; #endif //S_IN_STREAM_H |
Et le code de test :
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 | #include "sInStream.h" #include <string> bool foo(const float fl) { return fl >= 0.f && fl <= 1.f; }; int main() { auto uint = 0u; do { std::cout << "Entrez un nombre entier entre 1 et 10\n"; } while (!sInStream<unsigned int>(std::cin, uint, [](int var) {return var > 1 && var < 10; })); float fl{}; do { std::cout << "Entrez un à virgule nombre entre 0 et 1\n"; } while (!sInStream<float>(std::cin, fl, foo)); std::string str{}; do { std::cout << "Entrez votre nom :\n"; } while (!sInStream<std::string>(std::cin, str)); std::cout << "uint = " << uint << "\nfl = " << fl << "\nVous vous appellez " << str << "\n"; std::cin >> uint; } |
Merci encore et A++