简体   繁体   English

在 C++ 中实现二维数组模板的问题

[英]Problems with implementing 2D array template in C++

I tried to create a template for a generic 2D array, which would allow me to create arrays of different data types and fill them with random values.我尝试为通用二维数组创建一个模板,这将允许我创建不同数据类型的 arrays 并用随机值填充它们。 My current code seemingly creates three objects, but fills them with the same random values, and the double type massive does not even have double values.我当前的代码看似创建了三个对象,但是用相同的随机值填充它们,而 double 类型的 mass 甚至没有 double 值。 I think the problem is somewhere in the constructor and with the pointers, but I am not sure how to fix this.我认为问题出在构造函数和指针的某个地方,但我不确定如何解决这个问题。

My class:我的 class:

template <typename T>
    class MATRIX
    {
    private:
      T** M;
      int m = 8;
      int n = 12;
    public:
    MATRIX(T matr[8][12]);
      void fill();
      };

Constructor:构造函数:

template <typename T>
 MATRIX<T>::MATRIX(T matr[8][12]){
    M = (T**) new T*[m];
    for (int i = 0; i < m; i++)
      M[i] = (T*)new T[n];
}

Method:方法:

    template <typename T>
    void MATRIX<T>::fill(){
        T randomNumber;
        srand((unsigned) time(0));
        for (int i = 0; i < m; i++){
          for (int j = 0; j < n; j++){
            randomNumber = (rand() % (122 + 1 - 65)) + 65;
            M[i][j] = randomNumber;} } }

Main:主要的:

 int main() {
    int intMatr[8][12];
    MATRIX<int>a(intMatr);
    a.fill();
    
    double doubleMatr[8][12];
    MATRIX<double>b(doubleMatr);
    b.fill();
    
    char charMatr[8][12];
    MATRIX<char>c(charMatr);
    c.fill();
    return 0; }

Not really a direct answer to your question, howeverr try not to use new/delete if you don't have to as is shown in this example (note the array2d_t class is something I wrote earlier and reused for this example so it can do a bit more then needed) I also show how to use c++'s random generators to create characters for your matrix.并不是对您的问题的直接回答,但是,如果您不需要,请尽量不要使用 new/delete,如本示例所示(请注意,array2d_t class 是我之前编写的并在此示例中重复使用,因此它可以执行比需要多一点)我还展示了如何使用 c++ 的随机生成器为您的矩阵创建字符。

#pragma once

#include <vector>
#include <iostream>
#include <random>
#include <utility>
#include <string>
#include <stdexcept>

//---------------------------------------------------------------------------------------------------------------------

template<typename type_t, std::size_t rows_v, std::size_t cols_v>
struct array2d_t 
{
    constexpr array2d_t() :
        m_values{}
    {
    }

    constexpr explicit array2d_t(const type_t(&values)[rows_v][cols_v])
    {
        // constexpr compatible initialization
        for (auto row = 0; row < rows_v; ++row)
        {
            for (auto col = 0; col < cols_v; ++col)
            {
                m_values[row][col] = values[row][col];
            }
        }
    }

    ~array2d_t() = default;

    // return a row
    constexpr auto operator[](const std::size_t row)
    {
        //assert(row < rows_v);
        if (row >= rows_v) throw std::invalid_argument("row out of bounds");
        return row_t(&m_values[row][0]);
    }

    // return a const row
    constexpr auto operator[](const std::size_t row) const
    {
        //assert(row < rows_v);
        if (row >= rows_v) throw std::invalid_argument("row out of bounds");
        return const_row_t(&m_values[row][0]);
    }

    // return iterator to the first row (so array can be used in range based for loop)
    constexpr auto begin() 
    {
        return std::begin(m_values);
    }

    // return iterator to the last row (so array can be used in range based for loop)
    constexpr auto end() 
    {
        return std::end(m_values);
    }

    constexpr std::size_t rows() const 
    {
        return rows_v;
    }

    constexpr std::size_t columns() const
    {
        return cols_v;
    }

private:
    //-----------------------------------------------------------------------------------------------------------------
    ///  row helper
    struct row_t
    {
        constexpr row_t(type_t* row) :
            m_row{ row }
        {
        }

        constexpr type_t& operator[](const std::size_t column) const
        {
            //assert(column < cols_v);
            if (column >= cols_v) throw std::invalid_argument("column out of bounds");
            return m_row[column];
        }

        constexpr auto begin() const
        {
            return std::begin(m_row);
        }

        constexpr auto end() const
        {
            return begin() + rows_v;
        }

    private:
        type_t* m_row;
    };

    //-----------------------------------------------------------------------------------------------------------------
    // row helper for const 
    struct const_row_t
    {
        constexpr const_row_t(const type_t* row) :
            m_row{ row }
        {
        }

        constexpr const type_t& operator[](const std::size_t column) const
        {
            //assert(column < cols_v);
            if (column >= cols_v) throw std::invalid_argument("column out of bounds");
            return m_row[column];
        }

        constexpr auto begin() const
        {
            return std::begin(m_row);
        }

        constexpr auto end() const
        {
            return begin() + rows_v;
        }

    private:
        const type_t* m_row;
    };

    type_t m_values[rows_v][cols_v];
};

template<typename type_t, std::size_t rows_v, std::size_t cols_v>
std::ostream& operator<<(std::ostream& os, array2d_t<type_t,rows_v,cols_v>& arr)
{
    for (const auto& row : arr)
    {
        bool comma = false;

        for (const auto& value : row)
        {
            if (comma) std::cout << ", ";
            std::cout << value;
            comma = true;
        }

        std::cout << "\n";
    }

    std::cout << "\n";

    return os;
}

//---------------------------------------------------------------------------------------------------------------------

class MATRIX :
    public array2d_t<char, 8, 12>
{
public:

    void fill()
    {
        // initialize a vector of valid character for random to pick from
        // static ensures this is only done on first call to function
        static std::vector<char> valid_chars = []
        {
            std::vector<char> chars;
            chars.reserve(52);
            for (char c = 'A'; c < 'Z'; ++c) chars.push_back(c);
            for (char c = 'a'; c < 'z'; ++c) chars.push_back(c);
            return chars;
        }();

        // this is how to setup random number generation in C++
        static std::random_device rd{};
        static std::default_random_engine random{ rd() };
        static std::uniform_int_distribution<std::size_t> distribution(0, valid_chars.size() - 1);

        for (auto& row : *this)
        {
            for (auto& value : row)
            {
                value = valid_chars[distribution(random)];
            }
        }
    }
};

//---------------------------------------------------------------------------------------------------------------------

int main()
{
    MATRIX m;
    m.fill();

    std::cout << m;
    return 0;
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM