Loading lang_cpp_01_basics...
//----------------------------------------------------------------------------
#ifndef MODULE_HPP #define MODULE_HPP
void dummy_function(void);
double use_arguments(int argc, char **argv);
#endif // MODULE_HPP
//----------------------------------------------------------------------------
//----------------------------------------------------------------------------
#include "module.hpp" #include <stdio.h> // standard C header-file #include <math.h> // standard C header-file
void dummy_function(void) { printf("~~~~ %s() ~~~~\n", __func__); }
double use_arguments(int argc, char **argv) { double sqr_sum=0.0; for(int i=0; i<argc; ++i) { printf("argv[%d]=<%s>\n", i, argv[i]); double value; if(sscanf(argv[i], " %lg ", &value)==1) { sqr_sum+=value*value; } } return sqrt(sqr_sum); }
//----------------------------------------------------------------------------
//----------------------------------------------------------------------------
#include "module.hpp" #include <stdio.h> // standard C header-file
int main(int argc, char **argv) { printf("~~~~ entering %s() ~~~~\n", __func__); dummy_function(); const double r=use_arguments(argc, argv); printf("use_arguments() gave %g\n", r); printf("~~~~ leaving %s() ~~~~\n", __func__); return 0; }
//----------------------------------------------------------------------------
<cstdio>,
<cmath>,
<cstdint>,
<cstdio>,
<cmath>...) incluent probablement ceux du C (pour des raisons pratiques de réalisation).
<stdio.h>et
<math.h>) et la désignation des fonctionnalités visées (printf(), sscanf() et sqrt()) avec le préfixe std::.
<unistd.h>, voir
man 2 execve), peuvent toujours être utilisées comme en langage C dans l'espace de noms global (C++ préserve la compatibilité avec le langage C).
namespace enib { namespace dept_elec { namespace utils { /* ce code source concerne des fonctionnalités utilitaires développées par le département Électronique de l'ENIB... */ } namespace proj_a { /* ce code source concerne le projet proj_a développé par le département Électronique de l'ENIB... */ } } }
namespace enib { namespace dept_info { namespace utils { /* ce code source concerne des fonctionnalités utilitaires développées par le département Informatique de l'ENIB... */ } namespace proj_b { /* ce code source concerne le projet proj_b développé par le département Informatique de l'ENIB... */ } } }
namespace enib { namespace dept_meca { namespace utils { /* ce code source concerne des fonctionnalités utilitaires développées par le département Mécatronique de l'ENIB... */ } namespace proj_c { /* ce code source concerne le projet proj_c développé par le département Mécatronique de l'ENIB... */ } } }
namespace utils_m = dept_meca::utils; namespace utils_i = dept_info::utils;
using enib::dept_info::proj_b::useful_computation;
namespace s4prc {
} // namespace s4prc
<<✍
std::cerr << "This is a message!\n"; std::cout << "Twice my variable x gives " << 2*x << '\n';
<iostream>(flux d'entrée/sortie). Intervenez alors sur les fichiers prog.cpp et module.cpp afin de remplacer l'usage de std::printf() par celui de std::cout.
//----------------------------------------------------------------------------
#ifndef S4PRC_MODULE_HPP #define S4PRC_MODULE_HPP
namespace s4prc {
void dummy_function(void);
double use_arguments(int argc, char **argv);
} // namespace s4prc
#endif // S4PRC_MODULE_HPP
//----------------------------------------------------------------------------
//----------------------------------------------------------------------------
#include "module.hpp" #include <cstdio> // <stdio.h> features exposed in the ``std'' C++ namespace #include <cmath> // <math.h> features exposed in the ``std'' C++ namespace #include <iostream> // C++ I/O streams (``std'' namespace)
namespace s4prc {
void dummy_function(void) { std::cout << "~~~~ " << __func__ << "() ~~~~\n"; }
double use_arguments(int argc, char **argv) { double sqr_sum=0.0; for(int i=0; i<argc; ++i) { std::cout << "argv[" << i << "]=<" << argv[i] << ">\n"; double value; if(std::sscanf(argv[i], " %lg ", &value)==1) { sqr_sum+=value*value; } } return std::sqrt(sqr_sum); }
} // namespace s4prc
//----------------------------------------------------------------------------
//----------------------------------------------------------------------------
#include "module.hpp" #include <iostream> // C++ I/O streams (``std'' namespace)
int main(int argc, char **argv) { std::cout << "~~~~ entering " << __func__ << "() ~~~~\n"; s4prc::dummy_function(); const double r=s4prc::use_arguments(argc, argv); std::cout << "use_arguments() gave " << r << '\n'; std::cout << "~~~~ leaving " << __func__ << "() ~~~~\n"; return 0; }
//----------------------------------------------------------------------------
void my_function(int a, double d); int my_function(int a, double d); // error: differs only with return type! // ... my_function(2, 3.4); // which one would be called?
int main(); il s'agit de la version de cette fonction qui ignore la ligne de commande.
int main(void)ici)✍
void display(int value) { std::cout << "an integer: " << value << '\n'; }
const char *et qu'elle l'injecte dans la sortie standard juste avant ce qu'elle injectait auparavant.
"here is "par exemple) après la valeur entière lors de l'appel à cette fonction.
void display(int value) { display(value, ""); }
void warn(const char *msg, bool confirm=true);
int place(int i=0, int j=-1);
warn("Watch out!", false); // all parameters provided warn("Watch out!"); // same as warn("Watch out!", true);
place(5, 8); // all parameters provided place(5); // same as place(5,-1); place(); // same as place(0,-1);
void warn(bool confirm=true, const char *msg); // non-default after default!
int place(int i=0, int j=i); // using ``i'' which value is unknown until run-time!
const int my_value=9; s4prc::display(my_value); s4prc::display(my_value*2, "and also "); s4prc::display(my_value*1.5, "but now "); s4prc::display("Hello", "and why not ");
struct Vec3D { double x, y, z; };
void display(Vec3D value, const char *prefix) { std::cout << prefix << "a 3D vector: {" << value.x << ", " << value.y << ", " << value.z << "}\n"; }
struct Vec3D { double x, y, z; };imposerait d'utiliser
struct Vec3Dpour désigner ce type.
typedef struct { double x, y, z; } Vec3D;; en langage C++ ce n'est pas nécessaire.
const s4prc::Vec3D v={1.1, 2.2, 3.3}; s4prc::display(v, "and even ");
display(v, "ADL helps displaying ");
Vec3D add(Vec3D lhs, // left-hand side Vec3D rhs) // right-hand side { return Vec3D{lhs.x+rhs.x, lhs.y+rhs.y, lhs.z+rhs.z}; }
Vec3D negate(Vec3D rhs) // right-hand side (unary operation) { return Vec3D{-rhs.x, -rhs.y, -rhs.z}; }
Vec3D multiply(Vec3D lhs, // left-hand side double rhs) // right-hand side { return Vec3D{lhs.x*rhs, lhs.y*rhs, lhs.z*rhs}; }
v3=negate(add(v1, multiply(v2, 2.0))); // the intented meaning was v3=-(v1+v2*2.0);
operator<<qui donnent une toute autre signification à l'opérateur de décalage (étudié dans cette section du cours S3-PRC) lorsqu'elles combinent un flux avec d'autres types.
const s4prc::Vec3D v1={1.1, 2.2, 3.3}, v2={40.04, 50.05, 60.06}; display(-(v1+v2*2.0), "ADL helps displaying ");
inline Vec3D operator*(double lhs, // left-hand side Vec3D rhs) // right-hand side { return rhs*lhs; // multiplication of a vector by a scalar is commutative }
//----------------------------------------------------------------------------
#ifndef S4PRC_DISPLAY_HPP #define S4PRC_DISPLAY_HPP
namespace s4prc {
void display(int value, const char *prefix="");
void display(double value, const char *prefix="");
void display(const char *value, const char *prefix="");
} // namespace s4prc
#endif // S4PRC_DISPLAY_HPP
//----------------------------------------------------------------------------
//----------------------------------------------------------------------------
#include "display.hpp" #include <iostream>
namespace s4prc {
void display(int value, const char *prefix) { std::cout << prefix << "an integer: " << value << '\n'; }
void display(double value, const char *prefix) { std::cout << prefix << "a real: " << value << '\n'; }
void display(const char *value, const char *prefix) { std::cout << prefix << "a string: " << value << '\n'; }
} // namespace s4prc
//----------------------------------------------------------------------------
//----------------------------------------------------------------------------
#ifndef S4PRC_VEC3D_HPP #define S4PRC_VEC3D_HPP
namespace s4prc {
struct Vec3D { double x, y, z; };
void display(Vec3D value, const char *prefix="");
Vec3D operator+(Vec3D lhs, // left-hand side Vec3D rhs); // right-hand side
Vec3D operator-(Vec3D rhs); // right-hand side (unary operator)
Vec3D operator*(Vec3D lhs, // left-hand side double rhs); // right-hand side
inline Vec3D operator*(double lhs, // left-hand side Vec3D rhs) // right-hand side { return rhs*lhs; // multiplication of a vector by a scalar is commutative }
double // dot-product operator*(Vec3D lhs, // left-hand side Vec3D rhs); // right-hand side
Vec3D // cross-product operator^(Vec3D lhs, // left-hand side Vec3D rhs); // right-hand side
} // namespace s4prc
#endif // S4PRC_VEC3D_HPP
//----------------------------------------------------------------------------
//----------------------------------------------------------------------------
#include "vec3D.hpp" #include <iostream>
namespace s4prc {
void display(Vec3D value, const char *prefix) { std::cout << prefix << "a 3D vector: {" << value.x << ", " << value.y << ", " << value.z << "}\n"; }
Vec3D operator+(Vec3D lhs, // left-hand side Vec3D rhs) // right-hand side { return Vec3D{lhs.x+rhs.x, lhs.y+rhs.y, lhs.z+rhs.z}; }
Vec3D operator-(Vec3D rhs) // right-hand side (unary operator) { return Vec3D{-rhs.x, -rhs.y, -rhs.z}; }
Vec3D operator*(Vec3D lhs, // left-hand side double rhs) // right-hand side { return Vec3D{lhs.x*rhs, lhs.y*rhs, lhs.z*rhs}; }
double // dot-product operator*(Vec3D lhs, // left-hand side Vec3D rhs) // right-hand side { return lhs.x*rhs.x+lhs.y*rhs.y+lhs.z*rhs.z; }
Vec3D // cross-product operator^(Vec3D lhs, // left-hand side Vec3D rhs) // right-hand side { return Vec3D{lhs.y*rhs.z-lhs.z*rhs.y, lhs.z*rhs.x-lhs.x*rhs.z, lhs.x*rhs.y-lhs.y*rhs.x}; }
} // namespace s4prc
//----------------------------------------------------------------------------
//----------------------------------------------------------------------------
#include "display.hpp" #include "vec3D.hpp"
int main() { const int my_value=9; s4prc::display(my_value); s4prc::display(my_value*2, "and also "); s4prc::display(my_value*1.5, "but now "); s4prc::display("Hello", "and why not "); const s4prc::Vec3D v={1.1, 2.2, 3.3}; s4prc::display(v, "and even "); const s4prc::Vec3D v1={1.1, 2.2, 3.3}, v2={40.04, 50.05, 60.06}; display(-(3.0*v1+v2*2.0), "ADL helps displaying "); display(v1^v2); // ADL works here too s4prc::display(v1*v2); return 0; }
//----------------------------------------------------------------------------
#include <cstdint>et
#include <cstddef>(comme vu ici) pour fournir les types std::int8_t...std::uint64_t, std::size_t, std::ptrdiff_t.
'\0'(voir cette section du cours S3-PRC).
<string>(sans la lettre c) expose un type std::string qui prend complètement en charge cette notion✍
std::string enumerate_chars(std::string txt, // a string is safely received as a parameter char separator) { std::string result; // default initialisation yields an empty string for(const auto &c: txt) // for each character in a string { if(!empty(result)) // test whether a string is empty or not { result+=separator; // append a character to a string } result+=c; // append a character to a string } return result; // a string is safely transmitted as a return value }
'|'comme valeur par défaut pour le paramètre separator. Le programme principal doit définir et appeler une fonction test_string().
std::string msg="Hi there!";(ou encore
std::string msg{"Hi there!"};✍
std::string result="";✍
==,
!=,
<,
<=,
>ou
>=) sur votre chaîne msg et des valeurs littérales afin de constater qu'ils se comportent bien selon l'intuition.
const std::string::size_type pos=msg.find(' '); if(pos!=std::string::npos) { // character ' ' was found at position pos }
const auto pos=msg.find(' '); if(pos!=std::string::npos) { // character ' ' was found at position pos }
const auto pos=msg.find(' '); if(pos!=msg.npos) { // character ' ' was found at position pos }
if(const auto pos=msg.find(' '); pos!=msg.npos) { // character ' ' was found at position pos }
for(int i=0; i<n; ++i) { // do something with i }
int i; // this variable exists before and after the loop! for(i=0; i<n; ++i) { // do something with i }
std::cout << "found <" << msg[pos] << "> at position " << pos << '\n';
'\0'à la position choisie ; faites alors de même en utilisant l'opérateur [] sur msg, puis affichez à nouveau cette chaîne et l'énumération de ses caractères.
'\0'.
bool // success parse_int(std::string txt, int *out_value)
<cstdio>issue de la bibliothèque standard du langage C (voir cette section du cours S3-PRC).
<array>expose un type std::array<T, N> qui nous permet désormais de considérer un tableau de la même façon que n'importe quel autre type✍
std::array<double, 3>.
double coord[3];en langage C. Produisez alors l'affichage dans la sortie standard de ce qu'indiquent les fonctions empty() et size() appliquées à coord✍
{ 1.1, 2.2, 3.3 }.
double magnitude(std::array<int, 3> coord)
<cmath>) de cette somme (c'est-à-dire la norme du vecteur de coordonnées coord).
void normalise(std::array<int, 3> coord)
using dbl3 = std::array<double, 3>;
<vector>.
std::vector<double>.
{ 1.1, 2.2, 3.3 }à la variable coord et produisez une nouvelle fois les affichages précédents.
std::vector<double>en lieu et place de s4prc::dbl3.
std::vector<double>avec celles qui étaient dédiées au type s4prc::dbl3 traduit une volonté des concepteurs de la bibliothèque standard de favoriser la réutilisabilité du code : si nous savons exprimer un traitement avec un type, il est très probable que ce même traitement puisse s'appliquer à un autre type ayant une sémantique assez proche.
//----------------------------------------------------------------------------
#ifndef S4PRC_USE_STRING_HPP #define S4PRC_USE_STRING_HPP
#include <string>
namespace s4prc {
std::string enumerate_chars(std::string txt, char separator='|');
bool // success parse_int(std::string txt, int *out_value);
} // namespace s4prc
#endif // S4PRC_USE_STRING_HPP
//----------------------------------------------------------------------------
//----------------------------------------------------------------------------
#include <iostream> #include <cstdio> #include "use_string.hpp"
namespace s4prc {
std::string enumerate_chars(std::string txt, // a string is safely received as a parameter char separator) { std::string result; // default initialisation yields an empty string for(const auto &c: txt) // for each character in a string { if(!empty(result)) // test whether a string is empty or not { result+=separator; // append a character to a string } result+=c; // append a character to a string } return result; // a string is safely transmitted as a return value }
bool // success parse_int(std::string txt, int *out_value) { const char *cstr=data(txt); // access C-style string inside C++ string return std::sscanf(cstr, " %d ", out_value)==1; // C-style string analysis }
} // namespace s4prc
//----------------------------------------------------------------------------
//----------------------------------------------------------------------------
#ifndef S4PRC_USE_ARRAY_HPP #define S4PRC_USE_ARRAY_HPP
#include <array>
namespace s4prc {
using dbl3 = std::array<double, 3>;
double magnitude(dbl3 coord);
dbl3 normalise(dbl3 coord);
} // namespace s4prc
#endif // S4PRC_USE_ARRAY_HPP
//----------------------------------------------------------------------------
//----------------------------------------------------------------------------
#include "use_array.hpp" #include <cmath>
namespace s4prc {
double magnitude(dbl3 coord) { double sqr_sum=0.0; for(const auto &elem: coord) { sqr_sum+=elem*elem; } return std::sqrt(sqr_sum); }
dbl3 normalise(dbl3 coord) { const double mag=magnitude(coord); if(mag!=0.0) { for(auto &elem: coord) { elem/=mag; } } return coord; }
} // namespace s4prc
//----------------------------------------------------------------------------
//----------------------------------------------------------------------------
#ifndef S4PRC_USE_VECTOR_HPP #define S4PRC_USE_VECTOR_HPP
#include <vector>
namespace s4prc {
double magnitude(std::vector<double> coord);
std::vector<double> normalise(std::vector<double> coord);
} // namespace s4prc
#endif // S4PRC_USE_VECTOR_HPP
//----------------------------------------------------------------------------
//----------------------------------------------------------------------------
#include "use_vector.hpp" #include <cmath>
namespace s4prc {
double magnitude(std::vector<double> coord) { double sqr_sum=0.0; for(const auto &elem: coord) { sqr_sum+=elem*elem; } return std::sqrt(sqr_sum); }
std::vector<double> normalise(std::vector<double> coord) { const double mag=magnitude(coord); if(mag!=0.0) { for(auto &elem: coord) { elem/=mag; } } return coord; }
} // namespace s4prc
//----------------------------------------------------------------------------
//----------------------------------------------------------------------------
#include <iostream> #include "use_string.hpp" #include "use_array.hpp" #include "use_vector.hpp"
void test_string(int argc, char **argv) { std::cout << "\n~~~~ " << __func__ << "() ~~~~\n"; std::string msg="Hi there!"; std::cout << "message is <" << msg << "> i.e. <" << s4prc::enumerate_chars(msg) << ">\n"; if(msg!="Hello") { std::cout << '<' << msg << "> is not <Hello>\n"; } if(msg>"Hello") { std::cout << '<' << msg << "> comes after <Hello>\n"; } if(msg<"Hooray") { std::cout << '<' << msg << "> comes before <Hooray>\n"; } // actual return-type is std::string::size_type if(const auto pos=msg.find(' '); pos!=msg.npos) { std::cout << "found <" << msg[pos] << "> at position " << pos << '\n'; msg[pos]='\0'; // try to cut the string as we would do in C std::cout << "message changed to <" << msg << "> i.e. <" << s4prc::enumerate_chars(msg) << ">\n"; msg.resize(pos); // actually make the string end here std::cout << "... then to <" << msg << "> i.e. <" << s4prc::enumerate_chars(msg) << ">\n"; } std::cout << "message size is " << size(msg) << ", thus empty() returns " << (empty(msg) ? "true\n" : "false\n"); msg.clear(); std::cout << "message size is now " << size(msg) << ", thus empty() returns " << (empty(msg) ? "true\n" : "false\n"); for(int i=0; i<argc; ++i) { const std::string str=argv[i]; int value; if(s4prc::parse_int(str, &value)) { std::cout << "integer " << value << " found in <" << str << ">\n"; } else { std::cout << "cannot parse <" << str << "> as an integer!\n"; } } }
void test_array() { std::cout << "\n~~~~ " << __func__ << "() ~~~~\n"; s4prc::dbl3 coord; std::cout << "empty(coord)=" << empty(coord) << " size(coord)=" << size(coord) << '\n'; std::cout << "sizeof(coord)=" << sizeof(coord) << " sizeof(coord[0])=" << sizeof(coord[0]) << '\n'; std::cout << "coord[0]=" << coord[0] << " coord[1]=" << coord[1] << " coord[2]=" << coord[2] << '\n'; coord={1.1, 2.2, 3.3}; std::cout << "after assignment: coord[0]=" << coord[0] << " coord[1]=" << coord[1] << " coord[2]=" << coord[2] << '\n'; std::cout << "original magnitude(coord)=" << s4prc::magnitude(coord) << '\n'; coord=s4prc::normalise(coord); std::cout << "modified magnitude(coord)=" << s4prc::magnitude(coord) << '\n'; }
void test_vector() { std::cout << "\n~~~~ " << __func__ << "() ~~~~\n"; std::vector<double> coord; std::cout << "initial: empty(coord)=" << empty(coord) << " size(coord)=" << size(coord) << " sizeof(coord)=" << sizeof(coord) << '\n'; coord={1.1, 2.2, 3.3}; std::cout << "after assignment: empty(coord)=" << empty(coord) << " size(coord)=" << size(coord) << " sizeof(coord)=" << sizeof(coord) << '\n'; std::cout << "coord[0]=" << coord[0] << " coord[1]=" << coord[1] << " coord[2]=" << coord[2] << '\n'; coord.emplace_back(4.4); coord.emplace_back(5.5); while(!empty(coord)) { std::cout << "size(coord)=" << size(coord) << " coord.front()=" << coord.front() << " coord.back()=" << coord.back() << '\n'; std::cout << "original magnitude(coord)=" << s4prc::magnitude(coord) << '\n'; coord=s4prc::normalise(coord); std::cout << "modified magnitude(coord)=" << s4prc::magnitude(coord) << '\n'; coord.pop_back(); } }
int main(int argc, char **argv) { test_string(argc, argv); test_array(); test_vector(); return 0; }
//----------------------------------------------------------------------------
<type_traits>expose notamment de nombreuses fonctionnalités pour raisonner sur les propriétés des types.
std::vector<int> integers_from_args(std::vector<std::string> args) { std::vector<int> result; // to be completed, later on return result; }
std::vector<std::string> args{argv, argv+argc};
for(int i=2;i<6;++i): la valeur 6 (2+4) qui sert de limite ne fait pas partie de la séquence
2 3 4 5.
char **donc argv est équivalent à
&argv[0]et argv+argc est équivalent à
&argv[argc], il ne s'agit que d'arithmétique des pointeurs (voir cette section du cours S3-PRC).
static_assert(sizeof(int)>=4, "larger integers are required in this application");
>=8par exemple), cela fera apparaître explicitement le message indiqué dans static_assert() parmi ceux que le compilateur produit✍
static_assert(sizeof(values[0])>=4, "larger integers are required as arguments");
if constexprintroduite dans C++17, vont également dans cette direction (voir cette section).
for(const auto &elem: args) { result.emplace_back(std::stoi(elem)); }
<string>, afin qu'elle fournisse un entier qui complêtera le tableau dynamique result.
for(const auto &elem: args) { try { result.emplace_back(std::stoi(elem)); } catch(const std::invalid_argument &e) { std::cerr << "<" << elem << "> does not look like an integer!\n"; } }
try { }englobe une portion de code dans laquelle nous soupçonnons le risque d'émission d'une exception (ici la conversion vers un entier de la chaîne désignée par elem, suivie de l'ajout au résultat).
catch( ) { }dont le rôle est de réagir au type d'exception spécifié entre parenthèses✍
const std::invalid_argument &ematérialise le passage par référence constante d'une donnée de type std::invalid_argument que nous désignerons par e en nous interdisant de la modifier.
try { }une exception est levée, ce bloc est immédiatement terminé (même s'il lui restait des instructions à exécuter jusqu'à son accolade fermante), et l'exécution se poursuit par le premier bloc
catch( ) { }dont le type correspond à celui de l'exception émise✍
<stdexcept>est nécessaire pour prendre connaissance du type std::invalid_argument.
catch( ) { }n'est satisfaisant dans le contexte courant, l'exception est propagée au contexte appelant ; si lui-même est constitué d'un bloc
try { }disposant du bloc
catch( ) { }adapté, alors la propagation s'arrêtera à ce dernier, sinon la remontée se poursuit de la même façon jusqu'à atteindre en dernier recours std::terminate() qui mettra fin à l'exécution du programme.
<climits>qui correspondent au style d'écriture du langage C (voir cette section du cours S3-PRC).
std::numeric_limits<int>::min()et
std::numeric_limits<int>::max()du fichier d'en-tête standard
<limits>.
catch( ) { }immédiatement à la suite du précédent afin de réagir à cette nouvelle anomalie.
<stdexcept>.
catch(const std::exception &e) { std::cerr << "integer conversion failure on <" << elem << ">: " << e.what() << '\n'; }
if(empty(result)) { throw std::runtime_error{"integer arguments were expected"}; } return result;
<stdexcept>.
try { }disposant d'un bloc
catch( ) { }en mesure de capturer l'exception créée ici.
catch( ) { }distincts) ; seulement, dans la pratique, on se confronte à la vanité de trouver une réponse appropriée à chacune de ces causes...
//----------------------------------------------------------------------------
#ifndef S4PRC_ARGS_HPP #define S4PRC_ARGS_HPP
#include <vector> #include <string>
namespace s4prc {
std::vector<int> integers_from_args(std::vector<std::string> args);
} // namespace s4prc
#endif // S4PRC_ARGS_HPP
//----------------------------------------------------------------------------
//----------------------------------------------------------------------------
#include "args.hpp" #include <iostream> #include <stdexcept>
namespace s4prc {
std::vector<int> integers_from_args(std::vector<std::string> args) { std::vector<int> result; for(const auto &elem: args) { try { result.emplace_back(std::stoi(elem)); } catch(const std::invalid_argument &e) { std::cerr << "<" << elem << "> does not look like an integer!\n"; } catch(const std::exception &e) { std::cerr << "integer conversion failure on <" << elem << ">: " << e.what() << '\n'; } } if(empty(result)) { throw std::runtime_error{"integer arguments were expected"}; } return result; }
} // namespace s4prc
//----------------------------------------------------------------------------
//----------------------------------------------------------------------------
#include <iostream> #include "args.hpp"
static_assert(sizeof(int)>=4, "larger integers are required in this application");
int main(int argc, char **argv) { std::vector<std::string> args{argv, argv+argc}; const auto values=s4prc::integers_from_args(args); static_assert(sizeof(values[0])>=4, "larger integers are required as arguments"); std::cout << "values:"; for(const auto &elem: values) { std::cout << ' ' << elem; } std::cout << '\n'; return 0; }
//----------------------------------------------------------------------------