سؤال

من وقت لآخر ، أستخدم الكود التالي لإنشاء بنية بيانات نمط المصفوفة

typedef double myType;

typedef struct matrix_t{                                                             |Compilation started at Mon Apr  5 02:24:15
  myType **matrix;                                                                   |
  size_t x;                                                                          |gcc structreaderGeneral.c -std=gnu99 -lz
  size_t y;                                                                          |
}matrix;                                                                             |Compilation finished at Mon Apr  5 02:24:15
                                                                                     |
                                                                                     |
matrix alloc_matrix(size_t x, size_t y){                                             |
  if(0)                                                                              |
    fprintf(stderr,"\t-> Alloc matrix with dim (%lu,%lu) byteprline=%lu bytetotal:%l\|
u\n",x,y,y*sizeof(myType),x*y*sizeof(myType));                                       |
                                                                                     |
  myType **m = (myType **)malloc(x*sizeof(myType **));                               |
  for(size_t i=0;i<x;i++)                                                            |
    m[i] =(myType *) malloc(y*sizeof(myType *));                                     |
                                                                                     |
  matrix ret;                                                                        |
  ret.x=x;                                                                           |
  ret.y=y;                                                                           |
  ret.matrix=m;                                                                      |
  return ret;                                                                        |
} 

وبعد ذلك أود تغيير typedef الخاص بي وفقًا لذلك إذا كنت بحاجة إلى نوع مختلف من النوع للإدخالات في المصفوفة الخاصة بي.

الآن أحتاج إلى مصفوفين مع أنواع مختلفة ، سيكون الحل السهل هو نسخ/لصق الكود ، ولكن هل هناك طريقة لفعل تنفيذ أكثر عاما.

شكرًا

تحرير: يجب أن أوضح أنه في C ليس C ++. آسف لعدم توضيح ذلك.

هل كانت مفيدة؟

المحلول

في ج؟ فوضوي ، ولكن ممكن مع Macro Magic. (أنت تصل إلى النقطة التي يكون فيها C ++ خيارًا أفضل ، راجع للشغل).

#define DECL_MATRIX(type,name) \
    typedef struct matrix_##type##_t {             \
        type **matrix;                             \
        size_t x;                                  \
        size_t y;                                  \
    } name;                                        \
    name alloc_##name(size_t x,size_t y)

#define DEFINE_MATRIX_OPS(type,name) \
    struct matrix_##type##_t                       \
    alloc_##name(size_t x, size_t y) {             \
        size_t i;                                  \
        struct matrix_##type##_t ret;              \
        type **m;                                  \
                                                   \
        m = (type **)malloc(x*sizeof(type *));     \
        for(size_t i=0;i<x;i++)                    \
            m[i] =(type *) malloc(y*sizeof(type)); \
        ret.x=x;                                   \
        ret.y=y;                                   \
        ret.matrix=m;                              \
        return ret;                                \
    }

ثم تستخدم هذا مثل هذا:

// At the top level of the file
DECL_MATRIX(double, dmat);
DECL_MATRIX(int, imat);
DEFINE_MATRIX_OPS(double, dmat);
DEFINE_MATRIX_OPS(int, imat);

// In a function
dmat d = alloc_dmat(3,3);
imat i = alloc_imat(2,6);

كملاحظة تصميم ، من الأفضل بالنسبة لمصفوفات الحجم الثابت لتخصيص الذاكرة للعناصر ككتلة واحدة واستخدام القليل من الرياضيات للفهرس فيها. وهكذا بدلا من ary[a][b] انت تستخدم ary[a*x_size+y]. يمكنك لف كل هذا في المزيد من وحدات الماكرو إذا كنت تريد ، لكنها أكثر كفاءة ، سواء من حيث إدارة الذاكرة والوصول إليها.

نصائح أخرى

كنت بحاجة إلى مصفوفة بسيطة للغاية لمشروع لمرة واحدة وطرق هذا المشروع. هذا ليس ما أسميه جودة الإنتاج ، لكنه قد يمنحك بعض الأفكار:

template <typename T>
class Matrix2D {

    public:

        Matrix2D( unsigned int  width, unsigned int  height,
                            const T & v  = T() ) {
            if ( width == 0 || height == 0 ) {
                throw std::out_of_range( "Invalid Matrix2D size ");
            }
            for ( unsigned int x = 0; x < width; x++ ) {
                mData.push_back( std::vector<T>( height, v ) );
            }
        }

        T & operator()( unsigned int x, unsigned int y ) {
            if ( x >= Width() || y >= Height() ) {
                throw std::range_error( "Invalid Matrix2D index" );
            }
            return mData[x][y];
        }

        const T & operator()( unsigned int x, unsigned int y ) const {
            if ( x >= Width() || y >= Height() ) {
                throw std::range_error( "Invalid Matrix2D index" );
            }
            return mData[x][y];
        }


        void Clear( const T & v  = T() ) {
            for ( unsigned int x = 0; x < Width(); x++ ) {
                for ( unsigned int y = 0; y < Height(); y++ ) {
                    mData[x][y] = v;
                }
            }
        }

        unsigned int Width() const {
            return mData.size();
        }

        unsigned int Height() const {
            return mData[0].size();
        }

        void DumpOn( std::ostream & os ) {
            for ( unsigned int y = 0; y < Height(); y++ ) {
                for ( unsigned int x = 0; x < Width(); x++ ) {
                    os << '[' << mData[x][y] << ']';
                }
                os << "\n";
            }
        }

    private:

        std::vector <std::vector  <T> > mData;
};

كما هو مقترح في التعليقات السابقة ، مصفوفة صف ماجور باستخدام الذاكرة الخطية:

template<typename T, unsigned int DIM>
class matrix {
    public:
        matrix<T,DIM>() {
            matrix(0);
        }
        matrix<T,DIM>(const T* v) {
            for (unsigned int i=0; i<DIM*DIM; ++i)
                value[i] = v[i];
        }
        matrix<T,DIM>(T v) {
            for (unsigned int i=0; i<DIM*DIM; ++i)
                value[i] = v;
        }
        T& operator[](int index) {
            assert(index >= 0 && index < (int)(DIM*DIM));
            return value[index];
        }

        // and so on...

    private:
        T value[DIM * DIM];
}
مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top