Loading...

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

gydigydi avatar gydigydi 12 Точки

Задача 1 от Memory Аccess and Мanagement c++

Write a program that reads two integer arrays from the console and
compares them element by element. The comparing should be done in a
function bool compArr(int arr1, int arr2), which returns true if
they are equal and false if not

Щом така е зададено в условието bool compArr(int arr1, int arr2), според мен означава че в тази функция сравняваме само по един елемент от масивите а не всички елементи от масивите, така ли е ?

Тагове:
0
C++ Programming
Aguzelov avatar Aguzelov 78 Точки

Точно така. Трябва да се сравни дали елемент на i позиция в arr1[] е равен на елемента на същата позиция в arr2[].

-1
ThePSXHive avatar ThePSXHive 436 Точки

Така представена, сигнатурата на compArr не предполага, че на функцията ще бъдат предадени масиви като аргументи. Ако "равенство" на масивите означава просто да се провери дали двата масива имат еднакъв брой елементи, то тогава е безсмислено да се обсъжда сравяване на елементи, но предполагам, че това не е формулировката на заданието, и че се изисква проверка (елемент по елемент) за това дали елементът на i-th индекс в единия масив е равен на елементът на същият индекс от другия масив. Това означава, че най-напред трябва да се провери дали масивите имат еднакъв размер, иначе от проверката няма смисъл. Разбира се, другият вариант е да се има предвид итерация в главната програма, в която не предаваме на функцията " всички елементи от масивитe", а "само по един елемент от масивите", но и в този случай, ако не се въвежда отделно, размерът на съответния масив трябва да бъде известен. Най-удобно е това да се реализира чрез оператора sizeof, и то използван така:

sizeof(array)/sizeof(array[0]);

Пиша този пример, защото понякога виждам следното:

sizeof(array)/sizeof(<Type>); 

където с Type се обозначава типът на съответните елементи в масива. В този случай, ако по-натам решиш да смениш типът на елементите в колекцията, ще трябва да отразиш тази промяна на всеки ред, използващ този израз.Първата версия няма този недостатък.

1
MartinBG avatar MartinBG 4803 Точки

Съгласен съм с @ThePSXHive относно тълкуването на условието.

bool compArr(int arr1, int arr2) предполага, че ще ѝ бъдат подадени две int стойности за сравнение.

Аз я бях решил по по-опростен начин:

1. Питам за размер на двата масива

2. Създавам ги и ги чета от конзолата елемент по елемент за всеки масив по отделно

3. Извиквам bool compArr(int arr1[], int arr2[]), като ѝ подавам двата масива като параметри, защото това ми се беше сторило правилното решение :). Като се замисля, още по-правилно би било масивите да се подадат като константни параметри: bool compArr(const int arr1[], const int arr2[]) за да се застраховаме, че нищо няма да ги промени.

 

След като прочетох тази тема, реших, че първото ми решение не е правилно спрямо условието и пререших задачата по следния начин:

1. Прочитам елементите на първия масив

2. Прочитам елементите на втория масив

3. Ако броя елементи на двата масива е еднакъв, ги сравнявам елемент по елемент в цикъл от main(), който вика bool compArr(const int&, const int&). Позволих си волността да подавам към функцията (константни) референции за елементите, вместо техни копия, защото смятам, че това е по-правилно в случая.

 

@ThePSXHive

Относно sizeof(array)/sizeof(<Type>) или  sizeof(array)/sizeof(array[0])

На последната лекция Жоро (@georgi.stef.georgiev) спомена, че намирането на броя елементи на масив чрез този метод не е добра практика, защото има ситуации, в които може и да не сработи. Какво би коментирал по въпроса?

 

 

1
10/03/2017 16:12:30
ThePSXHive avatar ThePSXHive 436 Точки

Благодаря за запитването!

 

Да, менторът е, разбира се, прав; ако масивът бива предаван като актуален аргумент, в тялото на функцията, найменованието му ще бъде разглеждано от компилаторът като указател към първият елемент. В този случай, единственият резултат от прилагането на горния израз ще бъде размерът на указателят, който е един и същ съответно за различните архитектури, без значение към какъв тип данни сочи (64 или x86 арх.) В тази ситуация масивът в тялото на функцията "деградира" до указател (pointer decay). Според мен, един от по-добрите варианти е просто да се използват ресурсите на стандартната библиотека, и когато е необходим статично алокиран масив, да се използва std::array; ако е необходимо може да се прибегне и към std::list или std::vector, но и в двата случая няма да се наложи човек да се ангажира с детайлите за размера на колекцията. Другият вариант е размерът просто да бъде предаван като допълнителен аргумент, но от условието става ясно, че това не се изисква. Това е засегнато в курса, явно, но в по-нататъшните лекции.

