Лучший способ представить двумерный массив в C ++ с размером, определенным во время выполнения - PullRequest
19 голосов
/ 02 ноября 2008

В C ++ я хотел бы сделать что-то вроде:

int n = get_int_from_user();

char* matrix = new char[n][n];

matrix[0][0] = 'c';
//...
matrix[n][n] = 'a';

delete [][] matrix;

но, конечно, это не работает. Каков наилучший способ сделать что-то подобное? Я видел некоторые решения, но они кажутся довольно грязными.

Ответы [ 9 ]

24 голосов
/ 02 ноября 2008

Ручной динамический способ:

Допустим, вам нужен массив 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 , если есть зависимость.

Затем вы можете связать библиотеки линейной алгебры надстроек .

Вот пример примера кода 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) и, вероятно, ее можно включить в любом современном компиляторе.

9 голосов
/ 02 ноября 2008

Я обычно делаю что-то вроде этого:

char *matrix = new char [width * height];

matrix[i + j * width] = 'c'; // same as matrix[i][j] = 'c';

delete [] matrix;
4 голосов
/ 02 ноября 2008

А как же std::vector< std::vector<int> > array2d;?

4 голосов
/ 02 ноября 2008

Кажется, вам не хватает всего смысла в C ++ (C с классами) :-). Это тот тип использования, который требует класс для его реализации.

Вы могли бы просто использовать STL или другую стороннюю библиотеку классов, которая, я уверен, будет иметь структуру данных, которую вы ищете, но, если вам нужно свернуть свою собственную, просто создайте класс с следующие свойства.

  • конструктор, который при заданном n просто создаст новый n * n массив символов char (например, charray) ..
  • функции-члены, которые получают и устанавливают значения на основе x.y, которые просто ссылаются на charray [x * n + y];
  • деструктор, который удаляет [] массив.
3 голосов
/ 02 ноября 2008

Для истинного двумерного массива:

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;

Просто с макушки головы. Ошибки, без сомнения. Однако другие люди опубликовали более элегантный подход, я думаю.

2 голосов
/ 04 ноября 2008

Мне нравится подход массива 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);
}

Реализация - упражнение для читателя. ;)

2 голосов
/ 02 ноября 2008

повышение :: multi_array

делать это вручную будет беспорядком.

0 голосов
/ 27 февраля 2015
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];

(при исключении по Гауссу нам обычно нужно обмениваться одной строкой с другой, поэтому лучше поменять местами указатели на строки за постоянное время, а не копировать с помощью копирования за линейное время).

0 голосов
/ 21 ноября 2010

Я думаю, что это было бы хорошо.

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;
...