2013-07-18 2 views
-1

У меня этот многомерный динамический массив, и я могу распечатать его как шесть строк из шести столбцов нулей, но я не могу вернуть его как одно и то же. Предполагается, что функция инициализирует массив, который может быть передан другим функциям. Что я здесь делаю неправильно? Я прокомментировал части «cout», потому что это не то, что мне нужно сделать. Благодаря!Возвращение многомерного динамического массива?

long initializeArray (void) 
{ 
    int i = 0, j = 0; 
    typedef int* rollarray; 
    rollarray *m = new rollarray[6]; 
    for (int i = 0; i < 6; i++) m[i] = new int[6]; 
    while (j < 6) 
    { 
     while (i < 6) 
     { 
      m[i][j] = 0; 
      //cout << m[i][j] << " "; 
      i++; 
     } 
     //cout << endl; 
     i = 0; 
     j++; 
    } 
} 
+0

Это C++ не использовать указатели, используйте СТЛ контейнеры – aaronman

+0

Вы можете просто передать указатель; В вашем текущем случае вы используете локальную переменную '* m' и возвращаете ее без смысла. – ludesign

+3

Где ваше заявление 'return' или ваш параметр? Трудно вернуть что-либо без того или другого. – jxh

ответ

4

Вы должны объявить функцию:

int** initializeArray(void)

, а затем:

return m;

в конце концов, если вы должны сделать это таким образом. Не забывайте, что вам придется вручную рассказать что-нибудь еще, что использует этот указатель, что это массив размером 6 x 6, и не забывайте, что все эти массивы, когда вы закончите с ними, не забудьте сделать delete[].

+0

+1, потому что это единственный ответ, который фактически отвечает на вопрос. Тем не менее, я согласен с тем, что использование динамического массива динамических массивов может быть не правильным, в первую очередь, если вам действительно не нужно обрабатывать строки разного размера. – Boris

+0

Это также единственный ответ, который не отвечает на следующие 5 вопросов, связанных с проблемами с необработанными указателями, утечками памяти, неопределенным поведением, ошибками сегментации и т. Д. Из-за использования raw-указателя. Конечно, учиться на ошибках желательно, если интересы OP имеют академический характер. Без сомнения, узнает ли он что-нибудь о указателях, если он продолжит движение, но также может случиться так, что переход прямо по правильному пути приведет к лучшему ощущению «способа поведения на C++». Как говорит Страуступ: «Не взламывайте, не концентрируйтесь на алгоритмах!» (или подобное я точно не помню).) – Pixelchemist

+0

Я согласен в какой-то степени, и я не думаю, что нужно потратить много времени на изучение «плохих старых дней», прежде чем делать что-то на C++. Однако, как это или нет, указатели являются частью C++, и любой хорошо продуманный программист на C++ должен будет научиться правильно работать с ними в конечном итоге. 'std :: vector' не поможет многим людям, которые хотят получить доступ к оборудованию, или, например, написать свои собственные эффективные контейнеры. –

2

Я не буду повторять свой полный ответ о том, почему динамические двумерные матрицы (и это явно одно) не являются способом перехода на C++.

Answer on: 1D or 2D array, what's faster? (Начать чтение @длинный ответ, или почему динамическая 2 мерная хранения данных (указатель на указатель или вектор-из-вектора) является «плохой» для простых/небольших матриц.)

вы найдете:

  • довольно подробное объяснение, почему вы не хотите использовать указатель на указатель динамические массивы
  • пример класса для простой матрицы Объекты

Вам даже не нужна функция, которая инициализирует ваши данные до нуля. Просто напишите

matrices::simple<int> matrix_object(6, 6); 

, чтобы получить нулевой инициализированному матрицу размером 6x6.

Теперь вы можете получить доступ к элементам через

matrix_object(0,1) = 2; // sets 2nd element of first row to 2 

«C++ путь» писать матрицу в поток будет включать определение operator<< для этого класса, как:

