Форум программистов
 

Восстановите пароль или Зарегистрируйтесь на форуме, о проблемах и с заказом рекламы пишите сюда - alarforum@yandex.ru, проверяйте папку спам!

Вернуться   Форум программистов > C/C++ программирование > Общие вопросы C/C++
Регистрация

Восстановить пароль
Повторная активизация e-mail

Купить рекламу на форуме - 42 тыс руб за месяц

Ответ
 
Опции темы Поиск в этой теме
Старый 07.05.2009, 03:31   #1
Парсифаль
Форумчанин
 
Аватар для Парсифаль
 
Регистрация: 28.04.2009
Сообщений: 186
По умолчанию Конкурс им. Парсифаля - н-мерные массивы.

Дорогие друзья, у меня, видимо, какое-то осложнение на н-мерные динамические массивы - наверное, потому что каждый день в них увязаю.
На дворе 3 часа ночи и мне все еще не дает покоя задача об объявлении н-мерного динамического массива (N*N*N*N*...*N - n раз - N-мерный куб со сторонами N).
Хочется услышать Ваши решения этой задачи. Естественно, n вводится пользователем и заранее неизвестно.
Итак, от Вас требуется создать массив необходимого размера и попробовать обращаться к нему как к н-мерному массиву! Тот, кто предложит самое красивое решение этой задачи, будет объявлен Рыцарем Агнца и, собственно, выиграет состязание. Завтра к полуночи я приведу собственное решение.
Ruft ihm es zu durch alle Land', Der durch dies Wunder Gnade fand!
Hoch uber aller Welt ist Gott, Und Sein Erbarmen ist kein Spott
Парсифаль вне форума Ответить с цитированием
Старый 07.05.2009, 14:12   #2
Парсифаль
Форумчанин
 
Аватар для Парсифаль
 
Регистрация: 28.04.2009
Сообщений: 186
По умолчанию

Ни у кого даже предположений нет?(
Ruft ihm es zu durch alle Land', Der durch dies Wunder Gnade fand!
Hoch uber aller Welt ist Gott, Und Sein Erbarmen ist kein Spott
Парсифаль вне форума Ответить с цитированием
Старый 07.05.2009, 14:24   #3
Sazary
В тени
Старожил
 
Аватар для Sazary
 
Регистрация: 19.12.2008
Сообщений: 5,788
По умолчанию

Я вот что не могу понять.
Предположим, мы сделали это. Есть некая функция, которая по заданному N создает N-мерный массив.

Как вы будете обращаться к его элементам? Ведь для этого нужно знать его размерность.

Ведь массив нужно объявить. А для этого нужно знать размерность.
Нельзя же написать как-то так:
Код:
int **.....***mas;
или
Код:
cin>>N;
int *{N звездочек}mas;


Цитата:
Завтра к полуночи я приведу собственное решение.
Будет интересно посмотреть )
Вполне очевидно, чтобы что-то понять, необходимо книги читать.
Не нужно плодить бессмысленных тем. Вас Поиск избавит от многих проблем.

___________________________________ ___________________________________ _______
[=Правила форума=]_____[Поиск]_____[Литература по С++]____[Литература. Паскаль]
Sazary вне форума Ответить с цитированием
Старый 07.05.2009, 15:05   #4
Sazary
В тени
Старожил
 
Аватар для Sazary
 
Регистрация: 19.12.2008
Сообщений: 5,788
По умолчанию

Вот. Сочинил кое-что. Это на уровне идеи (но приведенный код работает).
Правда, почему-то некорректно выводится последний элемент, если вводить размерность 1 или 2.
Код:
#include <iostream>
#include <conio.h>
#include <cstdlib>
using namespace std;

const int M=2;

int main()
{

int *mas;    // это наш массив
int N,index[50],i,j,k;  
cout<<"Vvedite razmernost massiva: ";
cin>>N;   // вводим размерность
mas = new int[N*M+1];   // выделяем память
for(i=0;i<N;i++)       // зануляем индексы
 index[i] = 0;

for(i=0;i<N*M;i++)    // теперь вводим элементы
 {
  cout<<"Enter element mas";
  for(j=0;j<N;j++)        // выводим строку вида "mas[0][0][0][0] = "
   cout<<"["<<index[j]<<"]";
 index[N-1]++;    // увеличиваем индекс
 for(k=N-1; k>=0; k--)    // и меняем остальные индексы, если нужно
  if(index[k]==M)
   {
    index[k]=0;
    index[k-1]++;
   }
   cout<<":  ";
  cin>>mas[i];   // вводим элемент
 }
//------------
// вывод
//------------
cout<<"-=-----------"<<endl;
for(i=0;i<N;i++)  // снова зануляем индексы
 index[i] = 0;
for(i=0; i<M*N; i++)
 {
  cout<<"Element mas";
  for(j=0; j<N; j++)
   cout<<"["<<index[j]<<"]";
  cout<<" = "<<mas[i];
  index[N-1]++;
  for(k=N-1; k>=0; k--)
   if(index[k]==M)
    {
     index[k]=0;
     index[k-1]++;
    }
 cout<<endl;
 }
delete[] mas;
getch();
return 0;
}
Вполне очевидно, чтобы что-то понять, необходимо книги читать.
Не нужно плодить бессмысленных тем. Вас Поиск избавит от многих проблем.

