двумерный динамический массив
От: potap  
Дата: 28.11.02 08:24
Оценка: 1 (1)
Люди, просветите плиз.

Одномерный статический (с заранее известным размером)массив (char a[5]) легко переводится в одномерный динамический (с заранее НЕизвестным размером) массив (char* a=malloc(n)).

А как быть с двумерным (и более) массивом. Как перевести char a[5][7] в nxm динамический массив.

Спасибо за возможные ответы.
Re: Динамическим по одному или обоим измерениям?
От: Vi2 Удмуртия http://www.adem.ru
Дата: 28.11.02 08:29
Оценка:
Здравствуйте, potap, Вы писали:

P>А как быть с двумерным (и более) массивом. Как перевести char a[5][7] в nxm динамический массив.

Динамическим по одному или обоим измерениям?
Vita
Выше головы не прыгнешь, ниже земли не упадешь, дальше границы не убежишь! © КВН НГУ
Re: двумерный динамический массив
От: Аноним  
Дата: 28.11.02 08:29
Оценка:
Здравствуйте, potap, Вы писали:

P>Люди, просветите плиз.


P>Одномерный статический (с заранее известным размером)массив (char a[5]) легко переводится в одномерный динамический (с заранее НЕизвестным размером) массив (char* a=malloc(n)).

char * — это указатель на char, а не динамический массив.

P>А как быть с двумерным (и более) массивом. Как перевести char a[5][7] в nxm динамический массив.


char (*p)[5] = new char[5][7];
p[0][0] = 'x';
Re: двумерный динамический массив
От: Volnin L.V. Россия  
Дата: 28.11.02 08:31
Оценка:
Здравствуйте, potap, Вы писали:

P>Люди, просветите плиз.


P>Одномерный статический (с заранее известным размером)массив (char a[5]) легко переводится в одномерный динамический (с заранее НЕизвестным размером) массив (char* a=malloc(n)).


P>А как быть с двумерным (и более) массивом. Как перевести char a[5][7] в nxm динамический массив.


P>Спасибо за возможные ответы.


Двумерный массив — это одномерный массив указателей на одномерные массивы.
Динамически можно организовать, например так:

const int width=5,height=7;
int **a;
// создание
a=malloc(sizeof(int*)*width);
for(int i=0;i<width;i++)a[i]=malloc(sizeof(int)*height);

a[1][1]=10;
a[4][6]=1;

// удаление
for(i=0;i<width;i++)free(a[i]);
free(a);


Всего хорошего. Леонид
best regards, Leonid
Re: двумерный динамический массив
От: kmn Украина  
Дата: 28.11.02 08:34
Оценка:
Здравствуйте, potap, Вы писали:

P>Люди, просветите плиз.


P>Одномерный статический (с заранее известным размером)массив (char a[5]) легко переводится в одномерный динамический (с заранее НЕизвестным размером) массив (char* a=malloc(n)).


P>А как быть с двумерным (и более) массивом. Как перевести char a[5][7] в nxm динамический массив.


P>Спасибо за возможные ответы.


char * p = new char [M * N];

p[i][j] -->> p[i*N + j];
Re[2]: Динамическим по одному или обоим измерениям?
От: potap  
Дата: 28.11.02 08:36
Оценка:
Здравствуйте, Vi2, Вы писали:

Vi2>

P>>А как быть с двумерным (и более) массивом. Как перевести char a[5][7] в nxm динамический массив.

Vi2>Динамическим по одному или обоим измерениям?

По обоим — n- по одному, m- по другому.
Re[2]: двумерный динамический массив
От: potap  
Дата: 28.11.02 08:40
Оценка:
Здравствуйте, Аноним, Вы писали:

А>Здравствуйте, potap, Вы писали:


P>>Люди, просветите плиз.


P>>Одномерный статический (с заранее известным размером)массив (char a[5]) легко переводится в одномерный динамический (с заранее НЕизвестным размером) массив (char* a=malloc(n)).

А>char * — это указатель на char, а не динамический массив.

P>>А как быть с двумерным (и более) массивом. Как перевести char a[5][7] в nxm динамический массив.


А>char (*p)[5] = new char[5][7];

