IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
logo
Sommaire > Les Collections de données
        Comment récupérer le tableau mémoire d'un CArray ?
        Comment déclarer un CArray à deux dimensions ?
        Comment faire une CList à deux dimensions ?
        Comment implémenter l'opérateur d'affection dans une CMap ?



Comment récupérer le tableau mémoire d'un CArray ?
Créé le 22/01/2007[haut]
auteur : Farscape
Imaginons la problématique suivante :
Je dispose d'un tableau de double à gérer dynamiquement, une solution MFC simple est d'utiliser un CArray.
On pourra écrire :

typedef CArray<double,double&> DoubleArray;


Maintenant comment faire si je veux récupérer un pointeur sur le tableau de double géré par la CArray ?
En utilisant la fonction GetData() Comme suit :

void SetDatas(int nSize,double * ptableau)
{
}
DoubleArray dArray;
// utilisation aprés remplissage....
SetDatas(dArray.GetSize(),dArray.GetData( ));



Comment déclarer un CArray à deux dimensions ?
Créé le 22/01/2007[haut]
auteur : Farscape
La première idée serait de faire :

CArray<CArray<CString,const char *>,CArray<CString,const char *> > tableau;

Malheureusement la classe CArray n'implémente pas le constructeur de copie, et ce genre code provoquera une erreur à la compilation.
Pour y remédier on devra réaliser une classe avec un constructeur de copie et l'opérateur d'affectation.
La classe template ci-dessous résout ce problème:

#ifndef __ARRAYEX_H__
#define __ARRAYEX_H__

#if _MSC_VER < 0x0600
    #pragma warning(disable : 4786) //identifier was truncated to '255' characters in the debug information
#endif

#ifndef __AFXTEMPL_H__
    #include <afxtempl.h>
#endif

template<class TYPE, class ARG_TYPE>
class CArrayEx: public CArray<TYPE, ARG_TYPE>
{
    public:

    CArrayEx();
    CArrayEx(const CArrayEx &x);

    // assigment operator
    CArrayEx &operator = (const CArrayEx& x);
    
};

template<class TYPE, class ARG_TYPE>
inline CArrayEx<TYPE, ARG_TYPE>::CArrayEx():CArray<TYPE, ARG_TYPE>()
{
}


template<class TYPE, class ARG_TYPE>
inline CArrayEx<TYPE, ARG_TYPE>::CArrayEx(const CArrayEx &x)
{
    *this = x;
}

template<class TYPE, class ARG_TYPE>
inline CArrayEx<TYPE, ARG_TYPE> &
       CArrayEx<TYPE, ARG_TYPE>::operator = (const CArrayEx& x)
{
    if(this!=&x)
    {
        RemoveAll();
        Copy(x);
    }
    return *this;
}
#endif

Exemple d'application:

typedef CArrayEx<CString ,const char *> StringArray; // Like CStringArray !!
    CArrayEx<StringArray,StringArray &> ArOfstrArray;    

    StringArray strArray;
    strArray.Add("coucou");

    ArOfstrArray.Add(strArray);
    for(i=0;i<ArOfstrArray.GetSize();i++)
    {
        for(int n=0;n<ArOfstrArray[i].GetSize();n++)
        {
            TRACE("\n Array[%d][%d]=%s",i,n,static_cast<const char *>(ArOfstrArray[i].GetAt(n)));
        }
    }



Comment faire une CList à deux dimensions ?
Créé le 22/01/2007[haut]
auteur : Farscape

Imaginons que je veuille écrire la chose suivante :

typedef CList< Gage,Gage &> ListGage;
typedef CList<ListGage,ListGage &> ListOfListGage;

Ce code provoquera inévitablement des erreurs à la compilation,
la CList ne possède pas d'opérateur d'affectation ou de constructeur de copie, de plus il faudra s'assurer que l'objet géré par la CList dispose lui aussi d'un constructeur et d'un opérateur de copie.
Le problème peut être solutionné comme suit:

Utiliser une CList qui dispose de l'opérateur de copie:

#ifndef LIST_EX_H__
#define LIST_EX_H__

#ifndef __AFXTEMPL_H__
    #include <afxtempl.h>
#endif

////////////////////////////////////////////////////////////////////////////

template< class TYPE, class ARG_TYPE>
class CListEx : public CList<TYPE, ARG_TYPE>
{
// Construction
public:
    CListEx (int nBlockSize = 10);
    CListEx (const CListEx &x);

// Assigment
public:
    CListEx &operator = (const CListEx &x);

};

template< class TYPE, class ARG_TYPE>
inline
    CListEx<TYPE,ARG_TYPE>::CListEx(int nBlockSize)
    :    CList<TYPE,ARG_TYPE>(nBlockSize)
{
}

template< class TYPE, class ARG_TYPE>
inline
    CListEx<TYPE,ARG_TYPE>::CListEx(const CListEx &x)
{
    *this = x;
}

template< class TYPE, class ARG_TYPE>
inline CListEx<TYPE,ARG_TYPE> &
    CListEx<TYPE,ARG_TYPE>::operator = (const CListEx &x)
{
    if(this != &x)
    {
        TYPE tDst;
        TYPE tSrc;
        POSITION pos;

        RemoveAll();
        pos = x.GetHeadPosition();
        while(pos != NULL)
        {
            tSrc = x.GetNext(pos);
            CopyElements<TYPE>(&tDst,&tSrc,1);
            AddTail(tDst);
        }
    }

    return *this;
}

#endif 

Ensuite rajouter l'opérateur de copie et le constructeur de copie a la classe gérée par la CList en s'appuyant sur le modèle suivant:

// la classe qui contient les données 
class Gage : public CObject
{
public:
    DECLARE_SERIAL( Gage )

