Премини към съдържанието
Любомир Пенчев

теоретичен въпрос относно масиви(или как да си го предствим в съзнанието)

Препоръчан отговор


здравейте въпросът ми може да се окаже много глупав но предполагам че за много новобранци в програмирането тия неща са тъмна индия. И по темата имам си идея какво е двумерен масив (представям си го като матрица) да въведеш масив и да го изведеш е лесно

(for(i=0;i<n;i++)

for(i=0;i<n;i++)

{

cout<<i<<" "<<j<<" "; cin>>a[j];

}

for(i=0;i<n;i++)

for(i=0;i<n;i++)

{

cout<<i<<" "<<j<<" ">>a[j];

} )

обаче стигаме до момента в които с този масив трябва да се направи нещо понеже няма полза да си въвейдаме и извеждаме масиви.

примерно да изведем сбора на елементите на редовете и да ги въведем като елементи на масива b,

или да сравним елементите на масива а и да изведем най-голямата стоиност (или индекса на наи коглемия елемент),

или някаква друга задача (отворен съм за идеи).

лично аз стигам до моментите с въвеждането инициализацията на масива е ясна за да разчете елементите се използва пак функциите

for(i=0;i<n;i++)

for(i=0;i<n;i++)

и след това става някакво адско объркване. не изписвам код понеже незнам какъв за което се и извинявам но той е в основата на въпроса ми. Не моля да ми се реши задача  понеже така всеки може. молбата ми е ако някой може и му се занимава да обясни някакви подходи на работа на теория и с код кое от каде идва и защо става така. ясно ми е че въпроса е адски обемен но предполагам че много хора са се зблъсквали с тези проблеми.

Сподели този отговор


Линк към този отговор
Сподели в други сайтове

Има достатъчно уроци в интернет примерно . Не знам за да видят дали внимавате или защото просто и те са хора даскалите правят умишлено или неволно грешки - като разбереш как се работи с масиви сам ще я/ги намериш в горния урок.

Редактирано от ined (преглед на промените)

Сподели този отговор


Линк към този отговор
Сподели в други сайтове

Здравей,

 

Ти сам си го казал двумерният масив е нищо повече от една матрица. Като достъпваш до съответният елемент като използваш съответно индексите за ред и колона. За да обходиш масива ти трябва конструкция на два вложени цикъла, например с for. А пък в общият случай задачите с двумерен масив се свеждат до инициализация на масива, обхождане и извеждане на резултатите. Като при обхождането му, съответно достъпването на даден елемент и изпълнението на някакво условие е решението на задача. Например :

//Find the max element of matrixint maxElement = array[0][0]; //Initialize max element with first element of the matrixfor(int i = 0 ; i < rowCount ; i++) // Iteration of rows of the matrix  for(int j = 0 ; j < columnsCount; j++) // Iteration of columns of the matrix {    if(maxElement < array[i][j]) // If max element is less than current element    {       maxElement = array[i][j];    } }

Сподели този отговор


Линк към този отговор
Сподели в други сайтове

Може би е добре, като допълнение към написаното от @ined да отбележим и как обаче един двумерен масив физически съществува в паметта. Тук е даден един частичен отговор на въпроса, като остава да се отбележи и какво всъщност е двойния (n- торния) указател към даден тип данна (т.е. какво е примерно int**). В случая, броя на '*' отбелязва броя на нивата на адресация (мисля, че това беше термина) на указваната памет.

Както знаем от програмирането, n* съдържа адрес към памет, която може да е както един - единствен елемент от съответния приложим тип, така и поредица от елементите, с адрес на първия елемент, записан като стойност в паметта на променливата n. 

 

Визуално това може да се интерпретира така:

TYPE* n -> |0xA1A3BF|  (Типа на данната в реферираната памет е TYPE)

 

                  |0x111112|    |0x212122|   |0x43AAC3|   (Типа на данните в тази памет е TYPE)

                  |0x111111|    |0x212121|   |0x43AAC2|   (Типа на данните в тази памет е TYPE)

                            ^                 ^                  ^

                            |                  |                   |

TYPE** n -> |0xA1A3BF | 0xA1A3C0 |  0xA1A3C1|    (Типа на данните в тази памет в TYPE* )

(Стойносттa на n е 0xA1A3BF )

(Стойността на записаната информация в памет с адрес 0xA1A3BF e 0x111111)

