Форум программистов «Весельчак У»
  *
Добро пожаловать, Гость. Пожалуйста, войдите или зарегистрируйтесь.
Вам не пришло письмо с кодом активации?

  • Рекомендуем проверить настройки временной зоны в вашем профиле (страница "Внешний вид форума", пункт "Часовой пояс:").
  • У нас больше нет рассылок. Если вам приходят письма от наших бывших рассылок mail.ru и subscribe.ru, то знайте, что это не мы рассылаем.
   Начало  
Наши сайты
Помощь Поиск Календарь Почта Войти Регистрация  
 
Страниц: [1] 2  Все   Вниз
  Печать  
Автор Тема: [C++] динамический массив в классе  (Прочитано 72138 раз)
0 Пользователей и 4 Гостей смотрят эту тему.
Rustam
Гость
« : 20-05-2010 18:37 » 

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

спасибо!
Записан
Finch
Спокойный
Администратор

il
Offline Offline
Пол: Мужской
Пролетал мимо


« Ответ #1 : 20-05-2010 19:29 » 

Пока отбросим классы. Как создается динамический массив?
Записан

Не будите спашяго дракона.
             Джаффар (Коша)
Rustam
Гость
« Ответ #2 : 20-05-2010 19:48 » 

как создать динамический массив я знаю
процедуру я написал, он мне выдаёт ошибку:

Type '<имя класса>' may not be defined here
Записан
Sla
Команда клуба

ua
Offline Offline
Пол: Мужской

WWW
« Ответ #3 : 20-05-2010 19:57 » 

Rustam, код в студию...
Записан

Мы все учились понемногу... Чему-нибудь и как-нибудь.
Rustam
Гость
« Ответ #4 : 20-05-2010 20:18 » 

Код:
#include <iostream.h>
#include <assert.h>
#include <conio.h>
#include <alloc.h>
#include <stdio.h>
class graf
{
int **mas();
 public:
int n;
//**mas(void);
**izmas(int **x, int **z);
prov();
}
 graf::**mas(void)
{
 int i,j;
 int **z;
 clrscr();
 z=(int**)malloc(n*sizeof(int*));
 for(i=0;j<n;i++)
 {
  z[i]=(int*)malloc(n*sizeof(int*));
  for(j=0;i<n;i++)
  {z[i][j]=0;}
 }
 for (i=0;i<n;i++)
 for (j=0;j<n;i++)
 {
  printf("\nVvedite element matrici A(%d,%d)",i+1,j+1);
  scanf("%d",&z[i][j]);}
 return z;}

void graf::prov()
{
 int i,j,k,kol,nachuz,nachuz2;
 for (i=0,nuchuz=0,kol=0,i<n,i++)
 {
  for (j=0,k=0,j<n,j++)
  if (z[i][j]=1) k+=1;
  if (k%2=1) {kol+=1; if (nachuz=0) nuchuz=i else nachuz2=i;}}
  if (kol=2) {printf("\nLiniya UNIKURSALNA");
      printf("\nNachat s uzla %d ili %d",nachuz,nachuz2);}
  else printf("LINIYA NE YVLYAETSA UNIKUrSALNOI");
}

void main()
{
 int **a,**b;
 printf("Vvedite kolichestvo uzlov=");
 scanf(&n);
 a=mas(void);
 prov(a);
 free(a);
 getch();
}
Записан
Алексей++
глобальный и пушистый
Глобальный модератор

ru
Offline Offline
Сообщений: 13


« Ответ #5 : 21-05-2010 03:06 » 

точно одна ошибка уже есть - не поставлена ";" после class graf{...}

затем,

int** graf::mas(void)
{
}
Записан

Вад
Модератор

ru
Offline Offline
Пол: Мужской

« Ответ #6 : 21-05-2010 05:48 » 

Rustam, говоришь, умеешь создавать. Но память так выделяется обычно в С, а в C++ есть другой способ - оператор new[]. И потом: а кто будет освобождать всю выделенную память? У тебя освобождается только первый кусок, с указателями на указатели, а блоки, выделяемые под данные, не освобождаются нигде.