А>p[0][0] = 'x';

Ты, наверное, хотел сказать
char (*p)[5] = new char[5][n];//Вместо 7 — n
А>p[0][0] = 'x';

Но, насколько я понимаю — 5 в m никак не превратится, а мне заранее не известны оба измерения.
Re: двумерный динамический массив
От: Bell Россия  
Дата: 28.11.02 08:45
Оценка:
Здравствуйте, potap, Вы писали:

P>Люди, просветите плиз.


P>Одномерный статический (с заранее известным размером)массив (char a[5]) легко переводится в одномерный динамический (с заранее НЕизвестным размером) массив (char* a=malloc(n)).


P>А как быть с двумерным (и более) массивом. Как перевести char a[5][7] в nxm динамический массив.


P>Спасибо за возможные ответы.


Не забываем пользоваться поиском
Автор: Кодт
Дата: 23.09.02

Любите книгу — источник знаний (с) М.Горький
Re[3]: двумерный динамический массив
От: Аноним  
Дата: 28.11.02 08:45
Оценка:
Ну тогда способ, который тебе уже порекомендовали.

char ** p = new char*[n];
for(int i = 0; i < n; ++i)
*(p+i) = new char[m];
Re[2]: двумерный динамический массив
От: potap  
Дата: 28.11.02 08:50
Оценка:
Здравствуйте, Volnin L.V., Вы писали:

VLV>Двумерный массив — это одномерный массив указателей на одномерные массивы.

Если говорить про обычный (статический) массив, то это, имхо, неверно. Двумерный статический массив 5x7- это одномерный массив длиной 5x7=35. Данные лежат по строкам. Т.е. это не char** а char*.

VLV>Динамически можно организовать, например так:


VLV>[ccode]

VLV>const int width=5,height=7;
VLV>int **a;
VLV>// создание
VLV>a=malloc(sizeof(int*)*width);
VLV>for(int i=0;i<width;i++)a[i]=malloc(sizeof(int)*height);

В данной реализации, как я уже говорил, данные будут храниться не компактно, а кусками по height. А это, согласись, совершенно не эквивалентно статическому двумерному массиву. Кроме того, ничто тебе не мешает сделать "неровный", "рваный" массив — с неодинаковыми height, а мне это не нужно. У тебя char**, а мне нужно char*.
Re: двумерный динамический массив
От: wasilij  
Дата: 28.11.02 08:52
Оценка:
Здравствуйте, potap, Вы писали:

P>Люди, просветите плиз.


P>А как быть с двумерным (и более) массивом. Как перевести char a[5][7] в nxm динамический массив.


я бы сделал так:


class Array
{
    int n, m;
    char** p;
public:
    Array(int nRow, int nCol)
    {
        n = nRow;
        m = nCol;
        p = new char* [n];
        for(int i = 0; i < n; i++)
            p[i] = new char[m];
    }
    ~Array()
    {
        for(int i = 0; i < n; i++)
        {
            delete []p[i];
            p[i] = NULL;
        }
        delete []p;
    }
    char Get(int i, int j)
        {return p[i][j];}
    char Set(int i, int j, char ch)
        {return p[i][j] = ch;}
};


Хотя можно, наверно, как-то хитрее исподвыподвернуться....
Re[3]: двумерный динамический массив
От: Bell Россия  
Дата: 28.11.02 08:54
Оценка:
Здравствуйте, potap, Вы писали:

P>Здравствуйте, Volnin L.V., Вы писали:


VLV>>Двумерный массив — это одномерный массив указателей на одномерные массивы.

P>Если говорить про обычный (статический) массив, то это, имхо, неверно. Двумерный статический массив 5x7- это одномерный массив длиной 5x7=35. Данные лежат по строкам. Т.е. это не char** а char*.

Неверно.
Любите книгу — источник знаний (с) М.Горький
Re[2]: двумерный динамический массив
От: potap  
Дата: 28.11.02 08:57
Оценка:
Насколько я понимаю, это единственно реальный способ. В-общем, я обычно так и делаю, для удобства задефайнив последнюю строку
#define P(i,j) p[i*N + j]

kmn>char * p = new char [M * N];


