Как генерировать случайные числа для заполнения динамического массива в соответствии с типом шаблона? - PullRequest
0 голосов
/ 08 марта 2019

Я сосредоточился на своем последнем упражнении по программированию, чтобы реализовать шаблоны для печати 2D-массивов. Мне разрешено только изменять файлы реализации. (т.е. файлы main и header должны оставаться нетронутыми) Я застрял при заполнении массивов случайными числами в соответствии с типом шаблона, который принимает объект. Есть ли способ использовать rand () для генерации случайных чисел в соответствии с типом? Любая помощь будет оценена. Спасибо!

 RowAray.h:
#ifndef ROWARAY_H
#define ROWARAY_H
template<class T>
class RowAray{
    protected:
        int size;
        T *rowData;
    public:
        RowAray(int);
        virtual ~RowAray();
        int getSize()const{return size;}
        T getData(int i)const{
            if(i>=0&&i<size)return rowData[i];
            else return 0;}
        void setData(int,T);
};


#endif /* ROWARAY_H */

Table.h:
#ifndef TABLE_H
#define TABLE_H
#include "RowAray.h"

    template<class T>
    class Table{
        protected:
            int szRow;
            int szCol;
            RowAray<T> **columns;
        public:
            Table(unsigned int,unsigned int);
            Table(const Table<T> &);
            virtual ~Table();
            int getSzRow()const {return szRow;}
            int getSzCol()const {return szCol;}
            T getData(int,int)const;
            void setData(int,int,T);
            Table<T> operator+(const Table<T> &);
    };

    #endif /* TABLE_H */

RowAray.cpp:
#include "RowAray.h"
#include <cstdlib>


template<class T> 
RowAray<T>::RowAray(int r) {
    size = r;

    rowData = new T[r];

    for (int i = 0; i < size; i++) {
        rowData[i] = static_cast<T>((rand() % 90 + 10));
    }
}

template<class T>
RowAray<T>::~RowAray() {
    delete []rowData;
}

template<class T>
void RowAray<T>::setData(int i, T value) {
    rowData[i] = value;
}


Table.cpp:
#include "Table.h"

template<class T>
Table<T>::Table(unsigned int r, unsigned int c) {
    szRow = r;
    szCol = c;

    columns = new RowAray<T>*[r];

    for(int i = 0; i < r; i++) {
        columns[i] = new RowAray<T>(c);
    }
}

    template<class T>
    Table<T>::Table(const Table<T> &t) {
        szRow = t.getSzRow();
        szCol = t.getSzCol();

        columns = new RowAray<T>*[t.getSzRow()];

        for(int i = 0; i < t.getSzRow(); i++) {
            columns[i] = new RowAray<T>(t.getSzCol());
        }

        for (int i = 0; i < t.getSzRow(); i++) {
            for (int j = 0; j < t.getSzCol(); j++) {
                columns[i]->setData(j, t.getData(i, j));
            }
        }
    }

    template<class T>
    Table<T>::~Table() {
        for (int i = 0; i < szRow; i++) {
            delete []columns[i];
        }
        delete []columns;
    }

        template<class T>
        Table<T> Table<T>:: operator+(const Table<T> &t) {
            Table<T> tab;

            tab.szRow = t.getSzRow();
            tab.szCol = t.getSzCol();

            for(int i = 0; i < t.getSzRow(); i++) {
                for (int j = 0; j <t.getSzCol(); j++) {
                    tab.columns[i]->setData(j, this->getData(i,j) + t.getData(i,j));
                }
            }

            return tab;
        }

main.cpp:
#include <cstdlib>
#include <ctime>
#include <iostream>
#include <iomanip>
using namespace std;

//User Libraries
#include "Table.h"

//Global Constants

//Function Prototype
template<class T>
void prntRow(RowAray<T> *,int);
template<class T>
void prntTab(const Table<T> &);

//Execution Begins Here!
int main(int argc, char** argv) {
   //Initialize the random seed
   srand(static_cast<unsigned int>(time(0)));

   //Declare Variables
   int rows=3,cols=4;

   //Test out the Row with integers and floats
   RowAray<int> a(3);RowAray<float> b(4);
   cout<<"Test the Integer Row "<<endl;
   prntRow(&a,3);
   cout<<"Test the Float Row "<<endl;
   prntRow(&b,4);

   //Test out the Table with a float
   Table<float> tab1(rows,cols);
   Table<float> tab2(tab1);
   Table<float> tab3=tab1+tab2;

   cout<<"Float Table 1 size is [row,col] = ["
           <<rows<<","<<cols<<"]";
   prntTab(tab1);

   cout<<"Float Table 2 size is [row,col] = ["
           <<rows<<","<<cols<<"]";
   prntTab(tab2);

   cout<<"Float Table 3 size is [row,col] = Table 1 + Table 2 ["
           <<rows<<","<<cols<<"]";
   prntTab(tab3);

   //Exit Stage Right
   return 0;
}

template<class T>
void prntRow(RowAray<T> *a,int perLine){
    cout<<fixed<<setprecision(1)<<showpoint<<endl;
    for(int i=0;i<a->getSize();i++){
        cout<<a->getData(i)<<" ";
        if(i%perLine==(perLine-1))cout<<endl;
    }
    cout<<endl;
}

template<class T>
void prntTab(const Table<T> &a){
    cout<<fixed<<setprecision(1)<<showpoint<<endl;
    for(int row=0;row<a.getSzRow();row++){
        for(int col=0;col<a.getSzCol();col++){
            cout<<setw(8)<<a.getData(row,col);
        }
        cout<<endl;
    }
    cout<<endl;
}

1 Ответ

0 голосов
/ 08 марта 2019

Не совсем понятно из вашего вопроса, но, предполагая, что вы хотите генерировать случайные значения различными способами для разных типов, вы можете использовать специализацию шаблонной функции:

template <class T>
T random_value(); // no definition

template <> 
float random_value<float>()
{
  return float(random()) / RAND_MAX; // number in [0, 1)
}

template <>
int random_value<int>()
{
  return random();
}

template <>
uint64_t random_value<uint64_t>()
{
  return (uint32_t(random()) << 32) | uint32_t(random());
}

А затем внутри RowArray::RowArray вы просто используете:

rowdata[i] = random_value<T>();

Чтобы объединить связанные специализации (например, все интегральные типы), взгляните на std::enable_if.

Второй способ сделать это в C ++ 17 - это if constexpr и std::is_same_v. Например, внутри вашего RowArray::RowArray конструктора вы можете сделать что-то вроде этого:

for (int i = 0; i < size; ++i)
{
  if constexpr (std::is_same_v<T, float>)
    row[i] = /* whatever you want for float case */
  else if constexpr (std::is_same_v<T, int>)
    row[i] = /* whatever you want for int case*/
  else
    static_assert(sizeof(T) == 0, "unsupported type");
}

Взгляните на заголовок type_traits, чтобы узнать, как проверить все целочисленные типы и т. Д.

Наконец, взгляните на библиотеку C ++ random http://www.cplusplus.com/reference/random/, чтобы избежать ошибок при работе со случайными значениями.

...