Лучший способ представить двумерный массив на C ++ с размером, определяемым во время выполнения
-
05-07-2019 - |
Вопрос
В C ++ я бы хотел сделать что-то вроде:
int n = get_int_from_user();
char* matrix = new char[n][n];
matrix[0][0] = 'c';
//...
matrix[n][n] = 'a';
delete [][] matrix;
но, конечно, это не работает.Каков наилучший способ сделать что-то подобное?Я видел несколько решений для этого, но они кажутся довольно запутанными.
Решение
Ручной динамический способ:
Допустим, вам нужен массив width * height, наиболее эффективный способ - просто использовать одномерный массив:
char *matrix = new char[width*height];
Чтобы удалить его:
delete[] matrix;
Чтобы получить к нему доступ:
char getArrayValue(char *matrix, int row, int col)
{
return matrix[row + col*width];
}
Чтобы изменить его:
void setArrayValue(char *matrix, int row, int col, char val)
{
matrix[row + col*width] = val;
}
<Ч>
Матрица повышения:
Рассмотрите возможность использования boost :: matrix если вы можете иметь зависимость.
Затем вы можете подключиться к линейному ускорению. алгебра библиотеки.
Вот несколько пример кода повышения: : матрица :
#include <boost/numeric/ublas/matrix.hpp>
using namespace boost::numeric::ublas;
matrix<char> m (3, 3);
for (unsigned i = 0; i < m.size1 (); ++ i)
for (unsigned j = 0; j < m.size2 (); ++ j)
m (i, j) = 3 * i + j;
<Ч>
В стеке для некоторых компиляторов:
Некоторые компиляторы фактически позволяют вам создавать массивы в стеке с определенными размерами во время выполнения. g ++ является примером такого компилятора. Вы не можете сделать это по умолчанию VC ++, хотя. Р>
Так что в g ++ это правильный код:
int width = 10;
int height = 10;
int matrix[width][height];
Дрю Холл упомянул, что эта функция C99 называется массивами переменной длины (VLA) и, вероятно, ее можно включить в любом современном компиляторе. Р>
Другие советы
Я обычно делаю что-то вроде этого:
char *matrix = new char [width * height];
matrix[i + j * width] = 'c'; // same as matrix[i][j] = 'c';
delete [] matrix;
Как насчет std::vector< std::vector<int> > array2d;
?
Кажется, вы упускаете весь смысл C ++ (C с классами) :-).Это тот вид использования, который требует, чтобы класс реализовал его.
Ты мог бы просто используйте STL или другую стороннюю библиотеку классов, которая, я уверен, будет иметь структуру данных, которую вы ищете, но, если вам нужно создать свою собственную, просто создайте класс со следующими свойствами.
- конструктор, который, учитывая n, просто создаст новый n * n массив символов (например, charray)..
- функции-члены, которые получают и устанавливают значения на основе x.y, которые просто ссылаются на charray [x* n + y];
- деструктор, который удаляет массив[].
Для истинного двумерного массива:
int n = get_int_from_user();
char** matrix = new char*[n];
for (int i = 0; i < n; i++) {
matrix[i] = new char[n];
}
// Operations on matrix.
for (int i = 0; i < n; i++) {
delete [] matrix[i];
}
delete matrix;
Просто с макушки головы. Ошибки, без сомнения. Однако другие люди опубликовали более элегантный подход, я думаю.
делать это вручную - беспорядок.
Мне нравится подход с 1-мерным массивом (выбранный ответ Брайана Р. Бонди) с расширением, в котором вы заключаете элементы данных в класс, так что вам не нужно отдельно отслеживать ширину: р>
class Matrix
{
int width;
int height;
char* data;
public:
Matrix();
Matrix(int width, int height);
~Matrix();
char getArrayValue(int row, int col);
void setArrayValue(int row, int col, char val);
}
Реализация - это упражнение для читателя. ;) Р>
Я думаю, что это было бы хорошо.
int n = get_int_from_user();
char **matrix=new (char*)[n];
for(int i=0;i<n;i++)
matrix[i]=new char[n];
matrix[0][0] = 'c';
//...
matrix[n][n] = 'a';
for(int i=0;i<n;i++)
delete []matrix;
delete []matrix;
std::vector<int> m;
Затем вызовите m.resize () во время выполнения.
int* matrix = new int[w*h];
если вы хотите сделать что-то вроде исключения по Гауссу, ваша матрица должна быть
int** matrix = new int*[h];
for(size_t i(0); i < h; ++i)
matrix[i] = new int[w];
(в методе исключения Гаусса нам обычно нужно обмениваться одной строкой с другой, поэтому лучше поменять местами указатели на строки за постоянное время, а не копировать с помощью копирования за линейное время).