kmn>p[i][j] -->> p[i*N + j];
Re[2]: двумерный динамический массив
От: potap  
Дата: 28.11.02 09:00
Оценка:
W>исподвыподвернуться
Re[4]: двумерный динамический массив
От: potap  
Дата: 28.11.02 09:01
Оценка:
Что именно неверно? Уточни, пожалуйста.

Здравствуйте, Bell, Вы писали:

B>Здравствуйте, potap, Вы писали:


P>>Здравствуйте, Volnin L.V., Вы писали:


VLV>>>Двумерный массив — это одномерный массив указателей на одномерные массивы.

P>>Если говорить про обычный (статический) массив, то это, имхо, неверно. Двумерный статический массив 5x7- это одномерный массив длиной 5x7=35. Данные лежат по строкам. Т.е. это не char** а char*.

B>Неверно.
Re[2]: двумерный динамический массив
От: wasilij  
Дата: 28.11.02 09:03
Оценка:
Здравствуйте, kmn, Вы писали:

kmn>char * p = new char [M * N];


kmn>p[i][j] -->> p[i*N + j];


Помоему, это то, что и требовалось, если еще добавить:

    char ** s = &p;
    s[i][j] = p[i*N+j];

будет совсем здорово.
Re[3]: двумерный динамический массив
От: potap  
Дата: 28.11.02 09:10
Оценка:
Не чувствую, что в этом более здорового .

Требовалось:
1. иметь некоторую переменную p- начальный адрес ЕДИНОГО куска памяти с данными.
2. обращаться к элементам массива — p[i][j].
3. на этапе компиляции неизвестны пределы, в которых будут меняться i и j.

Здравствуйте, wasilij, Вы писали:

W>Здравствуйте, kmn, Вы писали:


kmn>>char * p = new char [M * N];


kmn>>p[i][j] -->> p[i*N + j];


W>Помоему, это то, что и требовалось, если еще добавить:


W>
W>    char ** s = &p;
W>    s[i][j] = p[i*N+j];
W>

W>будет совсем здорово.
Re[5]: двумерный динамический массив
От: Bell Россия  
Дата: 28.11.02 09:13
Оценка:
Здравствуйте, potap, Вы писали:

P>Что именно неверно? Уточни, пожалуйста.


То, что "двумерный статический массив 5x7- это одномерный массив длиной 5x7=35. Данные лежат по строкам."

То, что все элементы двумерного статического массива лежат в одном блоке памяти, вовсе не означает, что это одномерный массив. К одномерному массиву нельзя применить [][], к двумерному — можно.

P>"Т.е. это не char** а char*."

Это ни то, и не другое. Это char[5][7].
Любите книгу — источник знаний (с) М.Горький
Re[4]: двумерный динамический массив
От: Bell Россия  
Дата: 28.11.02 09:24
Оценка: 3 (1)
Здравствуйте, potap, Вы писали:

P>Не чувствую, что в этом более здорового .


P>Требовалось:

P>1. иметь некоторую переменную p- начальный адрес ЕДИНОГО куска памяти с данными.
P>2. обращаться к элементам массива — p[i][j].
P>3. на этапе компиляции неизвестны пределы, в которых будут меняться i и j.

template<typename T>
class Arr
{
   T* m_pData;
   int m_nRows;
   ...
public:
   Arr(int nRows, int nColumns) : m_nRows(nRows) { m_pData = new T[nRows*nColumns]; }

   ...

   T* operator[] (size_t n) { return m_pData + n*m_nRows; }
   ...
};


использование:

Arr<int> arr(5, 7);
arr[1][2] = 3;


Преимущества — сохраняется семантика работы с двумерным массивом
Недостатки — невозможно проверять корректность второгл индекса.
Любите книгу — источник знаний (с) М.Горький
Re[5]: двумерный динамический массив
От: potap  
Дата: 28.11.02 09:35
Оценка:


B>
B>template<typename T>
B>class Arr
B>{
B>   T* m_pData;
B>   int m_nRows;
B>   ...
B>public:
B>   Arr(int nRows, int nColumns) : m_nRows(nRows) { m_pData = new T[nRows*nColumns]; }

B>   ...

B>   T* operator[] (size_t n) { return m_pData + n*m_nRows; }
B>   ...
B>};
B>


