一个类来管理多维数组!我该怎么办的细胞来管理不同类型的数据? [英] A class to manage multidimensional array! How can I do to manage different data types in the cells?

查看:109
本文介绍了一个类来管理多维数组!我该怎么办的细胞来管理不同类型的数据?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我声明,我是一个C程序员不是一个C ++程序员更多的(与C ++我是个初学者:P)

我写了一个C ++类来管理多维数组(N维矩阵)。这个类的方法来创建矩阵和设定,并从基体(也设置在它里面的位置)。

获得/值

我有两个问题:


  • 通过,我想类似米语法(X,Y,Z,...,N)来设置/获取值的一些方法使用省略号的想法EG:的getValue(INT dim0,... );但我认为这是危险的;虽然我写我假设传递的参数是相同的号码矩阵的各个维度的功能,用户可以通过少值超过必要,那么他将没有编译器错误或警告。


  • 我想能够管理的数据类型的基质细胞矩阵在创建时运行期间包含(不使用工会并以某种方式宣布型)。在类code,我插一个typedef(用于开发目的),它指示这样的修改会/可能会影响分。


对于第一个问题,我没有想法比实现要好。你有什么建议?

要解决的第二个问题,我可能想为方法创建的getValue()的setValue()和createMatrix()重载,但是这种想法需要一些变通方法,并可能完全重写每一个单一的方法,然后有更多的副本相同code的(我想避免的意图有更好的维修能力),而且这个解决方案并不授予管理所有可能的类型。我正在考虑使用模板,但如果这种方式是更好的方式,我不明白。你有什么建议?

这些是要修改来解决这两个问题的主要方法:

的CPP模块的方法:

  INT矩阵:: createMatrix(矩阵:: value_t *值)
{
    INT RETVAL = 1;    如果((m_values​​ = NULL || numOfDim())及!&放大器; valAreIntAlloc()==真){
        返回0;
    }    如果(值!= NULL){
        m_values​​ =值;
        setValAreIntAlloc(假);
    }其他{
        setValAreIntAlloc(真);
        //计算元件的数目为
        //整个矩阵
        的for(int i = 0; I< numOfDim();我++){
            RETVAL * = numOfElemInDim(ⅰ);
            如果(!RETVAL){
                //表明一个维度有一个0值
                //为numOfElemInDim!来电者将被允许
                //使用要知道这样的尺寸:-retval-1;
                RETVAL = - 第(i + 1);
                打破;
            }
        }
        如果(RETVAL大于0){
            m_values​​ =新value_t [RETVAL]
            如果(m_values​​!= NULL)
                RETVAL = 0;
        }
    }    //返回结果:
    // 1,如果值是外部分配的内存,
    //如果没有已分配或0
    // m_values​​已被设为内部!
    //分配元件的别处的数目。
    返回RETVAL;
}无效矩阵:: setPositions(INT dim0,...)
{
    va_list的VL;
    的va_start(VL,dim0);    的setPosition(0,dim0);
    的for(int i = 1; I< numOfDim();我++)
        setPosition两种(我,在va_arg(VL,INT));    va_end用来(VL);
}矩阵:: value_t矩阵::的getValue(INT dim0,...)
{
    va_list的VL;
    的va_start(VL,dim0);    的setPosition(0,dim0);
    的for(int i = 1; I< numOfDim();我++)
        setPosition两种(我,在va_arg(VL,INT));    va_end用来(VL);
    返回的getValue();
}无效矩阵:: setValue方法(矩阵:: value_t价值,诠释dim0,...)
{
    va_list的VL;
    的va_start(VL,dim0);    的setPosition(0,dim0);
    的for(int i = 1; I< numOfDim();我++)
        setPosition两种(我,在va_arg(VL,INT));    va_end用来(VL);
    的setValue(值);
}

在头文件内联方法:

 在线value_t的getValue(){返回m_values​​ [posInValueVector()]; }内嵌无效的setValue(value_t值){m_values​​ [posInValueVector()] =价值; }

的方法的setPosition(),setPositions()用于设置要管理的矩阵单元的坐标;该方法posInValueVector()计算向量使用的坐标基质细胞(由方法createMatrix创建)内的索引。