template<typename T> 
std::ostream & operator<< (std::ostream &stream, matrices::simple<T> const & matrix) 
{ 
    typedef typename matrices::simple<T>::size_type size_type; 
    for (size_type i(0u); i<matrix.rows(); ++i) 
    { 
    for (size_type j(0u); j<matrix.cols(); ++j) 
     stream << std::setw(4) << std::right << matrix(i,j); 
    stream << std::endl; 
    } 
    return stream; 
} 

Вы могли бы легко вывести ваша матрица таким образом, написав:

std::cout << matrix_object << std::endl; 

Вместе с предыдущей средой PTEs этот выход будет:

 0 2 0 0 0 0 
    0 0 0 0 0 0 
    0 0 0 0 0 0 
    0 0 0 0 0 0 
    0 0 0 0 0 0 
    0 0 0 0 0 0

Если вы хотите, чтобы продолжать идти по указателям вам придется решить несколько проблем в вашем коде. Я добавил два параметра для других размеров, но при необходимости их можно заменить на 6.

int** new_initialized_array (size_t const rows, size_t const cols) 
{ 
    typedef int* rollarray; 
    rollarray *m = new rollarray[rows]; 
    size_t allocated_arrays(0u); 
    try 
    { 
     for (size_t i(0u); i < rows; ++i) 
     { 
     m[i] = new int[cols]; 
     ++allocated_arrays; 
     for (size_t j(0u); j<cols; ++j) m[i][j] = 0; 
     } 
    } 
    catch (std::bad_alloc & e) 
    { 
     for (size_t i(0u); i < allocated_arrays; ++i) delete[] m[i]; 
     delete[] m; 
     throw; 
    } 
    return m; 
} 

Вопросы, я обратился:

  1. Чтобы вернуть указатель, функция должна иметь тип возвращаемого значения, что на самом деле является указателем (долго это значение без знака).
  2. Вам необходимо отследить выделение. Если один из них не работает, вам придется откатить все остальное, чтобы избежать утечек памяти.
  3. Вам не нужен цикл двойного цикла. У вас уже есть внешний контур (тот, который вы назначаете), поэтому вам нужно только внутренний цикл для установки начальных значений для вашего массива.
  4. И последнее, но не менее важное. Я переименовал функцию. Он фактически не «инициализирует» существующий массив, а создает новый, инициализированный.

Я могу рекомендовать только прочитать ссылку (или любой другой ресурс о том, как обрабатывать 2D-данные в соответствии с RAII).

2

C++ :)

#include <vector> 
#include <iostream> 

std::vector<std::vector<int> > initializeVector() { 
    std::vector<std::vector<int> > vec(6, std::vector<int>(6)); 

    int i = 0, j = 0; 
    while (i < 6) { 
     while (j < 6) { 
      vec[i][j] = i+j; 
      j++; 
     } 

     j = 0; 
     i++; 
    } 

    return vec; 
} 

int main(int argc, char* argv[]) { 
    std::vector<std::vector<int> > g_vec = initializeVector(); 

    int i = 0, j = 0; 
    while (i < 6) { 
     while (j < 6) { 
      std::cout << g_vec[i][j] << std::endl; 
      j++; 
     } 

     std::cout << "-----------------" << std::endl; 
     j = 0; 
     i++; 
    } 

    return 0; 
} 
1

ли это домашнее задание? Или вы пытаетесь сделать Matrix Algebra в C++?

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

Посмотрите в библиотеку Эйгеном: http://eigen.tuxfamily.org/dox/TutorialAdvancedInitialization.html

// Initializing a 6x6 dynamic size matrix with zeros, adapted from documentation 
using namespace Eigen; 
ArrayXXf a3 = ArrayXXf::Zero(6, 6); 
std::cout << a3 << "\n"; 
+0

+1 для Eigen, эта библиотека просто потрясающая – Boris