___________________________________ ___________________________________ _______
[=Правила форума=]_____[Поиск]_____[Литература по С++]____[Литература. Паскаль]

Последний раз редактировалось Sazary; 07.05.2009 в 16:54.
Sazary вне форума Ответить с цитированием
Старый 07.05.2009, 16:41   #5
|{ot
Форумчанин
 
Аватар для |{ot
 
Регистрация: 09.03.2008
Сообщений: 127
По умолчанию

У меня тут тоже только идея, но я не проверял, может что то где то провтыкал:
Код:
#include <iostream.h>
#include <stdlib.h>
#include <string.h>

int sqrn(int idx){//возвращает idxв степени idx
	int rez=1;
	for(int i=0;i<idx;++i) rez*=idx;
return rez;
}

int g(int k){// возвращает количество цифр в числе k
	char *s;
	itoa(k,s,10);
	return strlen(s);
}

class mass{
	unsigned n;
	int* mas;

public:
	int* operator[](char* );
	mass(unsigned zn_n=1):n(zn_n){
		mas=(int*)malloc(sizeof(int)*sqrn(n));//выделение памяти под n-мерное пространство
	}

};

int* mass::operator[] (char*p){//в качестве параметра строка в которой индексы элемента через запятую
	unsigned len=strlen(p);
	char*s_t=new char[g(n)];//вспомагательная строка для выделения чисел из р
	int k=0,inte,addr=0,j=0;//addr - смещение от указателя на массив 
                                       //j - Ктекущее количество символов в s_t
                                        //inte - преобразованое число из строки s_t
                                        //k - это порядковый номер индекса
	s_t="";
	for (int i=0;i<len;++i){
		if(p[i]!=','){
			s_t[j++]=p[i];//отделяем число
			continue;
		}
		inte=atoi(s_t);
		addr+=k*inte;
		++k;
		s_t="";
		j=0;
	}
return mas+addr*sizeof(int);
}
void main(){

mass A(3);//создание 3-х мерной матрици
*A["1,2,3"]=7;//обращение к элементу

}
Если я не ошибаюсь, то компилятор и сам что то такое делает. Если:
int **mas=new int*[n];
for(int i=0;i<n;++i) mas[i]=new int[n];

то при обращении допустим к mas[3][2] запись преобразуется к *((mas+3*sizeof(int))+2*sizeof(int) ) отличее только в том, что
здесть даные в памяти располагаются каждый массив отдельно((mas+3*sizeof(int)) - адрес 4-ого масива *((mas+3*sizeof(int))+2*sizeof(int) ) -адрес 3-его элемента в 4-ом массиве ), а в классе (см. выше) все в один ряд

Последний раз редактировалось |{ot; 07.05.2009 в 17:28.
|{ot вне форума Ответить с цитированием
Старый 07.05.2009, 16:46   #6
Парсифаль
Форумчанин
 
Аватар для Парсифаль
 
Регистрация: 28.04.2009
Сообщений: 186
По умолчанию

Цитата:
Как вы будете обращаться к его элементам? Ведь для этого нужно знать его размерность.
В этом и есть загвоздка. Основная креативная задача))

Друзья, а можно давать комментарии к коду? А то разбираться в нем - занимает немалое время для непрофи.
Ruft ihm es zu durch alle Land', Der durch dies Wunder Gnade fand!
Hoch uber aller Welt ist Gott, Und Sein Erbarmen ist kein Spott
Парсифаль вне форума Ответить с цитированием
Старый 07.05.2009, 17:06   #7
|{ot
Форумчанин
 
Аватар для |{ot
 
Регистрация: 09.03.2008
Сообщений: 127
По умолчанию

Цитата:
Сообщение от Sazary Посмотреть сообщение
Как вы будете обращаться к его элементам? Ведь для этого нужно знать его размерность.
так размерность же известна n-мерное пространство
(может я что то не так понимаю??)

мне кажется, что обращатся к элементу через строку это само оптимально...
|{ot вне форума Ответить с цитированием
Старый 07.05.2009, 17:15   #8
Pashan
Пользователь
 
Регистрация: 18.03.2009
Сообщений: 89
По умолчанию

Цитата:
так размерность же известна n-мерное пространство
Кому известна? По условию она известна пользователю, а не программисту. Тогда строка A["1,2,3"] теряет всякий смысл.

На самом деле, по-моему, задача не имеет смысла. N-мерный массив должен использоваться под конкретные цели. Абстрактно можно придумать только что-то вроде того, что написал |{ot, но использовать не забитую в программу индексацию, а динамическую, создаваемую по ходу исполнения. В общем, там что-то гениальное вряд ли получится. По-любому, если размерность вводится извне, то и индексация берется оттуда же. Будет просто куча массивов, которые передаются туда-сюда.

|{ot,
Я тоже начал придумывать нечто подобное, только вместо строк можно еще использовать специальную структуру для индексации, у которой будет конструктор с переменным количеством аргументов. Типа такого:

Код:
struct ArrIndex
{
  ArrIndex(...)
  {
  }
};

class CNArray
{
  TYPE operator [] (ArrIndex index)
  {
    ...
  }
}
Но там тоже все не очень красиво. А главное, все это не решает основную проблему

Последний раз редактировалось Pashan; 07.05.2009 в 17:32.
Pashan вне форума Ответить с цитированием
Старый 07.05.2009, 17:47   #9
Sazary
В тени
Старожил
 
Аватар для Sazary
 
Регистрация: 19.12.2008
Сообщений: 5,788
По умолчанию

А я вот что еще накатал. По-моему, неплохо вышло )
Код:
#include <iostream>
#include <stdlib.h>
#include <conio.h>
#include <stdarg.h>
using namespace std;

class nmas
{
 private:
  int *mas;
  int N;
  int *raz;
  int count;
  
 public:
 nmas(int,...);
 ~nmas();
 int& operator[](int,...);

};

nmas::nmas(int x,...)  // конструктор
{
 va_list LS;    // лист аргументов
 va_start(LS,x);  // ставим указатель на начало
 int k;
 count=1;   // количество аргументов
 if(x==-1) return;  // если аргумент =-1, выходим
 N = x;   // размер массива = первый аргумент
 while(k = va_arg(LS,int)!=-1)  // пока не встретим -1
  {
   N *= k;   // умножаем размер массива на аргумент.
   count++;  // увеличиваем размерность
  }
 va_end(LS);  
 mas = new int[N];  // выделяем память под массив
 raz = new int[count];  // выделяем память под индексы
 va_start(LS,x);  // ставим указатель на начало
 raz[0] = x;   // первый индекс равен первому аргументу
 int i=1;   
 while(k = va_arg(LS,int)!=-1)
   raz[i++] = k;  // загоняем в массив остальные аргументы
 va_end(LS);
}
//-----
nmas::~nmas()   // деструктор
{
 delete[] mas;   // освобождаем память под массив
 delete[] raz;   // и под индексы
 N=0; 
}
//------
int& nmas::operator[](int x,...)  // получаем доступ к элементу
{
 va_list LS;
 va_start(LS,x);

 int i,k,M=0;  // M - реальный индекс элемента.
 M = x;
 for(i=1;i<count; i++)
  {
   k = va_arg(LS,int);
   M += k*raz[i];
  }
 return mas[M];
}
//--------

int main(){

nmas A(3,3,3,-1);

A[1,2,3] = 7;
cout<<A[1,2,3];


getch();
return 0;
}
--------------
Как пользоваться:
Объявляем массив. Например, 3-мерный массив, размерности 1x2x3.
Объявляется так:
Код:
nmas A(1,2,3,-1);
В конце обязательно -1.
Ну а обращение, как в Делфи или паскале - A[0,1,1];

=================================== ===========
Цитата:
Сообщение от Pashan
На самом деле, по-моему, задача не имеет смысла.
Практического применения я тоже не вижу. Но просто подумать над идеей интересно )
Вполне очевидно, чтобы что-то понять, необходимо книги читать.
Не нужно плодить бессмысленных тем. Вас Поиск избавит от многих проблем.

___________________________________ ___________________________________ _______
[=Правила форума=]_____[Поиск]_____[Литература по С++]____[Литература. Паскаль]
Sazary вне форума Ответить с цитированием
Старый 07.05.2009, 17:59   #10
Pashan
Пользователь
 
Регистрация: 18.03.2009
Сообщений: 89
По умолчанию

Sazary, а что за компилятор? У меня VS 2005 и она выдает, что оператор [] не может иметь переменное количество аргументов.
Pashan вне форума Ответить с цитированием
Ответ


Купить рекламу на форуме - 42 тыс руб за месяц



Похожие темы
Тема Автор Раздел Ответов Последнее сообщение
2-х мерные массивы (С++) TheWanderer Помощь студентам 5 05.12.2008 14:35
Помогите кто может (Массивы 2-х мерные) raccooni Общие вопросы C/C++ 15 25.11.2008 23:55
помогите в QBasic'е 2-мерные массивы Sergmodern Помощь студентам 1 05.06.2007 08:39
конкурс программистов ! (первый конкурс) Alar Свободное общение 129 18.03.2007 00:50