Старый 29.12.2013, 20:08   #1
<Gh0St>
 
Аватар для <Gh0St>
 
Регистрация: 22.03.2012
Сообщений: 75
Репутация: 19
Question Получить размер матрицы по указателю (Си)

Всем привет!
Возможно вопрос покажется тривиальным, но что-то решения не нашёл.
Допустим, имеется матрица:
Код:
int x[4][4] = { 1, 2, 3, 4,
		5, 6, 7, 8,
		8, 7, 6, 5,
		4, 3, 2, 1 };
Нужно передать её в функцию (через указатель):
Код:
int f(int *p);
В функции нужно вычислить размер матрицы. В данном случае 4х4.

Подскажите, как это сделать?
Благодарю.
__________________
- Про опыт говорят: "Мы так свои ошибки называем"
<Gh0St> вне форума   Ответить с цитированием
Старый 30.12.2013, 08:33   #2
lefty
 
Аватар для lefty
 
Регистрация: 01.09.2011
Сообщений: 50
Репутация: 13
По умолчанию

имхо тут нужно делать структуру - сама матрица + дополнительные поля где будешь хранить ее размерность. ну и считывать размерность оттуда уже.
ну и передавать в функцию указатель на структуру
lefty вне форума   Ответить с цитированием
Старый 30.12.2013, 15:20   #3
<Gh0St>
 
Аватар для <Gh0St>
 
Регистрация: 22.03.2012
Сообщений: 75
Репутация: 19
По умолчанию

была такая мысль.
ещё на ЛОРе вот такой пример:
Код:
include <iostream>
using std::cout;
using std::endl;

template <size_t Len>
void print(int (&arr)[Len])
{
    for (size_t i = 0; i < Len; ++i)
        cout << " "[!i] << arr[i];
    cout << endl;
}

int main()
{
    int arr[] = {1, 2, 5, 4, 3};
    print(arr);
    return 0;
}
__________________
- Про опыт говорят: "Мы так свои ошибки называем"
<Gh0St> вне форума   Ответить с цитированием
Старый 30.12.2013, 17:49   #4
Beched
 
Регистрация: 06.07.2010
Сообщений: 395
Репутация: 118
По умолчанию

А sizeof не годится в силу необходимости извлечь корень?
Beched вне форума   Ответить с цитированием
Старый 30.12.2013, 20:39   #5
<Gh0St>
 
Аватар для <Gh0St>
 
Регистрация: 22.03.2012
Сообщений: 75
Репутация: 19
По умолчанию

Такая мысль тоже была, но:
1) если передавать матрицу в функцию через указатель, то с sizeof не всё так гладко.
2) если матрица квадратная, например 4х4, проблем не будет. Получаем размер массива (16), извлекаем корень (4), получаем матрицу 4х4, всё ок. Но если матрица не квадратная? Например, 4х3. Размер массива будет 12. Корень из 12-и не извлекается, там будет 3,46, и дробная часть от бросится. В итоге получим матрицу 3х3, что неверно.

Способ с ЛОРа не плох, но не спешу им воспользоваться. Идея со структурой мне больше понравилась.
Описал такую структуру (просьба не придираться к русским комментариям):
Код:
#define matrixType int
#define pMatrixType matrixType **

struct MATRIX {
	// конструктор по умолчанию
	MATRIX(const unsigned short m_, const unsigned short n_) : M(m_), N(n_) { }

	// матрица
	pMatrixType w;

	// размер матрицы (MxN)
	const unsigned short M;
	const unsigned short N;
};
Метод создания матрицы. Принимает размер матрицы, возвращает указатель на созданную матрицу
Код:
MATRIX *makeMatrix(unsigned short m, unsigned short n) {
        // минимальный размер матрицы 1х1
	if(m <= 0) {
		m = 1;
	}
	if(n <= 0) {
		n = 1;
	}

	MATRIX *matrix = new MATRIX(m, n);

        // собственно, создание матрицы
	matrix->w = new(matrixType * [matrix->M]);
	for(int i = 0; i < matrix->M; i++) {
		matrix->w[i] = new(matrixType[matrix->N]);
	}

	if(!matrix->w) {
		delete matrix;
		return nullptr;
	}

         // заполнение матрицы нулями
	for(int i = 0; i < matrix->M; i++) {
		for(int j = 0; j < matrix->N; j++) {
			matrix->w[i][j] = 0;
		}
	}

        // список хранит указатели матриц в динамической памяти
        // определён, как std::list<struct MATRIX *> m_matrixList;
	m_matrixList.push_back(matrix);

	return matrix;
}
Список m_matrixList лишь содержит указатели на объекты структуры в динамической памяти. Освобождение памяти происходит в методе clear():
Код:
void clear() {
	for(auto it = begin(m_matrixList); it != end(m_matrixList); ++it) {
                // удаление матрицы
		for(int i = 0; i < (*it)->M; i++) {
			delete (*it)->w[i];
		}

		delete [](*it)->w;

                // удаление объекта структуры
		delete *(it);
	}

        // ну и напоследок, очистка списка
	m_matrixList.clear();
}
Интересует Ваше мнение по поводу этого кода, а так же возможные рекомендации по улучшению кода.
Благодарю.
__________________
- Про опыт говорят: "Мы так свои ошибки называем"
<Gh0St> вне форума   Ответить с цитированием
Старый 31.12.2013, 15:31   #6
Enigma
 