Теперь собственно к задаче: класс в данном случае не имеет смысла, если просто умеет создавать массивы (выделять память) - так можно было просто набор функций написать. Смысл задачи, полагаю, в том, чтобы объект класса и был массивом. То есть, содержал бы вот этот указатель в качестве поля - так же, как он у тебя содержит поле размера (n).

Для конструирования (инициализации) экземпляра класса должен быть конструктор. У тебя массив имеет две размерности (в случае массива n*n они равны) - конструктор должен иметь соответствующие параметры и выделять память нужного размера (то, чем у тебя занимается mas).

Где конструктор - там и деструктор. Особенно когда мы говорим о работе с динамической памятью. Деструктор должен освобождать все ресурсы, выделенные под объект (в данном случае - память).

Для доступа к массиву должны быть соответствующие функции (в самом простом варианте - get(x, y) и set(x,y, value) ) - потому что коль скоро это ты решил завести класс, то данные (указатель) принято прятать от окружающего мира. Таким образом, внешний код может совершать над массивом только определённые операции, криминал типа "вручную заменить что-то там" исключается: управление данными осуществляется методами класса, и никак больше.

Главное, нужно разобраться с тем, что такое класс, и для чего он нужен. Тогда сами собой должны отпасть странные решения вроде того, чтобы просто собрать туда набор функций или делать ввод-вывод данных для пользователя прямо в методах класса.
Записан
Rustam
Гость
« Ответ #7 : 21-05-2010 06:34 » 

Спасибо!
Буду думать
Записан
lazy_troll
Интересующийся

ru
Offline Offline

« Ответ #8 : 21-05-2010 12:39 » 

Спасибо!
Буду думать

А зачем тебе двухмерный массив?

В плане управления памятью и быстродействия - имхо, будет удобнее представить реализацию класса одномерным массивом с публичными методами set(x,y) и get(x,y)

Записан

Do not feed the troll
Finch
Спокойный
Администратор

il
Offline Offline
Пол: Мужской
Пролетал мимо


« Ответ #9 : 21-05-2010 14:27 » 

lazy_troll,   Что лучше, объясни преподавателю. Раз есть задание сделать так, значит нужно.
Записан

Не будите спашяго дракона.
             Джаффар (Коша)
Джон
просто
Администратор

de
Online Online
Пол: Мужской

« Ответ #10 : 21-05-2010 15:03 » 

lazy_troll, стесняюсь спросить, а в чём конкретно преимущество одномерного массива С++ перед двумерным в плане быстродействия и управления памятью? Желательно с примером (для наглядности).
Записан

Я вам что? Дурак? По выходным и праздникам на работе работать. По выходным и праздникам я работаю дома.
"Just because the language allows you to do something does not mean that it’s the correct thing to do." Trey Nash
"Physics is like sex: sure, it may give some practical results, but that's not why we do it." Richard P. Feynman
"All science is either physics or stamp collecting." Ernest Rutherford
"Wer will, findet Wege, wer nicht will, findet Gründe."
lazy_troll
Интересующийся

ru
Offline Offline

« Ответ #11 : 21-05-2010 17:26 » new



Джон, быстродействие: 2х мерному массиву потребуется считать из массива первого уровня адрес массива второго уровня, а потом уже получить из него данные

В плане управления памятью: очень много возни с выделением и удалением массивов 2 уровня, и Вад уже нашел ошибку в коде
Записан

Do not feed the troll
Finch
Спокойный
Администратор

il
Offline Offline
Пол: Мужской
Пролетал мимо


« Ответ #12 : 21-05-2010 17:40 » 

lazy_troll, А что считать? Чтоб посчитать смешение в массиве указателей, достаточно умножить на 4  Замечу, что умножить на 4 довольно быстрое действо. Это всего лиш сдвиг влево на 2 позиции. Выташить указатель на вторую размерность, и считать уже смешение для второй размерности только.
Чтобы работать в одномерном массиве, как в двухмерном. Нужно будет делать два раза умножение. Так что на счет скорости работы, не совсем точное утверждение. Да при этом на иницилизацию и удаление затрачивается чуть больше времени и памяти.
Записан