    Gage(){Clear();}
    //-----------------------------
    ~Gage(){}
    //-----------------------------
     // constructeur de copie
    Gage(const Gage &rItem)
    {
        CopyFrom(rItem);
    }
    //-----------------------------
    // operateur d'affectation
    const Gage& operator=(const Gage& Src)
    {
        CopyFrom(Src);
        return *this;
    }
    //-----------------------------
    // effacer les données.
    void Clear()
    {
 //......   
    }
    //-----------------------------
    // copier les données d'une source.
    void CopyFrom(const  Gage& Src )
    {
        if(this==&Src) return;
        
        Clear(); // clear eventuel.
        // copie des données ici a faire...
   }
//....
 };

Ensuite on pourra écrire:

typedef CListEx<Gage,Gage &> ListGage;
typedef CList<ListGage,ListGage &> ListOfListGage;

Comment implémenter l'opérateur d'affection dans une CMap ?
Créé le 22/01/2007[haut]
auteur : Farscape
La CMap comme d'ailleurs les autres classes template CArray et Clist ne possède pas d'opérateur d'affectation ou de constructeur de copie.
Un contexte définissant une CMap de CMap ou impliquant la copie d'une CMap vers une CMap provoquera des erreurs de compilations.

Le code qui suit implémente le constructeur de copie et l'opérateur d'affectation pour la CMap :

#ifndef MAPEX_H__
#define MAPEX_H__

#if _MSC_VER < 0x0600
    #pragma warning(disable : 4786) //identifier was truncated to '255' characters in the debug information
#endif

#ifndef __AFXTEMPL_H__
    #include <afxtempl.h>
#endif

// specialisation pour une CString 
// extrait de CMapStringToPtr::HashKey(LPCTSTR key) const  :)
template<> 
inline UINT AFXAPI HashKey<CString> (CString strKey)
{
    LPCSTR key = strKey;
    UINT nHash = 0;
    while (*key)
    {
        nHash = (nHash<<5) + nHash + *key++;
    }
    return nHash;
}

template<> 
inline UINT AFXAPI HashKey<CString&> (CString& strKey)
{
    LPCSTR key = strKey;
    UINT nHash = 0;
    while (*key)
    {
        nHash = (nHash<<5) + nHash + *key++;
    }
    return nHash;
}

template<class KEY, class ARG_KEY, class VALUE, class ARG_VALUE>
class CMapEx : public CMap<KEY, ARG_KEY, VALUE, ARG_VALUE>
{
public:

    CMapEx(int nBlockSize = 10);
   // constructeur de copie
    CMapEx(const CMapEx &x);

    // opérateur d'affection
    CMapEx &operator = (const CMapEx& x);

    // accès a la donnée par GetAt par un index comme pour un CArray
    VALUE GetAt(int nIndex,KEY &rKey) const;
};

template<class KEY, class ARG_KEY, class VALUE, class ARG_VALUE>
inline CMapEx<KEY, ARG_KEY, VALUE, ARG_VALUE>::CMapEx(int nBlockSize)
    :CMap<KEY, ARG_KEY, VALUE, ARG_VALUE>(nBlockSize)
{
}

template<class KEY, class ARG_KEY, class VALUE, class ARG_VALUE>
inline CMapEx<KEY, ARG_KEY, VALUE, ARG_VALUE>::CMapEx(const CMapEx &x)
{
    *this = x;
}

template<class KEY, class ARG_KEY, class VALUE, class ARG_VALUE>
inline CMapEx<KEY, ARG_KEY, VALUE, ARG_VALUE> &
       CMapEx<KEY, ARG_KEY, VALUE, ARG_VALUE>::operator = (const CMapEx& x)
{
    KEY rKey;
    VALUE rValue;
    POSITION pos = x.GetStartPosition();

    RemoveAll();
    while(pos != NULL)
    {
        x.GetNextAssoc(pos,rKey,rValue);
        SetAt(rKey,rValue);
    }
    return *this;
}
template<class KEY, class ARG_KEY, class VALUE, class ARG_VALUE>
inline VALUE CMapEx<KEY, ARG_KEY, VALUE, ARG_VALUE>::GetAt(int nIndex,KEY &rKey) const
{
    ASSERT(nIndex >= 0 && nIndex < GetCount());
    
    POSITION pos = GetStartPosition();    
    VALUE rValue;
    
    do    
    {
        GetNextAssoc(pos,rKey,rValue);
    }while(nIndex --);
    
    return rValue;
}

Ensuite on pourra écrire:

   CMapEx<CString ,CString,CString ,CString> map;
   CMapEx<CString ,CString,CString ,CString> map2;

    map.SetAt("VC-MODO1","Farscape");
    map.SetAt("VC-MODO2","Nico");
    map.SetAt("VC-MODO3","BigBoom");

    map2=map;
    CString key;
    for(int i=0;i<map2.GetCount() ();i++)
    {
        TRACE("\n%s",(const char *)map2.GetAt(i,key));
        TRACE("\n%s",(const char *)key);
    }





Consultez les autres F.A.Q.


Valid XHTML 1.0 TransitionalValid CSS!

Les sources présentées sur cette page sont libres de droits et vous pouvez les utiliser à votre convenance. Par contre, la page de présentation constitue une œuvre intellectuelle protégée par les droits d'auteur. Copyright © 2004 Developpez Developpez LLC. Tous droits réservés Developpez LLC. Aucune reproduction, même partielle, ne peut être faite de ce site ni de l'ensemble de son contenu : textes, documents et images sans l'autorisation expresse de Developpez LLC. Sinon vous encourez selon la loi jusqu'à trois ans de prison et jusqu'à 300 000 € de dommages et intérêts.