1
MartinBG avatar MartinBG 4803 Точки

Благодаря за отговора!

Стана ми интересно и пробвах различни варианти за предаване или получаване на масив към/от функция, като при всички по-горният метод за изчисляване на размера даде грешен резултат (на конкретната система: 1 за int масив от 10 елемента).

 

Всъщност, единственият сценарий, при който сметката беше вярна, e когато масива се създаде в стека и се изчисли директно:

 

    int localArray[10];

    cout << sizeof(localArray) / sizeof(localArray[0]) << endl; // Връща 10

 

Ако масива се създаде в хийпа, отново дава грешен резултат за размера:

 

    int* pArr = new int[10];

    cout << sizeof(localArray) / sizeof(localArray[0]) << endl; // Връща 1

 

Тези резултати окончателно ме убедиха да сложа този трик за смятане на броя елементи на масив в списъка си с лоши практики. :)

 

1
11/03/2017 00:32:08
georgi.stef.georgiev avatar georgi.stef.georgiev 921 Точки

Това пак е грешка от моя страна в сигнатурата на фунцията - самата задача не се променя, трябва да въведете два масива и да изведете дали са еднакви.

Сигнатурата я дадох уж за да ви помогна да си организирате кода, ама съм я объркал - подходяща сигнатура на compArr в тази задача би била bool compArr(int arr1[], int arr1Length, int arr2[], int arr2Length), или пък ако искате да си играете с templates (преди да ги учим) - template<unsigned int L1, unsigned int L2> bool compArr(int arr1[L1], int arr2[L2]). Няколко const-а там също не биха били зле. Правилно описана, функцията трябва да мине по индексите на първия масив и да сравни стойностите от съответните индекси на втория (разбира се дължините също трябва да съвпадат, за да имаме еднаквост).

Ако в някоя задача нещо от този тип не е наред, спазвайте главното условие на задачата - детайлите са сложени с цел да са в помощ, така че ако има грешка в тях, просто правете нещата, както намерите за добре, стига да програмата ви да решава дадената задача. И казвайте, че съм омазал нещо - понякога правя редакция в последния момент без да я мисля достатъчно, а като нямам реално peer review нещата остават, докато не би забележете.

В случая, ако вече сте решили задачата и програмата вярно сверява два масива дали са еднакви - няма нужда да я пренаписвате, ако не ви се занимава.

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

Поздрави,

Жоро

P.S.: дискусията между @MartinBG и @ThePSXHive дава някои добри предложения за интерпретация на условието, както и за проблемите със pointer decay и факта, че по-сигурния подход е ползването на някой STL клас като например vector (btw бих избягвал list освен ако нямате добра причина да е точно list, а не vector - като стигнем до STL лекцията ми напомнете да спомена защо - или можете да го google-нете, мисля, че дори Bjarne Stroustrup имаше лекция по темата)

1
Можем ли да използваме бисквитки?
Ние използваме бисквитки и подобни технологии, за да предоставим нашите услуги. Можете да се съгласите с всички или част от тях.
Назад
Функционални
Използваме бисквитки и подобни технологии, за да предоставим нашите услуги. Използваме „сесийни“ бисквитки, за да Ви идентифицираме временно. Те се пазят само по време на активната употреба на услугите ни. След излизане от приложението, затваряне на браузъра или мобилното устройство, данните се трият. Използваме бисквитки, за да предоставим опцията „Запомни Ме“, която Ви позволява да използвате нашите услуги без да предоставяте потребителско име и парола. Допълнително е възможно да използваме бисквитки за да съхраняваме различни малки настройки, като избор на езика, позиции на менюта и персонализирано съдържание. Използваме бисквитки и за измерване на маркетинговите ни усилия.
Рекламни
Използваме бисквитки, за да измерваме маркетинг ефективността ни, броене на посещения, както и за проследяването дали дадено електронно писмо е било отворено.