Не будите спашяго дракона.
             Джаффар (Коша)
Вад
Модератор

ru
Offline Offline
Пол: Мужской

« Ответ #13 : 21-05-2010 18:43 » 

Finch, ещё, если выделять единым куском, возможно, будет профит при кэшировании.
Записан
Finch
Спокойный
Администратор

il
Offline Offline
Пол: Мужской
Пролетал мимо


« Ответ #14 : 21-05-2010 19:22 » 

Вад, В принципе, если выделяется память сразу, то есть большой процент вероятности, что все выделенные участки лягут рядом с друг другом. С другой сторону, если имеется массив больше чем кеш процессора, и произвольно гулять по массиву. Там уже без разници, как будет строиться массив.
Записан

Не будите спашяго дракона.
             Джаффар (Коша)
Антон (LogRus)
Глобальный модератор

ru
Offline Offline
Пол: Мужской
Внимание! Люблю сахар в кубиках!


WWW
« Ответ #15 : 21-05-2010 20:11 » 

Finch, я полагаю, господин lazy_troll имел ввиду конструкцию вида
Код:
int ** a;
a = new *int[N];
for(int i =0; i != N; ++i)
  a[i] = new int[M];
Записан

Странно всё это....
Вад
Модератор

ru
Offline Offline
Пол: Мужской

« Ответ #16 : 21-05-2010 21:19 » 

Я тут уже как-то предлагал в одной подобной теме в порядке обще-развивающего упражнения:
Код:
int ** a = new int*[N];
a[0] = new int[M*N];
for (int i = 1; i < N; ++i)
    a[i] = a[0] + M*i;

delete[] a[0];
delete[] a;
Но это так, хохмы ради.

Вад, В принципе, если выделяется память сразу, то есть большой процент вероятности, что все выделенные участки лягут рядом с друг другом. .
Finch, если память уже существенно фрагментирована, то не факт. Маленькие куски могут оказаться далеко друг от друга.
В случае произвольного доступа на большом массиве монолитность, конечно, не спасёт, но какой-то эффект тем не менее может дать (особенно если одна строка массива всё-таки меньше линии кэша)
« Последнее редактирование: 21-05-2010 21:25 от Вад » Записан
Rustam
Гость
« Ответ #17 : 22-05-2010 16:39 » 

А зачем тебе двухмерный массив?
В плане управления памятью и быстродействия - имхо, будет удобнее представить реализацию класса одномерным массивом с публичными методами set(x,y) и get(x,y)



У меня по заданию нужно определить является ли линия уникурсальной (что то типа графа Эйлера), по моему там без двумерного массива сложно будет обойтись
а вобще преподу не важна реализация, лишь бы классы были правильны
Записан
lazy_troll
Интересующийся

ru
Offline Offline

« Ответ #18 : 23-05-2010 07:08 » 

Rustam, лови тогда реализацию 2д массива + немного кода показывающего его использование:
Код:

#include <iostream>
using namespace std;

class array_2d {
const int sz;
int *pdata;
public:
explicit array_2d(int size): sz(size),
pdata(new int[size*size]) {};
~array_2d() {
delete[] pdata;
}
void set(int x,int y,int data) { pdata[x+sz*y]=data ; }
int get(int x,int y) { return pdata[x+sz*y] ; }
};

int main() {
array_2d a(10); // создает массив 10*10
int aa;
cin>>aa;
a.set(4,4,aa); //записывает в 4,4
cout << a.get(4,4) << endl; // prints !!!Hello World!!!
return 0;
}

Записан

Do not feed the troll
Rustam
Гость
« Ответ #19 : 23-05-2010 07:41 » 

lazy_troll, спасибо большое, выручил!!!
Записан
Алексей++
глобальный и пушистый
Глобальный модератор

ru
Offline Offline
Сообщений: 13


« Ответ #20 : 23-05-2010 08:43 » 

Цитата
explicit array_2d(int size): sz(size),
         pdata(new int[size*size])
жесткодром Улыбаюсь)
А инициализация - это уже совсем не модно Улыбаюсь
« Последнее редактирование: 23-05-2010 08:46 от Алексей1153++ » Записан

