/**
 *
 * @File :
 *
 * @Authors : D. Mathieu
 *
 * @Date : 25/03/2000
 *
 * @Version : V1.0
 *
 * @Synopsis : Test de C++ n° 2
 *
 **/
#include <iostream>
#include <iomanip>    // setw()
#include <string>

using namespace std;

// Question 1 : voir test question 1

#include <vector>
#include <stdexcept> // out_of_range

template <class T>
class CVector : public vector <T>
{
  public :
    T & at (size_type n) throw (out_of_range);

    // Les véritables profils indiqués dans la norme sont les suivants :
    /** /
    reference       & at (size_type n);
    const_reference & at (size_type n) const;

    // La première fonction renvoie une référence à un objet T. Le type
    //   "reference" est exporté par la classe vector. C'est une
    //   adresse mémoire.
    //   Elle permet d'affecter une valeur à un élément du vecteur
    // La seconde fonction renvoie une référence à un objet T constant,
    //   dont le type est le type standard const_reference, exporté
    //   par la classe vector.
    //   Elle permet d'utiliser un élément du vecteur partout où est utilisé un
    //   utilisé un objet de type const T.
    /**/

}; // CVector

template <class T>
inline T & CVector <T>::at (size_type n) throw (out_of_range)
{
    if (n < 0 || n >= size()) throw out_of_range ("Indice invalide");
    return (*this)[n];

} // at()

// Question 2a

#include <fstream>

void CopyFile (const string & Source, const string & Destination)
{
    ifstream is (Source.     c_str());
    ofstream os (Destination.c_str());
    char Octet;
    for (is.get (Octet); !is.eof(); is.get (Octet)) os << Octet;

} // CopyFile()

// Question 3a

void ComptCaract (const string & Source, vector <char> & VCaract, vector <unsigned> & VCpt)
{
    ifstream is (Source.     c_str());

    char Octet;
    for (is.get (Octet); !is.eof(); is.get (Octet))
    {
        unsigned i;
        for (i = 0; i < VCaract.size(); ++i) if (VCaract [i] == Octet) break;
        if (i == VCaract.size())
        {
            VCaract.push_back (Octet);
            VCpt.push_back    (0);
        }
        ++VCpt [i];
    }

} // ComptCaract()

// Question 3b

void EssaiComptCaract (void)
{
    string Source;
    cout << "Nom du fichier : ";
    getline (cin, Source);
    ifstream is (Source.c_str());

    vector <char>     VCar;
    vector <unsigned> VCompteur;
    ComptCaract (Source, VCar, VCompteur);
    for (unsigned i = 0; i < VCar.size(); ++i)
        if (VCar [i] >= 20)
            cout << "caractere : " << VCar [i] << " : " << setw (5)
                 << VCompteur [i] << endl;

} // EssaiComptCaract()

int main (int argc, char * argv [])
{
    // Test question 1

    CVector <int> VInt;
    VInt.resize (10);
    VInt.at (1) = 10;
    cout << VInt.at (1) << endl;
    try
    {
        VInt.at (11) = 20;
    }
    catch (out_of_range & e)
    {
        cerr << e.what() << endl;
    }
    try
    {
        cout << VInt.at (11) << endl;
    }
    catch (out_of_range & e)
    {
        cerr << e.what() << endl;
    }

    // Question 2c

    if (argc != 3)
    {
        cerr << "usage : CopyFile <source> <destination>\n";
        return 12;
    }

    // Test question 2b

    CopyFile (argv [1], argv [2]);

    // Test question 3b

    EssaiComptCaract ();

    return 0;

} // main()