#c #arrays #templates #dynamic #netbeans
#c #массивы #шаблоны #динамический #netbeans
Вопрос:
Итак, я работал над программой, в которой я использую 2d-массивы и шаблоны для печати матриц на Netbeans 8.2. Мне разрешено записывать только файлы реализации. (т. Е. Мне не разрешено добавлять функции into / ditch из файлов заголовков или main.)
В идеале, если объект класса имеет тип int, он будет печатать 2d-массив, который заполняется случайными целыми числами; если объект класса имеет тип float , он будет печатать 2d-массив, который заполняется случайными числами с плавающей запятой. До сих пор мне удавалось получать выходные данные 2D-массива, и результат кажется законным. Однако я продолжаю получать это исключение «0 [main] review3_cis17c_template_ 302 cygwin_exception::open_stackdumpfile: сброс трассировки стека в review3_cis17c_template_.exe.stackdump», которое, как я полагаю, связано с неправильным использованием ключа удаления в Table.h.
В чем причина проблемы? Я не смог найти ничего неправильного в моем механизме выделения памяти. Я опубликую свой Table.h, RowAray.h и main.cpp поскольку все они являются согласованными.
Вот мой RowAray.h:
#ifndef ROWARAY_H
#define ROWARAY_H
#include<iostream>
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>=0amp;amp;i<size)return rowData[i];
else return 0;}
void setData(int,T);
};
#include <cstdlib>
template<class T>
RowAray<T>::RowAray(int r) {
size = r;
rowData = new T[r];
for (int i = 0; i < r; 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;
}
#endif /* ROWARAY_H */
Вот моя таблица.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> amp;);
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> amp;);
};
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> amp;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>
T Table<T>::getData(int r, int c) const {
return columns[r]->getData(c);
}
template<class T>
Table<T>::~Table() {
for (int i = 0; i < szRow; i ) {
delete []columns;
}
delete columns;
}
template<class T>
Table<T> Table<T>::operator (const Table<T> amp;t) {
Table<T> tab(t.getSzRow(), 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;
}
#endif /* TABLE_H */
И, наконец, мой 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> amp;);
//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(amp;a,3);
cout<<"Test the Float Row "<<endl;
prntRow(amp;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> amp;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. Вы могли / должны были создать
columns
вTable
классе aRowAray<RowAray<T>>
вместоRowAray<T>**
, что сокращает весь тот код, который у вас естьTable
сейчас, который пытается выполнить динамическое выделениеRowAray
. Тогда все процедуры динамического выделения будут изолированы отRowAray
класса, и там будут обнаружены любые ошибки.2. Кроме того, вам
RowAray
необходимо реализовать определяемый пользователем конструктор копирования и оператор присваивания. Как только у вас эти две функции заработают должным образом,Table
автоматически заработает (если вы использовали то, что я предложил в моем первом комментарии).3. Но если вы хотите (или должны) сделать это сложным способом, держу пари, вы можете довольно быстро решить проблему с помощью интерфейса GDB, встроенного в Netbeans. Создайте отладочный исполняемый файл, запустите его в GDB через Netbeans, дождитесь сбоя и соберите информацию, когда отладчик остановится. Используйте собранную информацию, чтобы решить, где вы хотите искать дальше, поместите там breakpont, запустите программу снова. Продолжайте, пока проблема не будет решена.
4. Ваш
Table
деструктор выглядит странно:for (int i = 0; i < szRow; i ) {delete []columns;}
. Что здесь удаляется? Вы удаляете одно и то же снова и снова в цикле. Но опять же, в этом нет необходимости, если вы делегировали все управление динамической памятьюRowAray
(что вам действительно следует сделать).5. Кроме того, ваш
RowAray<T>::getData
возвращает 0, если размер выходит за рамки. Это сбивает с толку, поскольку нет никаких указаний на то, что индекс выходит за рамки, и если у вас было что-то вродеRowAray<std::string>
, то преобразование в0
отсутствует. Лучше просто выдать исключение, ничего не возвращая.