Алексей++
глобальный и пушистый
Глобальный модератор

ru
Offline Offline
Сообщений: 13


« Ответ #21 : 23-05-2010 08:48 » 

если извращаться, то уж по-научному
Код:
#include <vector>

class array_2d
{
std::vector<BYTE> m_A;
public:
array_2d(int size):
{
m_A.resize(size*size,0);
}

BYTE& AT(DWORD x,DWORD y)
{
DWORD dwd=x*y;
if(m_A.size()<dwd)throw 0;
return m_A[dwd];
}
};
« Последнее редактирование: 23-05-2010 09:13 от Алексей1153++ » Записан

Вад
Модератор

ru
Offline Offline
Пол: Мужской

« Ответ #22 : 23-05-2010 14:24 » 

Цитата
Код:
array_2d(int size):
{
m_A.resize(size*size,0);
}

- а почему тогда уж не
Код:
array_2d(int size)
: m_A(size*size, 0)
    {}
?

и, в довесок:
Код:
	BYTE& AT(DWORD x,DWORD y)
{
return m_A.at(x*y);
}
« Последнее редактирование: 23-05-2010 14:26 от Вад » Записан
Алексей++
глобальный и пушистый
Глобальный модератор

ru
Offline Offline
Сообщений: 13


« Ответ #23 : 23-05-2010 14:28 » 

двоеточие у меня - очепятка, не компилировал )

А разницу между at и [] не вижу. А есть, кстати ?
Записан

Вад
Модератор

ru
Offline Offline
Пол: Мужской

« Ответ #24 : 24-05-2010 07:53 » 

А разницу между at и [] не вижу. А есть, кстати ?
[] не выполняет проверку границ (только ассерты есть в отладочных реализациях), а at генерирует исключение out_of_range. То есть, делает то, что ты для [] написал руками Улыбаюсь

ЗЫ. В первом примере я акцентировал внимание на том, что вектор можно конструировать не по умолчанию, а специальным конструктором, с указанием размера и значения.
« Последнее редактирование: 24-05-2010 07:56 от Вад » Записан
Алексей++
глобальный и пушистый
Глобальный модератор

ru
Offline Offline
Сообщений: 13


« Ответ #25 : 24-05-2010 07:54 » 

понятно ))
Записан

Антон (LogRus)
Глобальный модератор

ru
Offline Offline
Пол: Мужской
Внимание! Люблю сахар в кубиках!


WWW
« Ответ #26 : 25-05-2010 02:50 » 

Алексей1153++, Вад, не понял чего вам не понравилось
ошибок нет
дурацкие  названия переменных это - да
некрасивое форматирование тоже - да
нет оператора присваивания и конструктора копирования - да
но в остальном, то всё работает
я бы конечно переделал бы это в шаблон, но так вполне ничего.
Записан

Странно всё это....
Алексей++
глобальный и пушистый
Глобальный модератор

ru
Offline Offline
Сообщений: 13


« Ответ #27 : 25-05-2010 03:01 » 

LogRus, ты "бы" переделал, а мы взяли и переделали Улыбаюсь  Что, съел?
Записан

Антон (LogRus)
Глобальный модератор

ru
Offline Offline
Пол: Мужской
Внимание! Люблю сахар в кубиках!


WWW
« Ответ #28 : 25-05-2010 03:08 » 

Алексей1153++, я бы переделал, на шаблон, не потому, что меня не устраивает динамический массив, а потому, что небольшие массивы эффективней создавать на стеке и шаблоны тут очень кстати.
я вообще вектор не люблю Улыбаюсь он мне тупо не нравится
Записан

Странно всё это....
Алексей++
глобальный и пушистый
Глобальный модератор

ru
Offline Offline
Сообщений: 13


« Ответ #29 : 25-05-2010 06:33 » 

а мне понравился тем, что удобно в качестве мемберов класса делать, когда динамические массивы нужны Улыбаюсь
Записан

Страниц: [1] 2  Все   Вверх
  Печать  
 

Powered by SMF 1.1.21 | SMF © 2015, Simple Machines