Отправляет email-рассылки с помощью сервиса Sendsay
  Все выпуски  

RusFAQ.ru: Программирование на C / C++


РАССЫЛКИ ПОРТАЛА RUSFAQ.RU

/ КОМПЬЮТЕРЫ И ПО / Языки программирования / C/C++

Выпуск № 674
от 21.02.2007, 11:05

Администратор:Калашников О.А.
В рассылке:Подписчиков: 463, Экспертов: 58
В номере:Вопросов: 2, Ответов: 7


Вопрос № 75887: Здравствуйте дорогие эксперты. Я хотел бы спросить как в языке С одномерный массив преобразовать в многомерный? Заранее спасибо за ответы....
Вопрос № 75945: Добрый день. У меня вопрос по поводу графов, точнее метода обхода графов. Есть функция inOrder которая получает в качества параметра указатель на структуру, в ней идет проверка на наличие в памяти передаваемого елемента, если он есть то опять выз...

Вопрос № 75.887
Здравствуйте дорогие эксперты. Я хотел бы спросить как в языке С одномерный массив преобразовать в многомерный? Заранее спасибо за ответы.
Отправлен: 15.02.2007, 17:08
Вопрос задал: GOrilla (статус: Посетитель)
Всего ответов: 5
Мини-форум вопроса >>> (сообщений: 9)

Отвечает: estiGi
Здравствуйте, GOrilla!
Изменить сам тип? Никак.
Одномерный массив выглядит, например как
int * pArray;
или
int arr [size];
Двумерный:
int ** ppArray;
или
int arr [size][size];

Вы не сможете изменить тип int* на int**.
Если же имеется в виду просто преобразование, то как обычно:

void func (int * pArr)
{
int ** ppArr;
ppArr = (int **)pArr;
или
ppArr = (int **)&pArr;
}

вы должны сами выбирать, в зависимости от того, что на самом деле находится в pArr. Но если он создавался как одномерный массив, то в результате
ppArr = (int **)pArr;
вы получите фиг знает что, а в результате
ppArr = (int **)&pArr;
вы получите адрес массива
переделать же его в двумерный просто так вот не получится
Ответ отправил: estiGi (статус: Студент)
Ответ отправлен: 15.02.2007, 17:31

Отвечает: PROD
Здравствуйте, GOrilla!
Не буду утверждать, но помоему никак.
создаете новый многомерный массив и переносите туда нужным образом данные.
Если массив изначально задан как одномерный под него и память будет выделена соответствующе.
в определенных случаях от переписывания массива вас могут спасти указатели. То есть ваш массив останется одномерным, но данные из него вы будете по другому.
например был int a[10]; а вы хотите чтоб стал int b[2][5]; (одну строку разрезать пополам)то наш псевдо массив b это указатель на a смещенный на j*5+i элементов.
Во всех других случаях переписывайте массив в другой
Ответ отправил: PROD (статус: 6-ой класс)
Ответ отправлен: 15.02.2007, 19:23

Отвечает: ramok
Здравствуйте, GOrilla!

данные в одномерном массиве и многомерном хранятся одинаково, тоесть последовательно в памяти.
все зависит от интерпритации одномерного массива.

самый простой и очевидный способ это просто скопировать содержимое одномерного массива в многомерный. в приложении пример 1
но в данном случае вы дублируете массив.

можно просто вспомнить что синтаксис доступа к многомерному массиву это всего лишь удобная запись, но никто не мешает воспользоватся и указателями.
тоесть A[i][j] в вашем случае аналог *(M + 5*i + j)
смотрите пример 2 в приложении.
недостаток метода - некрасивый синтаксис
преимущество - не происходит никакого копирования

Приложение:

Ответ отправил: ramok (статус: Практикант)
Ответ отправлен: 15.02.2007, 19:44
Оценка за ответ: 5
Комментарий оценки:
ramok, спасибо большое за исчерпывающий ответ. Ваш ответ оказался наиболее понятным для меня. Особенно мне понравилось то, что вы предложили несколько методов решения задачи. Еще не ожидал то, что ответ поступит настолько быстро. Спасибо.

Отвечает: Ross
Здравствуйте, GOrilla!

Для удобства и наглядности извлечения данных из одномерного массива можно использовать макрос(если массив часто используется и заранее известно его имя).
Допустим имеется массив matrix[16], который нужно интерпретировать как матрицу 4*4:

#define m(i,j) *(matrix + j*4+i) //либо matrix[i+j*4]

float matrix[16];