下面的人code:

的main.cpp

 的#include<&iostream的GT;
#包括LT&;&cstdio GT;#包括matrix.h使用命名空间std;诠释的main()
{
    矩阵m(3);
    m.setNumOfElemInDims(4,5,6);
    m.createMatrix();    的for(int i = 0; I< m.numOfElemInDim(0);我++)
        为(中间体J = 0; J&下; m.numOfElemInDim(1); J ++)
            为(中间体K = 0; K&下; m.numOfElemInDim(2); K +)
                m.setValue(ⅰ* 100 + J * 10 + K,I,J,K); //矩阵(I,J,K)= I * 100 + J * 10 + K    //打印输出所有矩阵的值(I,J,K)细胞
    //我用printf的,因为我觉得这很简单!
    的for(int i = 0; I< m.numOfElemInDim(0);我++)
        为(中间体J = 0; J&下; m.numOfElemInDim(1); J ++)
            为(中间体K = 0; K&下; m.numOfElemInDim(2); K +)
                的printf((%D,%D,%D)=%03.0f \\ n,I,J,K,m.getValue(I,J,K));
}

matrix.h

 的#ifndef MATRIX_H
#定义MATRIX_H类矩阵
{
上市:
    双的typedef value_t;    矩阵();
    矩阵(INT numOfDim,为int * nelem个= NULL);
    〜矩阵();    内联unsigned int类型numOfDim()const的{返回m_numOfDim;}    INT setNumOfDim(INT numOfDim,为int * nelem个= NULL);    内联INT numOfElemInDim(INT DIM)常量
        {返回(点心< numOfDim())m_numOfElemInDim [DIM]: - 1; }    INT setNumOfElemInDim(INT暗淡,诠释nelem个);
    INT setNumOfElemInDims(中间体EL0,...);    INT createMatrix(value_t *值);
    内联INT createMatrix(){返回createMatrix(NULL); }    内联BOOL valAreIntAlloc()const的{返回m_valAreIntAlloc;}
    内嵌无效setValAreIntAlloc(布尔valAreIntAlloc)
        {m_valAreIntAlloc = valAreIntAlloc;}    内联INT位置(INT DIM)const的{返回m_positions [暗淡];}
    内嵌无效setPosition两种(INT暗淡,int值)
        {m_positions [暗淡] =值;}    内嵌无效setPositions为(int *位置)
        {的for(int i = 0; I< numOfDim();我++)setPosition两种(我,持仓量由[i]);}    空隙setPositions(中间体dim0,...);    内嵌value_t的getValue(){返回m_values​​ [posInValueVector()]; }    value_t的getValue(中间体dim0,...);    内嵌无效的setValue(value_t值){m_values​​ [posInValueVector()] =价值; }
    无效的setValue(value_t价值,诠释dim0,...);私人的:
    INT m_numOfDim;
    INT * m_numOfElemInDim;
    INT * m_positions;    value_t * m_values​​;
    布尔m_valAreIntAlloc;    INT posInValueVector();
};#ENDIF // MATRIX_H

matrix.cpp

 的#include<&iostream的GT;
