| Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате |
| Форум программистов > C/C++: Для новичков > Сдвиг двумерного массива. |
| Автор: Santa12 4.6.2009, 13:09 | ||
| Заранее прошу прощения, если нужно было не сюда, а в центр помощи, и если невнятно опишу проблему - учу язык всего месяц, да еще и самоучкой... Задачи ищу на просторах инета, и нашел вот такую: Пользователь вводит матрицу размерностью N*M. Выведете на экран матрицу N*M, элементы которой сдвинуты на один элемент влево относительно исходной матрицы.т.е. первый элемент матрицы будет равен второму элементу исходной матрицы, а последний равен первому. Проблема в сдвиге... С массивом 2*2 проходит вроде как без проблем, а вот с другими...
Были мысли запихнуть в одноменрый массив, сдвинуть, а потом обратно в двумерный, но, это ж, я так понимаю, не верно? Заранее спасибо за любую помощь ) |
| Автор: gosn1ck 4.6.2009, 13:30 | ||
и что же вы все пробелы то не любите.... ?
|
| Автор: Santa12 4.6.2009, 13:54 |
| Пробелы я люблю... Только здесь нагляднее было в строку, ну да ерунда это... Да, ваш код работает. Спасибо. Вот только... Делал я так... и на моем коде, если брать массив 4*4, то 4,8 и 12 значения получаются... эм... не знаю, как это правильно сказать... вобщем длинным отрицательным числом (поэтому я и вставлял проверку на равность j)... Потому и обратился за помощью - сам ен могу найти где именно я накосячил ( Если я правильно понимаю, то в какой-то момент j+1 становится равным 4, а такого значения ведь нет... |
| Автор: fry 4.6.2009, 14:11 | ||
Советую поднабраться знаний в сторону отладчиков. Этот вопрос думаю легко бы решился (см. пошаговая отладка). |
| Автор: Santa12 4.6.2009, 14:22 |
Именно поэтому, я и говорю, что ставил проверку на j... Пошагово прошел по всему что можно... Но моих познаний не хватило. в моем случае, при массиве 4*4 в случае: mass[0][3] = mass[0][3+1] -- у меня в этом месте mass[0][3+1] равняется -33686019 а если напрямую копирую код gosn1ck - в этом месте появляется 5, т.е. значение, которое должно быть в mass[1][0] |
| Автор: fry 4.6.2009, 14:38 | ||
Ты сам ответил на свой вопрос.........
Поясняю, в C индексы массивов начинаются с 0, т.е. [0], [1], [2], [3] уже 4 элемента. У тебя: mass[0] [3+1] <---- Добавлено через 1 минуту Если поподробнее, то ты обращаешься к элементу за массивом, который естессно не инициализирован никаким значением. |
| Автор: fry 4.6.2009, 14:54 |
| Ты меняешь каждый элемент i,n на m,0. Ты этого хотел? Сомниваюсь. n,m - размерность массива ЗЫ Если в голове не можешь проработать задачу делай рисунки - на порядок проще думать. ЗЫ Приводи кусок своего кода в постах, ч-то искать по листингу влом, думаю не только мне. Т.к. двигаешь влево надо скопировать первый элемент заранее. А то он затирается при первой же итерации. В конце копируешь это значение в конец. |
| Автор: Santa12 4.6.2009, 15:13 | ||||
Ок. Значит, попробую еще раз... я создаю динамически массив N*M. Передаю его в функцию, которая его сдвигает на одно значение. Первый элемент я сперва копирую в темп, в конце копирую его в последний элемент массива.
А если я просто беру код gosn1ck
Рисовать - рисую, но в данном случае - не помогло... |
| Автор: fry 4.6.2009, 15:27 | ||||||
Проверка как раз и сделана для того, чтобы этого не случилось, т.е. при j=3 она срабатывает и выполняется то, что я описал в предыдущем посте.
будет возвращать один и тотже элемент, а тебе, по моему, надо всего лишь
Только надо проверять чтобы [i+1] не было за пределами массива (последняя итерация). Кстати, гораздо легче будет если ты будешь создавать массив одномерный. его и сдвигать проще и быстрее работать будет. Конкретный элемент в нем можно искать так: i+j*n. Работать будет быстрее, чем у gosn1ck . |
| Автор: Santa12 4.6.2009, 15:37 | ||||||
ну, для этого я ее и сделал ;) При этом, в коде gosn1ck все отрабатывает без такой проверки. Почему?
вот примерно об этом я изначально и спрашивал... на последней итерации в этом случае вылетает, все правильно, не могу сообразить, как обработать правильно... сообразил. Изначально в этом и была моя ошибка - стормозил, и начал городить огород...
Я хочу с многомерными массивами разобтаться, не переводя их в одномерные ))) С одномерными, вроде бы уже вопросов и не возникает ))) Что ж, всем спасибо ;) Вопрос решен. |
| Автор: fry 4.6.2009, 15:44 | ||||||||||
Т.е. "не наигралсо". В том варианте, который я описал, не надо ничего переводить, он (2мерный) будет храниться в памяти как 1мерный и усе.
Потому, что у него ошибка: На последней итерации
Вообще лучше не решать задачу разными способами, при том что они заведомо хуже первого, а заняться другой. Еще лучьше поставить более менее реальную задачу и ее решить, а не двигать элементы матрицы в двойном цикле. |
| Автор: mes 4.6.2009, 15:52 | ||
Santa12, в статических многомерных массивах элементы располагаются линейно. Т.е весь массив в памяти занимает непрерывный кусок памяти и за последним элементом одной строки идет первый элемент следующей. Динамические многомерные массивы представлены многоуровнево, т.е 2х мерный массив является массивом указателей на одномерные массивы, которые могут лежать в произвольных местах памяти. Именно из этого расхождения представления и получается различное поведение. |
| Автор: fry 4.6.2009, 15:59 | ||
Я и говорил ему о динамическом варианте с линейным расположением элементов. Однако, о каком представлении идет речь если проги работают именно с 2мерным динамическим? ЗЫ И то неправильно. |
| Автор: mes 4.6.2009, 16:22 | ||
нет, не обе. У gosn1ck используется статический 2х мерный |
| Автор: Santa12 4.6.2009, 17:04 | ||
| О! Не знал что динамический и статический хранятся в памяти по разному! Спасибо! Буду знать. Видимо, или не попалось мне это в книгах/статьях, или не придал этому значения. Потому и не акцентировал внимание, что в приведенном примере был статический массив. есть такое ;) Есть такая. Но она мне пока не по плечу ) сделал лишь половину, и решил сперва сначала с базовыми вещами разобраться... Вот, разбираюсь... Еще бы со списками понять работу )
Заучил. Теперь не забуду. |
| Автор: fry 4.6.2009, 17:06 |
| mes, незаметил объявление, смотрел на работу (2 цикла по индексам) с массивом. Извини за поклеп. ЗЫ Нах автор второго варианта делал с 2 циклами если лучше с одним?! (только, чтобы показать "как правильно", но это ему тоже до конца не удалось) Все еще думаю что в этом случае(в случае автора темы) лучше динамика с линейным расположением элементов т.к. проще и быстрее. Добавлено через 4 минуты и 28 секунд Santa12, имей ввиду, что хранение динамического массива частями (2мерного) далеко не является рациональным решением т.к. заведомо менее производительно и несколько менее, но все же расточительнее. |
| Автор: Santa12 4.6.2009, 17:32 | ||
Учту. Но, я правильно понимаю, что к статическому это замечание не относится? Жаль, никому не могу поставить плюсы. Исправлюсь, как только наберу сотню постов ;) |
| Автор: azesmcar 4.6.2009, 17:34 | ||
поставил. |
| Автор: Santa12 4.6.2009, 17:54 |
Благодарю. |
| Автор: mes 4.6.2009, 18:01 | ||||
только при запоминании, делайте акцент не на статичность, и динамичность, а на способ выделения памяти под массив. потому как в этом примере динамический массив (хотя динамично только одно его направление) будет располагаться в памяти линейно :
это высказывание требует слишком много оговорок, и в принципе справедливо лишь к "излишнe" занимаемой памяти. |
| Автор: fry 4.6.2009, 18:01 | ||
| Santa12, если массив не динамический (статический), то он просто выделяется в стеке в виде линейно упорядоченных элементов,т.е. то, что я описал, только в стеке. Если выделять динамически (предложенный мной вариант), то есть два варианта: 1. выделить также линейно 2. выделить сначала массив указателей, а затем каждый элемент этого массива проинициализировать своей частью памяти. В первом варианте все элементы располагаются рядом. К ним обращение будет происходить без лишних операций со стороны операционной сис-мы(ОС). Во втором возможно падение производительности т.к. ОС не гарантирует что выделенная память будет располагаться за памятью выделенной ранее, что потребует некоторых манипульций со стороны ОС в случае обращения к элементам. К тому же код твоей программы во втором варианте будит несколько днлинее, чем во втором (сложнее будет код выделения массива, высвобождения массиваб работы с массивом).
посмотри на код в постах выше и прикинь код в случае линейного расположения элементов. Вложенности циклов не будет. Проявятся возможности ОС по части кэширования. Проще код, меньше жрет памяти, думаю, что прога возможно будет по размеру меньше (критично в некоторых местах(контроллеры и т.п.)). ЗЫ ты в своем посте проверку на невозможность выделения забыл. |
| Автор: mes 4.6.2009, 18:09 |
если это высказывание относится только применительно к конкретному коду, то спорить не буду (см. код лень). Однако для общего случая высказывание не корректно. |
| Автор: fry 4.6.2009, 18:10 | ||
По какой из частей моего суждения некорректно? |
| Автор: mes 4.6.2009, 18:11 | ||
В том что линейное раположение строк эффективнее в производительности при работе с матрицей, чем не линейное. Речь идет об одном и том же решении примененного к статическому и динамическому массиву. Если решение конкретной задачи приведено к линейному виду, то естественно у него будет преимущество. это обсуждалось в частности здесь : http://forum.vingrad.ru/forum/topic-249780/unread-1/hl/%25D0%25BC%25D0%25B0%25D1%2582%25D1%2580%25D0%25B8%25D1%2586%25D0%25B0/index.html#st_0_view_0 |
| Автор: Santa12 4.6.2009, 18:18 | ||
Так... я создаю динамический массив вот таким образом:
mes, т .е. в отличие от приведенного вами варианта, он будет располагаться в памяти не линейно? Я правильно понимаю? fry, а можно немножко пояснить: КАК задать массив линейно? И как выглядит код первого, а как второго вариантов? Приношу свои извинения за назойливость, просто я пока все не "разжую" мне сложно понять что имеется в виду... Если вместо ответа будут ссылки на статьи/книги - тоже буду рад ) |
| Автор: mes 4.6.2009, 18:20 | ||
правильно, так как выделяете память кусками. хотя это относится к целевому массиву. А вот вспомогательные массивы (строки и массив указателей на строки) располагается линейно. |
| Автор: fry 4.6.2009, 18:22 | ||||||
| Там нет технологии тестирования, это раз, в данном случае не надо будет вычислять смещение по двум индексам это два. По части всего остального остаюсь при своем. Кстати
Данная строчка будет не так красиво смотреться при добавнеии обработки исключений. Хотя конечно строчка красивая. mes, при всем уважении
Это не совсем правильно |
| Автор: mes 4.6.2009, 18:22 |
Согласен, но, думаю, так тс легче будет понять когда массив линейный, а когда нет. |
| Автор: fry 4.6.2009, 18:27 | ||||
|
| Автор: mes 4.6.2009, 18:32 | ||
При чем тут исключения по отношению к подобной записи ? В том примере использовался динамический массив строк постоянной длины. И ничего особенного от обычного синтаксиса массивов не имеет. Добавлено @ 18:34 т.е Вы утверждаете что что new int[n][20]; вернет массив, элементы которого расположены не линейно ?! |
| Автор: fry 4.6.2009, 18:35 |
| Ну может именно с исключениями я конечно перебарщил, но проверку на корректное выделение памяти для каждой части массива провести необходимо. Или я чего не понял, тогда поясни. Мне как-то приплюснутый вариант выделения через stl более по душе. Добавлено @ 18:39 Все допер.. Сорри. Добавлено @ 18:41 В твоем случае и в моем я ч-то не заметил разницы в смысле, а в синтаксисе огромная. Поясни почему сделал так. Если не сложно. |
| Автор: Santa12 4.6.2009, 18:47 |
| Еще раз спасибо ) |
| Автор: mes 4.6.2009, 18:49 | ||
Для того чтоб показать, что если в массиве только одно измерение динамическое, то можно для него выделить общий кусок памяти и соответственно элементы будут располагаться линейно. |
| Автор: fry 4.6.2009, 18:53 |
| В целом, лично для меня, данный синтаксис имеет преимущество в виде возможности писать " [ i ][ j ] " И недостатки: синтаксис ( ИМХО ИМХО ИМХО ИМХО ИМХО ИМХО ), статика одного измерения. Кстати подозреваю, что вычисление смещения по индексам будет темже (подозреваю). Рад за mes, что повесилил. |
| Автор: mes 4.6.2009, 18:57 | ||||||
Это следствие, так как наш массив объявлен многомерным
Если быть точнее, то преимущество в том, что одно (но только одно) из измерений является динамическим. Добавлено через 7 минут и 39 секунд
Хотя длина строки и константна, но оптимизация умножения может быть возможно, только в случае констаного индекса строки. Т.е. обращение mas[n][m] требует одинаковых вычислений, mas[5][m] может быть лишен умножения, а mas[5][2] - заменен на линейный индекс. |
| Автор: fry 4.6.2009, 19:10 |
| Думаю ответ на вопрос какой вариант пользовать знает тот, кто знает что ему надо (и к чему он привык): "[ ][ ]" или менее напрягающий код объявления (это про два варианта объявления динамических массивов). Ну и конечно от ситуации зависит. |
| Автор: fry 8.6.2009, 03:42 | ||||
| Понимаю, что тема закрыта, однако создавать по такой мелочевке тему не хочется, да и не надо. к
Забавы ради и удовлетворения любопытства для провел тест на ОС Linux (Fedora 10) на линейные и нелинейные массивы, точнее скорости выделения и работы. Код теста (взят частично http://forum.vingrad.ru/forum/topic-249780/unread-1/hl/%25D0%25BC%25D0%25B0%25D1%2582%25D1%2580%25D0%25B8%25D1%2586%25D0%25B0/index.html#st_15_view_0, переделан за неимением conio и vcl):
Выдает: Без оптимизации: Create On Pointers = 50000 Create solid = 0 Fill pointers = 900000 Fill solid = 920000 С оптимизацией: Create On Pointers = 40000 Create solid = 0 Fill pointers = 540000 Fill solid = 540000 ЗЫ ДАННЫЙ ПОСТ НЕ ИМЕЕТ ЦЕЛЬ ЧЕГО-ТО ДОКАЗАТЬ |