(Стойността на записаната информация в памет с адрес 0xA1A3C0 e 0x212121)

(Стойността на записаната информация в памет с адрес 0xA1A3C1 e 0x43AAC2)

В случая TYPE** n се чете "Указател към указател от тип TYPE". 

Т.е. всяка референция сочи към последователно заделена памет, в която имаме 1 или повече на брой данни от тип, който образно казано е с една '*' по - малко от типа, който го реферира. Т.е. : 

 

TYPE (k)* = {TYPE (k-1)*, TYPE (k-1)*, TYPE (k-1)*, ...};

 

Надявам се това да внесе повече разяснения, отколкото шум :).

 

Поздрави !

Редактирано от soundtracker (преглед на промените)
  • Харесва ми 1

Сподели този отговор


Линк към този отговор
Сподели в други сайтове

...

 soundtracker, да знаеш че всеки път когато някой спомене двоен указател, масив и урок в едно изречение, аз си представям краш. И според мен е много грешно да се представя многомерен масив като многократен указател. Защото НЕ Е така. двумерният масив от тип type НЕ Е двоен указател от тим type. Той е указател към "тип едномерен масив от тип type".

Много много заблуждаващо е да представяш нещата така. Хората си слагат след това знак за еквивалентност и почват да използват двойни указатели като двумерни масиви. Масивите носят информация на компилатора за броя елементи "зад" указателя. Чистите указатели НЕ.

Това го обяснявах преди много време накратко, тук.


  • Харесва ми 1

Сподели този отговор


Линк към този отговор
Сподели в други сайтове

 

Приемам забележката с едно малко "но" - в обясненията си в последния пост, говоря за "памет" - не конкретизирам директно масивите, защото както и ти спомена, не трябва да правим директен аналог между двете. Имат косвена връзка, но си имат и достатъчно разлики (както и отбеляза).  

 

двумерният масив от тип type НЕ Е двоен указател от тим type. Той е указател към "тип едномерен масив от тип type".

 

Т.е. всяка референция сочи към последователно заделена памет, в която имаме 1 или повече на брой данни от тип, който образно казано е с една '*' по - малко от типа, който го реферира. Т.е. : 

 

TYPE (k)* = {TYPE (k-1)*, TYPE (k-1)*, TYPE (k-1)*, ...};

Може би не съм се изразил, както ми се е искало, но идеята на примера и диаграмката ми беше именно тази, за която и ти споменаваш :)

 

Много много заблуждаващо е да представяш нещата така. Хората си слагат след това знак за еквивалентност и почват да използват двойни указатели като двумерни масиви.

Да, тук вече може би беше моя вина, че не разписах разликите. Двоен указател може да се използва, за да изгради структура, наподобяваща двумерен масив, но не и да създаде еквивалентна такава. Най-малко един истински двумерен масив ще е заделен в един непрекъснат блок от памет, докато при работа със указатели, имаме доста по - фрагментирано заделяне и рефериране (както се и вижда от примера в последния ми пост). 

 

Поздрави и отново благодаря за градивната критика !

  • Харесва ми 1

Сподели този отговор


Линк към този отговор
Сподели в други сайтове

Поздрави и отново благодаря за градивната критика !

Основната причина за намесата ми беше включването на многократните указатели. Тъй като те носят много малко информация (тоест никаква) за това дали зад тях стои един елемент, или сложна структура от елементи, не трябва самостоятелно да се ползват за описването и предаването на такава. Предпочитам нещо като клас или (структура + комплект функции за работа). А многократен указател - само когато трябва да се заделя/освобождава/променя "многократен-1" указател. Това е лично мое мнение, но особено много държа на него. Работата с указатели в C и C++ е изключително податлива на грешки и е хубаво да се пазиш колкото може повече.
  • Харесва ми 1

Сподели този отговор


Линк към този отговор
Сподели в други сайтове

Регистрирайте се или влезете в профила си за да коментирате

Трябва да имате регистрация за да може да коментирате това

Регистрирайте се

Създайте нова регистрация в нашия форум. Лесно е!

Нова регистрация

Вход

Имате регистрация? Влезте от тук.

Вход

×

Информация

Поставихме бисквитки на устройството ви за най-добро потребителско изживяване. Можете да промените настройките си за бисквитки, или в противен случай приемаме, че сте съгласни с нашите условия за ползване.