Choisissez votre style : style 1,    style 2,    sans commentaire,    impression,    ancien.

Correction
Templates

Exercice 1

Exercice 1 : chemin parcouru

Exercice n°70 (pages 183 et 379) de l'ouvrage C++ par la pratique.

Voici une solution «avancée» (ici le code complet) où plusieurs concepts du cours se cumulent. Étudiez bien la solution, comparez avec ce que vous avez fait vous-même.

#include <iostream>
#include <vector>
#include <iterator>  // pour ostream_iterator -- cours de la semaine prochaine
using namespace std;
 
// ----------------------------------------------------------------------
// déclaration de la classe générique
template<typename type> class Matrice;
 
// --------------------------------------------------------------------
// opérateur générique d'affichage pour la classe Matrice
template<typename type>
ostream& operator<<(ostream& output, const Matrice<type>& M)
{
  for (auto const& ligne : M.contenu) {
    copy(ligne.begin(), ligne.end(),
         ostream_iterator<type>(output, " "));
    output << endl;
  }
  return output;
}
 
// --------------------------------------------------------------------
// opérateur générique de saisie
template<typename type>
istream& operator>>(istream& input, Matrice<type>& M)
{
  for (auto& ligne : M.contenu) {
    for (auto& element : ligne) {
      input >> element;
    }
  }
 
  return input;
}
 
// --------------------------------------------------------------------
// définition de la classe générique Matrice
template<typename type>
class Matrice {
  friend ostream& operator<<<type>(ostream&, const Matrice&);
  friend istream& operator>><type>(istream&, Matrice&);
 
public:
  // un nouveau type pour les exceptions
  enum error { WRONG_SIZES };
 
  Matrice(size_t n, size_t m, type val = type()) 
    : contenu(n, vector<type>(m, val)) {}
  Matrice() = default ; // rappelle le constructeur par défaut
 
  Matrice& operator*=(const Matrice&);
  Matrice  operator*(const Matrice& right) const {
    return (Matrice(*this) *= right);
  }
 
protected:
  vector< vector<type> > contenu;
};
 
// ----------------------------------------------------------------------
template<typename type>
Matrice<type>& Matrice<type>::operator*=(const Matrice<type>& M2)
{
  if (contenu[0].size() != M2.contenu.size()) throw WRONG_SIZES;
 
  Matrice M1(*this);
 
  contenu.clear();
  for (size_t i(0); i < M1.contenu.size(); ++i) {
    contenu.push_back(vector<type>(M2.contenu[0].size()));
 
    for (size_t j(0); j < M2.contenu[0].size(); ++j) {
      contenu[i][j] = type(); // = 0
      for (size_t k(0); k < M2.contenu.size(); ++k) 
	contenu[i][j] += M1.contenu[i][k] * M2.contenu[k][j];
    }
  }
 
  return *this;
}
 
// ----------------------------------------------------------------------
Matrice<double> saisie_matrice() {
  cout << "Saisie d'une matrice :" << endl;
  cout << "  Nombre de lignes : ";
  size_t n;
  cin >> n;
  cout << "  Nombre de colonnes : ";
  size_t m;
  cin >> m;
 
  Matrice<double> M(n,m);
  cout << "Entrez la matrice :" << endl;
  cin >> M;
 
  return M;
}
 
// ----------------------------------------------------------------------
int main()
{
  Matrice<double> M1(saisie_matrice());
  Matrice<double> M2(saisie_matrice());
  Matrice<double> M;
 
  try {
    M = M1 * M2;
    cout << "Résultat :" << endl << M << endl;
  }
  catch (Matrice<double>::error e) {
    switch (e) {
    case Matrice<double>::WRONG_SIZES:
      cerr << "Tailles imcompatibles pour la multiplication de matrices !"
           << endl;
      break;
    default:
      cerr << "Multiplication de matrices impossible !" << endl;
      break;
    }
  }
 
  return 0;
}
 

Dernière mise à jour : $Date: 2012-11-09 14:16:46 +0100 (ven 09 nov 2012) $  ($Revision: 191 $)