Аватар для Enigma
 
Регистрация: 17.06.2013
Сообщений: 37
Репутация: 12
По умолчанию

Это ведь не C получается, а C++. А раз так не возможно ли воспользоваться средствами стандартной библиотеки?

http://stackoverflow.com/questions/10274162/how-to-find-2d-array-size-in-c/10274186#10274186
Цитата:
Use an std::vector.

std::vector< std::vector<int> > my_array; /* 2D Array */

my_array.size(); /* size of y */
my_array[0].size(); /* size of x */

Or, if you can only use a good ol' array, you can use sizeof.

sizeof( my_array ); /* y size */
sizeof( my_array[0] ); /* x size */
Это первое что пришло мне в голову когда я увидел что речь идёт о C++. Сам я его знаю очень поверхностно, но так понимаю что передавать указатель на std::vector< std::vector<int> > в функцию и получать размер будет можно.
Enigma вне форума   Ответить с цитированием
Старый 01.01.2014, 00:47   #7
lefty
 
Аватар для lefty
 
Регистрация: 01.09.2011
Сообщений: 50
Репутация: 13
По умолчанию

с++, классы, методы, объекты - тьфу, гадость какая.
даешь мануальную работу с памятью ! только адреса,оффсеты,нетипизиров анные указатели, только хардкор !

Последний раз редактировалось lefty; 01.01.2014 в 00:49..
lefty вне форума   Ответить с цитированием
Старый 01.01.2014, 04:09   #8
<Gh0St>
 
Аватар для <Gh0St>
 
Регистрация: 22.03.2012
Сообщений: 75
Репутация: 19
По умолчанию

Цитата:
Сообщение от lefty Посмотреть сообщение
с++, классы, методы, объекты - тьфу, гадость какая.
даешь мануальную работу с памятью ! только адреса,оффсеты,нетипизиров анные указатели, только хардкор !
ха-ха, от души) +
кстати, с Новым годом всех!
__________________
- Про опыт говорят: "Мы так свои ошибки называем"
<Gh0St> вне форума   Ответить с цитированием
Старый 22.02.2014, 02:11   #9
JKornev
 
Регистрация: 03.11.2013
Сообщений: 10
Репутация: 0
По умолчанию

Цитата:
с++, классы, методы, объекты - тьфу, гадость какая.
даешь мануальную работу с памятью ! только адреса,оффсеты,нетипизиров анные указатели, только хардкор !
и на долго ли тебя хватит

Что касаемо топика, размер двумерного массива заданного таким образом, чисто абстрактное значение известное только компилятору, так что передав матрицу в функцию по указателю эта абстракция потеряется и размер уже не высчитать. Если размер захардкоден, то можно сделать так:
Цитата:
#define MATRIX_X(matr) (sizeof(*matr) / sizeof(**matr))
#define MATRIX_Y(matr) (sizeof(matr) / sizeof(*matr))
int test[4][5];

printf("x:%d y:%d", MATRIX_X(test), MATRIX_Y(test));
хотя лучше конечно просто задавать размер обьявляя константу и не выдумывать каких-то свистоплясок
JKornev вне форума   Ответить с цитированием
Старый 22.02.2014, 08:52   #10
HeartLESS
 
Регистрация: 25.04.2012
Сообщений: 101
Репутация: 31
По умолчанию

Может тебе проще будет динамический список создать?
struct Node{
int value;
Node prev;
Node next;
}
будет header и дальше next - его чайлды. идем по чайлдам, пока next не null. Синтаксис C я уже не помню, прости.
Чтобы не держать размерность нигде, можно сделать лист двумерным (добавится вертикальная структура). Их вроде на 1м курсе все писали. В итоге будет точное обращение память в память, как ты хотел.
HeartLESS вне форума   Ответить с цитированием
Ответ

Опции темы Поиск в этой теме
Поиск в этой теме:

Расширенный поиск
Опции просмотра

Ваши права в разделе
Вы не можете создавать новые темы
Вы не можете отвечать в темах
Вы не можете прикреплять вложения
Вы не можете редактировать свои сообщения

BB коды Вкл.
Смайлы Вкл.
[IMG] код Вкл.
HTML код Выкл.

Быстрый переход



Powered by vBulletin® Version 3.8.5
Copyright ©2000 - 2018, Jelsoft Enterprises Ltd. Перевод: zCarot