B>использование:


B>
B>Arr<int> arr(5, 7);
B>arr[1][2] = 3;
B>
Re[4]: двумерный динамический массив
От: wasilij  
Дата: 28.11.02 09:38
Оценка:
Здравствуйте, potap, Вы писали:

P>Не чувствую, что в этом более здорового .


P>Требовалось:

P>1. иметь некоторую переменную p- начальный адрес ЕДИНОГО куска памяти с данными.
P>2. обращаться к элементам массива — p[i][j].
P>3. на этапе компиляции неизвестны пределы, в которых будут меняться i и j.

ну может тогда так:


class xxx
{
    char data;
public:
    char& operator [](int i) {return data;}
};
//...
xxx * p = new xxx [M * N];
p[i][j] = 0;
//...
Re[6]: двумерный динамический массив
От: Bell Россия  
Дата: 28.11.02 09:39
Оценка:
Здравствуйте, potap, Вы писали:

P>


И все-таки почитай топик, ссылку на который я дал ниже.
Любите книгу — источник знаний (с) М.Горький
Re[6]: двумерный динамический массив
От: Аноним  
Дата: 28.11.02 09:49
Оценка:
Он (потап) говорит о представлении массива в памяти. Если есть int a[5][5];
Можно написать int * pD1 = *a; и далее писать p[i_num*5+j_num] = 10; или a[i_num][j_num] = 10;
Re[5]: двумерный динамический массив
От: potap  
Дата: 28.11.02 10:00
Оценка:
Что-то не то. У тебя

char& operator [](int i) {return data;}

возвращает одну и ту же data для разных i, что, очевидно, неправильно.


W>ну может тогда так:


W>

W>
W>class xxx
W>{
W>    char data;
W>public:
W>    char& operator [](int i) {return data;}
W>};
W>//...
W>xxx * p = new xxx [M * N];
W>p[i][j] = 0;
W>//...
W>
Re: двумерный динамический массив
От: ilnar Россия  
Дата: 28.11.02 12:01
Оценка:
Здравствуйте, potap, Вы писали:

P>Люди, просветите плиз.


P>Одномерный статический (с заранее известным размером)массив (char a[5]) легко переводится в одномерный динамический (с заранее НЕизвестным размером) массив (char* a=malloc(n)).


P>А как быть с двумерным (и более) массивом. Как перевести char a[5][7] в nxm динамический массив.


P>Спасибо за возможные ответы.



char **a=(char**)malloc(n);
for(int i=0; i<n; i++)
   a[i]=(char*)malloc(m);
Re[5]: двумерный динамический массив
От: kmn Украина  
Дата: 28.11.02 12:25
Оценка:
Здравствуйте, Bell, Вы писали:

B>Здравствуйте, potap, Вы писали:


P>>Не чувствую, что в этом более здорового :???: .


P>>Требовалось:

P>>1. иметь некоторую переменную p- начальный адрес ЕДИНОГО куска памяти с данными.
P>>2. обращаться к элементам массива — p[i][j].
P>>3. на этапе компиляции неизвестны пределы, в которых будут меняться i и j.

B>
B>template<typename T>
B>class Arr
B>{
B>   T* m_pData;
B>   int m_nRows;
B>   ...
B>public:
B>   Arr(int nRows, int nColumns) : m_nRows(nRows) { m_pData = new T[nRows*nColumns]; }

B>   ...

B>   T* operator[] (size_t n) { return m_pData + n*m_nRows; }
B>   ...
B>};
B>


B>использование:


B>
B>Arr<int> arr(5, 7);
B>arr[1][2] = 3;
B>


B>Преимущества — сохраняется семантика работы с двумерным массивом

B>Недостатки — невозможно проверять корректность второгл индекса.


или так если хочется контроликовать диапазоны

