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 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142
| #include <vector> // std::vector
#include <string> // std::string
#include <algorithm> // std::copy,
#include <functional> // std::unary_function
#include <iterator> // std::ostream_iterator, std::back_inserter
#include <ostream> // std::ostream
#include <iostream> // std::cout
#include <cassert> // assert
#include <luc_lib/copy_if.hpp>
/*-------------------------------[ Ligne de la base ]------------------------*/
// Définition à la va-vite d'une ligne.
struct line_type : public std::vector<std::string> {
template <typename IterIn>
line_type(IterIn first, IterIn last)
: std::vector<std::string>(first, last) {}
friend std::ostream & operator<<(
std::ostream & os,
const line_type & l)
{
std::copy(l.begin(),l.end(),
std::ostream_iterator<std::string>(os, " - "));
return os;
}
};
/*-------------------------------[ Clauses de recherche ]--------------------*/
// Clause Where pour sélectionner certaines lignes seulement
class Where : std::unary_function<std::vector<std::string>, bool>
{
typedef std::vector<std::string> line_type;
typedef line_type::size_type field_id_type;
typedef line_type::value_type field_type;
field_id_type field_nb_;
field_type field_;
public:
Where(field_id_type id, const field_type & f)
: field_nb_(id), field_(f) {}
bool operator() (const line_type & l) const {
return l[field_nb_] == field_;
}
};
// Pour définir des ET-logiques entre clauses Where
template <typename P1, typename P2>
class PredicateAnd : std::unary_function<std::vector<std::string>, bool>
{
P1 p1_;
P2 p2_;
public:
PredicateAnd(P1 p1, P2 p2) : p1_(p1), p2_(p2) {}
bool operator() (const line_type & l) const {
return p1_(l) && p2_(l);
}
};
// Pour écrire plus simplement les fameux ET-logiques
template <typename P1, typename P2>
PredicateAnd<P1,P2> operator&&(P1 p1, P2 p2) {
return PredicateAnd<P1,P2>(p1, p2);
}
// Faire la même chose pour les OU-logique
/*-------------------------------[ Prédicat de comparaison ]-----------------*/
// Prédicat pour trier des lignes suivant un champ donné
class CmpCol {
unsigned int col_;
public:
CmpCol(unsigned int c) : col_(c) {}
bool operator()(
const line_type & v1,
const line_type & v2) const
{
assert(v1.size() >= col_);
assert(v2.size() >= col_);
return v1[col_] < v2[col_];
}
};
/*===============================[ Prog Princ ]==============================*/
int main (int argc, char **argv)
{
// 0- Initialise la base initiale
const char* lig1[] = { "Toto", "maison", "C" };
const char* lig2[] = { "Titi", "cabane", "B" };
const char* lig3[] = { "Tutu", "tente", "A" };
const char* lig4[] = { "Tata", "appart", "E" };
const char* lig5[] = { "Bobo", "maison", "D" };
const char* lig6[] = { "Baba", "maison", "D" };
typedef std::vector<line_type> base_type;
base_type basePrincipale;
basePrincipale.push_back(line_type(lig1, lig1+3));
basePrincipale.push_back(line_type(lig2, lig2+3));
basePrincipale.push_back(line_type(lig3, lig3+3));
basePrincipale.push_back(line_type(lig4, lig4+3));
basePrincipale.push_back(line_type(lig5, lig5+3));
basePrincipale.push_back(line_type(lig6, lig6+3));
// Affiche base initiale
std::copy(basePrincipale.begin(),basePrincipale.end(),
std::ostream_iterator<line_type>(std::cout, "\n"));
// extrait une sous-base avec le second critère : maison
base_type b2;
luc_lib::copy_if(basePrincipale.begin(),basePrincipale.end(),
std::back_inserter(b2), Where(1, "maison"));
std::cout << "\n--------\n";
std::copy(b2.begin(),b2.end(),
std::ostream_iterator<line_type>(std::cout, "\n"));
// extrait une sous-base avec les derniers critères
base_type b3;
luc_lib::copy_if(basePrincipale.begin(),basePrincipale.end(),
std::back_inserter(b3), Where(1, "maison") && Where(2,"D"));
std::cout << "\n--------\n";
std::copy(b3.begin(),b3.end(),
std::ostream_iterator<line_type>(std::cout, "\n"));
// On trie le résultat suivant le premier champ (pas de tri pour
// l'instant)
std::sort(b3.begin(),b3.end(), CmpCol(0));
std::cout << "\n--------\n";
std::copy(b3.begin(),b3.end(),
std::ostream_iterator<line_type>(std::cout, "\n"));
// Tri de la base initiale suivant le champ 2
base_type & b = basePrincipale;
std::sort(b.begin(),b.end(), CmpCol(1));
std::cout << "\n--------\n";
std::copy(b.begin(),b.end(),
std::ostream_iterator<line_type>(std::cout, "\n"));
std::cout.flush();
return 0;
} |