#包括LT&;&cstdarg GT;#包括matrix.h#定义__init __(V)\\
m_numOfDim(ⅴ),\\
m_numOfElemInDim(NULL),\\
m_positions(NULL),\\
m_values​​(NULL),\\
m_valAreIntAlloc(假)矩阵::矩阵():
    __init __(0)
{
}矩阵::〜矩阵()
{
    如果(m_numOfElemInDim!= NULL)
        删除m_numOfElemInDim;    如果(m_positions!= NULL)
        删除m_positions;    如果(valAreIntAlloc()及&放大器;!m_values​​ = NULL)
        删除m_values​​;
}矩阵::矩阵(INT numOfDim,为int * nelem个):
    __init __(numOfDim)
{
    setNumOfDim(numOfDim,nelem个);
}INT矩阵:: setNumOfDim(INT numOfDim,为int * nelem个)
{
    INT RETVAL = 0;    m_numOfDim = numOfDim;    m_numOfElemInDim =新INT [numOfDim]
    如果(m_numOfElemInDim == NULL)
        返回1;    m_positions =新INT [numOfDim]
    如果(m_positions == NULL)
        返回2;    的for(int i = 0; I< m_numOfDim;我++){
        如果(setNumOfElemInDim(ⅰ,(nelem个== NULL)?0:nelem个由[i])){
            RETVAL = -1;
            打破;
        }
        的setPosition(I,0);
    }    返回RETVAL; //一切都好!
}INT矩阵:: setNumOfElemInDim(INT暗淡,诠释nelem个)
{
    INT RETVAL = -1;    如果(点心< numOfDim()){
        m_numOfElemInDim [暗淡] = nelem个;
        RETVAL = 0;
    }    返回RETVAL;
}INT矩阵:: setNumOfElemInDims(INT EL0,...)
{
    va_list的VL;
    的va_start(VL,EL0);    setNumOfElemInDim(0,EL0);
    的for(int i = 1; I< numOfDim();我++)
        setNumOfElemInDim(I,在va_arg(VL,INT));    va_end用来(VL);
    返回0;
}INT矩阵:: createMatrix(矩阵:: value_t *值)
{
    INT RETVAL = 1;    如果((m_values​​ = NULL || numOfDim())及!&放大器; valAreIntAlloc()==真){
        返回0;
    }    如果(值!= NULL){
        m_values​​ =值;
        setValAreIntAlloc(假);
    }其他{
        setValAreIntAlloc(真);
        //计算元件的数目为
        //整个矩阵
        的for(int i = 0; I< numOfDim();我++){
            RETVAL * = numOfElemInDim(ⅰ);
            如果(!RETVAL){
                //表明一个维度有一个0值
                //为numOfElemInDim!来电者将被允许
                //使用要知道这样的尺寸:-retval-1;
                RETVAL = - 第(i + 1);
                打破;
            }
        }
        如果(RETVAL大于0){
            m_values​​ =新value_t [RETVAL]
            如果(m_values​​!= NULL)
                RETVAL = 0;
        }
    }    //返回结果:
    // 1,如果值是外部分配的内存,
    //如果没有已分配或0
    // m_values​​已被设为内部!
    //分配元件的别处的数目。
    返回RETVAL;
}无效矩阵:: setPositions(INT dim0,...)
{
    va_list的VL;
    的va_start(VL,dim0);    的setPosition(0,dim0);
    的for(int i = 1; I< numOfDim();我++)
        setPosition两种(我,在va_arg(VL,INT));    va_end用来(VL);
}矩阵:: value_t矩阵::的getValue(INT dim0,...)
{
    va_list的VL;
    的va_start(VL,dim0);    的setPosition(0,dim0);
    的for(int i = 1; I< numOfDim();我++)
        setPosition两种(我,在va_arg(VL,INT));    va_end用来(VL);
    返回的getValue();
}无效矩阵:: setValue方法(矩阵:: value_t价值,诠释dim0,...)
{
    va_list的VL;
    的va_start(VL,dim0);    的setPosition(0,dim0);
    的for(int i = 1; I< numOfDim();我++)
        setPosition两种(我,在va_arg(VL,INT));    va_end用来(VL);
    的setValue(值);
}INT矩阵:: posInValueVector()
{
    INT POS =位置(0);    的for(int i = 1; I< numOfDim();我++)
        POS = POS * numOfElemInDim(我)+位置(i);    返回POS;
}


解决方案

我觉得下面的解决方案,这是一个<一个href=\"http://stackoverflow.com/questions/30010444/how-to-convert-a-define-in-a-template-variadic/30010627#30010627\"标题=答案>另一个我的问题的答案,是一个美丽的解决方案,实现了所有我想要的东西,但我用了很多code的...它是基于C ++ 11可变参数模板。

我有这个code一dubt是在谁的其管理的内存的方式。我的意志是内存是单块,我几乎可以肯定这code不这样做。不过是一个又好又快code!

 模板&LT; typename的T,INT ...休息&GT;