template <typename T>  class Array2
{
protected:
    T * m_pData;
    int m_nColumns;
    int m_nRows;

    class Proxy
    {
    public:
        Proxy(T * p, int nRows)
        {
            m_nRows = nRows;
            m_pData = p;
        }
        ~Proxy()
        {
        }

        T operator [] (int n) const
        {
            ASSERT ((UINT)n < (UINT)m_nRows);
            return m_pData[n];
        }

        T& operator [] (int n)
        {
            ASSERT ((UINT)n < (UINT)m_nRows);
            return m_pData[n];
        }

    private:
        T * m_pData;
        int m_nRows;
    };
public:
    Array2(int nColumns,  int nRows)
    {
        m_nRows = nRows;
        m_nColumns = nColumns;
        m_pData = new T [nColumns * nRows];
    }
    ~Array2()
    {
        delete [] m_pData;
    }

    Proxy operator [] (int m)
    {
        ASSERT ((UINT)m < (UINT)m_nColumns);
        return Proxy(m_pData + m * m_nRows, m_nRows);
    }

    // или Так без проверки Rows    
        /*
    T * operator [] (int m)
    {
        ASSERT ((UINT)m < (UINT)m_nColumns);
        return m_pData + m * m_nRows;
    }
    */
};


    Array2<int> arr(5, 6);

    arr[3][4] = 123;
    int i34 = arr[3][4];
Re: двумерный динамический массив
От: Gregory Россия ICQ 300403361
Дата: 28.11.02 13:18
Оценка:
Здравствуйте, potap, Вы писали:

P>Люди, просветите плиз.


P>Одномерный статический (с заранее известным размером)массив (char a[5]) легко переводится в одномерный динамический (с заранее НЕизвестным размером) массив (char* a=malloc(n)).


P>А как быть с двумерным (и более) массивом. Как перевести char a[5][7] в nxm динамический массив.


Нет, с точки зрения машинного представления, разницы между 1-мерным и n-мерным массивом (если не рассматривать масивы а-ля Java). Это в том и в другом случае некоторая область памяти. Есть разница, с точки зрения компилятора и программера в способе адресации этой памяти. Так для получения элемента одномерного массива TYPE A[n], мы пишем A[i], что буквально означает
*((char*)A + (char)sizeof(TYPE)*i)). Для двумерного массива TYPE A[m][n], выражение A[i][j], будет означать
*((char*)A + (char)sizeof(TYPE)*i) + (char)sizeof(TYPE)*j) и т.д.
Т.е. можно прописать некий класс с соответствующими конструкторами и набором операторов ( типа (int i, int j) ), в котором сам массив
будет представлен в виде непрерывной области памяти, а задача распределения и адресации этой памяти реализуется при помощи функций-членов.
Не дай своим глазам увидеть, а ушам услышать то, что ты не сможешь объяснить.
Абрахам ван Хелсинг
Re: двумерный динамический массив
От: MaxS Удмуртия http://www.sautin.com
Дата: 28.11.02 13:58
Оценка:
Здравствуйте, potap, Вы писали:

P>Люди, просветите плиз.


P>Одномерный статический (с заранее известным размером)массив (char a[5]) легко переводится в одномерный динамический (с заранее НЕизвестным размером) массив (char* a=malloc(n)).


P>А как быть с двумерным (и более) массивом. Как перевести char a[5][7] в nxm динамический массив.


P>Спасибо за возможные ответы.

Привет, вот небольшой пример создания двумерного массива:


#include <stdio.h>
#include <stdlib.h>

typedef int T;

T **Allocate(size_t m, size_t n)
{
  int **a;
  int *p;
  size_t Row;
  a = malloc(m * n * sizeof **a + m * sizeof *a);
  if(a != NULL)
  {
    for(Row = 0, p = (T *)a + m; Row < m; Row++, p += n)
    {
      a[Row] = p;
    }
  }
  return a;
}



вместо T можешь подставить любой другой тип.
Пока.
Трудно ничего не делать, но мы не боимся трудностей.
Re: двумерный динамический массив
От: WolfHound  
Дата: 28.11.02 15:01
Оценка:
Здравствуйте potap, Вы писали:

Возможно это пригодится.http://www.rsdn.ru/forum/Message.aspx?mid=142144&amp;only=1
Автор: WolfHound
Дата: 28.11.02
... << RSDN@Home 1.0 alpha 12 >>
Пусть это будет просто:
просто, как только можно,
но не проще.
(C) А. Эйнштейн
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.