int main()
{
m(0,0) = 1;
m(0,1) = 2;
m(0,3) = m(0,0) + m(0,1);
}
Ответ отправил: Ross (статус: 5-ый класс)
Ответ отправлен: 16.02.2007, 00:04
Оценка за ответ: 4
Комментарий оценки:
Ross, спасибо за ответ. Я вполне понял вашу основную мысль. Спасибо за отличное от других решение проблемы.

Отвечает: kool
Здравствуйте, GOrilla!
Мона примерно так (см. приложение):

Приложение:

---------
I am.

Ответ отправил: kool (статус: 8-ой класс)
Ответ отправлен: 16.02.2007, 00:35
Оценка за ответ: 3
Комментарий оценки:
kool, спасибо за ответ. Вы дали оригинальный, но не совсем простой и понятный для меня ответ, хотя общую идею я понял. Кстати, впервые вижу, что массивы задаются так (через знак умножения).


Вопрос № 75.945
Добрый день. У меня вопрос по поводу графов, точнее метода обхода графов.
Есть функция inOrder которая получает в качества параметра указатель на структуру, в ней идет проверка на наличие в памяти передаваемого елемента, если он есть то опять вызывается inOrder.
То- есть, происходит проход по левой ветви дерева, и вот чего я не могу понять: ведь когда-то мы прийдем до конца ветвы, и она будет равна NULL, и операторы в теле if выполнятся не будут.
Но все работаем хорошо.
Обьясните пожалуйста почему?

Приложение:

Отправлен: 16.02.2007, 00:27
Вопрос задал: Platon (статус: Посетитель)
Всего ответов: 2
Мини-форум вопроса >>> (сообщений: 0)

Отвечает: ramok
Здравствуйте, Platon!

все верно. это называется рекурсивный обход дерева.

когда оператор if выполняется то функция опускается вниз по дереву вызывая снова и снова саму себя при этом не выходя.
как только дошли до конца ветки, то if перестает выполнятся и функции завершается.

в приложении по картинке http://alglib.sources.ru/articles/tree.gif (взятой отсюда http://alglib.sources.ru/articles/struct.php) объясняется шаг за шагом что выполняется..

PS
если еще не понятно то лучше всего это в дебагере пошагово выполнить

1

Приложение:

Ответ отправил: ramok (статус: Практикант)
Ответ отправлен: 16.02.2007, 01:47

Отвечает: Thread
Здравствуйте, Platon!
Я очень советую научиться пользоваться пошаговой отладкой. Тогда Вы бы собственными глазами увидели бы как все происходит. А происходит все следующим образом: здесь Вы имеете дело с ркурсией, т.е. пусть мы находимся на некотором шаге, когда у нас treeptr не NULL, значит проверяется treeptr!=NULL - это действительно так, теперь выполнется inOrder(treeptr->leftPtr); и не зависимо от результата выведется содержимое узла - printf("%3d", treeptr->data); и далее обход будет по правой ветви. Остановимся поподробнее на inOrder(treeptr->leftPtr); - здесь мы получаем, что узел нулевой и просто ничего не делаем. Да, действительно наступает момент когда операторы в теле условия не выполняются, но однако выполняются операторы в теле условия, из которого рекурсивно вызвалась функция - это printf("%3d", treeptr->data); inOrder(treeptr->rightPtr);
Ответ отправил: Thread (статус: 4-ый класс)
Ответ отправлен: 16.02.2007, 04:06


Отправить вопрос экспертам этой рассылки

Приложение (если необходимо):

* Код программы, выдержки из закона и т.п. дополнение к вопросу.
Эта информация будет отображена в аналогичном окне как есть.

Обратите внимание!
Вопрос будет отправлен всем экспертам данной рассылки!

Для того, чтобы отправить вопрос выбранным экспертам этой рассылки или
экспертам другой рассылки портала RusFAQ.ru, зайдите непосредственно на RusFAQ.ru.


Форма НЕ работает в почтовых программах The BAT! и MS Outlook (кроме версии 2003+)!
Чтобы отправить вопрос, откройте это письмо в браузере или зайдите на сайт RusFAQ.ru.


© 2001-2007, Портал RusFAQ.ru, Россия, Москва.
Идея, дизайн, программирование: Калашников О.А.
Email: adm@rusfaq.ru, Тел.: +7 (926) 535-23-31
ООО "Мастер-Эксперт Про", Москва, 2007
Авторские права | Реклама на портале
Версия системы: 4.45 beta от 20.02.2007
Яндекс Rambler's Top100

В избранное