结构矩阵;模板&LT; typename的T,INT N'GT;
结构矩阵LT; T,N&GT; {
    数据T [N];
    矩阵(){
        的for(int i = 0; I&LT; N;我++){
            数据[I] = T(0);
        }
    }
    夯;运算符[](INT指数){返回数据[指数] }
};模板&LT; typename的T,INT N,INT ...休息&GT;
结构矩阵LT; T,N,休息...&GT; {
    矩阵LT; T,休息...&GT;数据[N];
    矩阵LT; T,休息...&GT;&安培;运算符[](INT指数){返回数据[指数] }
};

这可与使用:

 矩阵LT;双,10,9,4&GT;米;
对(INT I = 0; I&小于10;我++){
    对于(INT J = 0; J&LT; 9; J ++){
        为(中间体K = 0; K&4;; k ++){
            M [i] [j]的[K] = I + J * 2.718 + K * 3.1416;
        }
    }
}

I state that I am a C programmer more than a C++ programmer (with C++ I'm a beginner: p)

I've written a C++ class to manage multidimensional arrays (n-dimensional matrices). This class has methods to create the matrix and to set and to get value in/from the matrix (also to set the position inside it).

I've two issues:

  • With the idea that I want a syntax similar to m(x,y,z, ..., n) to set/get values some methods use the ellipsis E.G.: getValue(int dim0,...); But I think it's dangerous; although in the functions I've written I assume that the passed arguments are the same number of the matrix dimensions, the user might pass less values than necessary, then he will have no compiler errors or warnings.

  • I want to be able to manage the data type that the matrix cells contain during runtime at matrix creation time (without the use of union and somehow declaring the type). In the class code I've inserted a typedef (for development purposes) which indicates the points where such a modifications would/might impact.

For the first issue I've no ideas better than those implemented. Do you have suggestions?

To solve the second issue, I might think to create overloads for the methods getValue(), setValue() and createMatrix(), but this idea requires some workarounds and probably to rewrite completely each single method and then to have more copies of the "same" code (I want avoid that with the intent to have a better maintenance capability) , moreover this solution doesn't grant to manage all possible types. I'm thinking about the use of templates, but I don't understand if such a way is the better way. Do you have suggestions?

These are the main methods to be modified to solve both the issues:

methods in the CPP module:

int Matrix::createMatrix(Matrix::value_t *values)
{
    int retval=1;

    if ( (m_values!=NULL || !numOfDim()) && valAreIntAlloc()==true ) {
        return 0;
    }

    if (values!=NULL) {
        m_values=values;
        setValAreIntAlloc(false);
    } else {
        setValAreIntAlloc(true);
        // Compute the number of elements for
        // the whole matrix
        for(int i=0;i<numOfDim();i++) {
            retval*=numOfElemInDim(i);
            if (!retval) {
                //Indicate that a dimension has a 0 value
                //as numOfElemInDim! The caller will be allowed
                //to know the such a dimension using: -retval-1;
                retval=-(i+1);
                break;
            }
        }
        if (retval>0) {
            m_values=new value_t[retval];
            if (m_values!=NULL)
                retval=0;
        }
    }

    //Returns:
    //1 if values is an external allocated memory,
    //0 if nothing has been allocated or the
    //m_values is already set as internal!
    //elsewhere the number of allocated elements.
    return retval;
}

void Matrix::setPositions(int dim0, ...)
{
    va_list vl;
    va_start(vl,dim0);

    setPosition(0,dim0);
    for (int i=1;i<numOfDim();i++)
        setPosition(i,va_arg(vl,int));

    va_end(vl);
}

Matrix::value_t Matrix::getValue(int dim0, ...)
{
    va_list vl;
    va_start(vl,dim0);

    setPosition(0,dim0);
    for (int i=1;i<numOfDim();i++)
        setPosition(i,va_arg(vl,int));

    va_end(vl);
    return getValue();
}

void Matrix::setValue(Matrix::value_t value, int dim0, ...)
{
    va_list vl;
    va_start(vl,dim0);

    setPosition(0,dim0);
    for (int i=1;i<numOfDim();i++)
        setPosition(i,va_arg(vl,int));

    va_end(vl);
    setValue(value);
}

methods inline in the Header file:

inline value_t getValue() { return m_values[posInValueVector()]; }

inline void setValue(value_t value) { m_values[posInValueVector()]=value; }

The methods setPosition(), setPositions() are used to set the coordinates of the matrix cell to be managed; the method posInValueVector() computes the index inside the vector (created by the method createMatrix) of the matrix cell using the coordinates.

Here al the code:

main.cpp

#include <iostream>
#include <cstdio>

#include "matrix.h"

using namespace std;

int main()
{
    Matrix m(3);
    m.setNumOfElemInDims(4,5,6);
    m.createMatrix();

    for(int i=0;i<m.numOfElemInDim(0);i++)
        for(int j=0;j<m.numOfElemInDim(1);j++)
            for(int k=0;k<m.numOfElemInDim(2);k++)
                m.setValue(i*100+j*10+k,i,j,k); // matrix(i,j,k)=i*100+j*10+k

    //printout the values of all matrix(i,j,k) cells
    //I've used the printf because I find it very simple!
    for(int i=0;i<m.numOfElemInDim(0);i++)
        for(int j=0;j<m.numOfElemInDim(1);j++)
            for(int k=0;k<m.numOfElemInDim(2);k++)
                printf("(%d,%d,%d)=%03.0f\n",i,j,k,m.getValue(i,j,k));
}

matrix.h

#ifndef MATRIX_H
#define MATRIX_H

class Matrix
{
public:
    typedef double value_t;

    Matrix();
    Matrix(int numOfDim, int *nelem=NULL);
    ~Matrix();

    inline unsigned int numOfDim() const {return m_numOfDim;}

    int setNumOfDim(int numOfDim, int *nelem=NULL);

    inline  int numOfElemInDim(int dim) const
        {return (dim<numOfDim())?m_numOfElemInDim[dim]:-1; }

    int setNumOfElemInDim(int dim, int nelem);
    int setNumOfElemInDims(int el0, ...);

    int createMatrix(value_t *values);
    inline int createMatrix() { return createMatrix(NULL); }

    inline bool valAreIntAlloc() const {return m_valAreIntAlloc;}
    inline void setValAreIntAlloc(bool valAreIntAlloc)
        {m_valAreIntAlloc = valAreIntAlloc;}

    inline int position(int dim) const {return m_positions[dim];}
    inline void setPosition(int dim,int value)
        {m_positions[dim] = value;}

    inline void setPositions(int *positions)
        {for(int i=0;i<numOfDim();i++) setPosition(i,positions[i]);}

    void setPositions(int dim0, ...);

    inline value_t getValue() { return m_values[posInValueVector()]; }

    value_t getValue(int dim0, ...);

    inline void setValue(value_t value) { m_values[posInValueVector()]=value; }
    void setValue(value_t value, int dim0, ...);

private:
    int m_numOfDim;
    int * m_numOfElemInDim;
    int * m_positions;

    value_t * m_values;
    bool m_valAreIntAlloc;

    int posInValueVector();
};

#endif // MATRIX_H

matrix.cpp

#include <iostream>
#include <cstdarg>

#include "matrix.h"

#define __INIT__(v)\
m_numOfDim(v),\
m_numOfElemInDim(NULL),\
m_positions(NULL),\
m_values(NULL),\
m_valAreIntAlloc(false)

Matrix::Matrix():
    __INIT__(0)
{
}

Matrix::~Matrix()
{
    if (m_numOfElemInDim!=NULL)
        delete m_numOfElemInDim;

    if (m_positions!=NULL)
        delete m_positions;

    if (valAreIntAlloc() && m_values!=NULL)
        delete m_values;
}

Matrix::Matrix(int numOfDim, int *nelem):
    __INIT__(numOfDim)
{
    setNumOfDim(numOfDim,nelem);
}

int Matrix::setNumOfDim(int numOfDim, int *nelem)
{
    int retval=0;

    m_numOfDim = numOfDim;

    m_numOfElemInDim = new int[numOfDim];
    if (m_numOfElemInDim==NULL)
        return 1;

    m_positions = new int[numOfDim];
    if (m_positions==NULL)
        return 2;

    for(int i=0;i<m_numOfDim;i++) {
        if (setNumOfElemInDim(i,(nelem==NULL)?0:nelem[i])) {
            retval=-1;
            break;
        }
        setPosition(i,0);
    }

    return retval; //All ok!
}

int Matrix::setNumOfElemInDim(int dim,int nelem)
{
    int retval=-1;

    if (dim<numOfDim()) {
        m_numOfElemInDim[dim] = nelem;
        retval=0;
    }

    return retval;
}

int Matrix::setNumOfElemInDims(int el0, ...)
{
    va_list vl;
    va_start(vl,el0);

    setNumOfElemInDim(0,el0);
    for (int i=1;i<numOfDim();i++)
        setNumOfElemInDim(i,va_arg(vl,int));

    va_end(vl);
    return 0;
}

int Matrix::createMatrix(Matrix::value_t *values)
{
    int retval=1;

    if ( (m_values!=NULL || !numOfDim()) && valAreIntAlloc()==true ) {
        return 0;
    }

    if (values!=NULL) {
        m_values=values;
        setValAreIntAlloc(false);
    } else {
        setValAreIntAlloc(true);
        // Compute the number of elements for
        // the whole matrix
        for(int i=0;i<numOfDim();i++) {
            retval*=numOfElemInDim(i);
            if (!retval) {
                //Indicate that a dimension has a 0 value
                //as numOfElemInDim! The caller will be allowed
                //to know the such a dimension using: -retval-1;
                retval=-(i+1);
                break;
            }
        }
        if (retval>0) {
            m_values=new value_t[retval];
            if (m_values!=NULL)
                retval=0;
        }
    }

    //Returns:
    //1 if values is an external allocated memory,
    //0 if nothing has been allocated or the
    //m_values is already set as internal!
    //elsewhere the number of allocated elements.
    return retval;
}

void Matrix::setPositions(int dim0, ...)
{
    va_list vl;
    va_start(vl,dim0);

    setPosition(0,dim0);
    for (int i=1;i<numOfDim();i++)
        setPosition(i,va_arg(vl,int));

    va_end(vl);
}

Matrix::value_t Matrix::getValue(int dim0, ...)
{
    va_list vl;
    va_start(vl,dim0);

    setPosition(0,dim0);
    for (int i=1;i<numOfDim();i++)
        setPosition(i,va_arg(vl,int));

    va_end(vl);
    return getValue();
}

void Matrix::setValue(Matrix::value_t value, int dim0, ...)
{
    va_list vl;
    va_start(vl,dim0);

    setPosition(0,dim0);
    for (int i=1;i<numOfDim();i++)
        setPosition(i,va_arg(vl,int));

    va_end(vl);
    setValue(value);
}

int Matrix::posInValueVector()
{
    int pos=position(0);

    for(int i=1;i<numOfDim();i++)
        pos=pos*numOfElemInDim(i)+position(i);

    return pos;
}

解决方案

I think the solution below, that is an answer at another my question, is a beautiful solution and implements all what I wanted, but I used a lot of code ... It's based on C++11 variadic templates.

A dubt I've about this code is the way in whose it manages the memory. My will would be the memory is a single block, I'm almost sure this code don't do that. However is a good and fast code!

template<typename T, int ...rest>
struct matrix;

template<typename T, int n>
struct matrix<T, n> {
    T data[n];
    matrix() {
        for (int i=0; i<n; i++) {
            data[i] = T(0);
        }
    }
    T& operator[](int index) { return data[index]; }
};

template<typename T, int n, int ...rest>
struct matrix<T, n, rest...> {
    matrix<T, rest...> data[n];
    matrix<T, rest...>& operator[](int index) { return data[index]; }
};

that can be used with:

matrix<double, 10, 9, 4> m;
for (int i=0; i<10; i++) {
    for (int j=0; j<9; j++) {
        for (int k=0; k<4; k++) {
            m[i][j][k] = i + j*2.718 + k*3.1416;
        }
    }
}

这篇关于一个类来管理多维数组!我该怎么办的细胞来管理不同类型的数据?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