Funkcja przekazuje (udostępnia) wartość na zewnątrz funkcji

0

Napisz funkcję która policzy ile w przekazanej funkcji tablicy liczb całkowitych jest wartości parzystych. Wyznaczona wartość jest zwracana. Funkcja znajduje również wartość maksymalną, która jest przekazywana (udostępniana) na zewnątrz funkcji.

Takie mam zadanie do wykonania i ono jest generalnie dosyć proste. Nie wiem tylko jak zrobić drugą część zadania tzn. w jaki sposób wartość maksymalna ma być przekazywana (udostępniana) na zewnątrz funkcji. Nie wiem czy to jakąś referencją trzeba czy czymś innym. Jeżeli ktoś zaprezentowałby w jakimś prostym algorytmie w jaki sposób funkcja przekazuje (udostępnia) jakąkolwiek wartość na zewnątrz funkcji byłbym bardzo wdzięczny.

0

Przekazywana przez np wskaźnik będący argumentem funkcji.

Prototyp:

unsigned foo(int *tab, int *max);
1

Jedno z dwóch:

  1. Wszystkie wartości zwracasz poprzez referencje
  2. Jedną zwracasz normalnie, drugą (i pozostałe) poprzez referencje
  3. Zwracasz strukturę zawierającą wszystkie wartości, np std::pair lub std::tuple
0

Jeszcze wersja z funktorem (C++11):

#include <iostream>
#include <vector>
#include <algorithm>

using namespace std;

struct Scanner {
  
  Scanner(int &aMaxValue, int &aEvenCount): maxValue(aMaxValue), evenCount(aEvenCount) 
  {
  }
  
  void operator()(int elem) const {
    if (elem % 2 == 0)
       evenCount++;
    if (elem > maxValue)
       maxValue = elem;
  }

private:
  int &maxValue;
  int &evenCount; 
};

int main() {
	std::vector<int> vect = {12,-3, 4, -8, 0, 222};

    int maxValue(-1), evenCount(0);	

	if (!vect.empty()) 
	  maxValue = vect.front();

	Scanner scanner(maxValue, evenCount);
	
	for_each(vect.begin(), vect.end(), scanner);
	
	cout << "Parzyste: " << evenCount << endl;
	cout << "Max: " << maxValue << endl;
	
	return 0;
}
0

Albo tak:

#include <iostream>
#include <algorithm>
#include <ctime>
#include <cstdlib>

void f(int tab[], const unsigned r, int &m , unsigned &l){
    l=0;
    m=*std::max_element(tab,tab+r);
    for(unsigned i=0;i<r;i++)
        if(!(tab[i]%2))l++;
}

int main(){
    srand(time(NULL));
    int tab[10],max;
    unsigned il;

    for(int i=0;i<10;i++){
        tab[i]=rand()%10+1;
        std::cout << tab[i] << " ";
    }

    f(tab,10,max,il);
    std::cout << "\nMaksimum:" << max << " Parzystych:" << il << "\n";
    return 0;
}
0

Chwileczkę. Mam pytanie: Jak zwrócić przez referencję wartość będącą już w ciele funkcji?

0

Chociażby tak jak moja funkcja to robi przy zmiennych 'r' oraz 'l'. (Swoją drogą tak: te nazwy są do bani) O to Ci chodziło? Kiedy argumentem jest referencja albo wskaźnik możesz traktować ten argument tak jakbyś pracował na oryginale przekazanym do funkcji. Kiedy go zmieniasz zmienia się oryginalna zmienna, bo przekazujesz tak naprawdę adres tej zmiennej, a nie jej wartość.

0
unsigned f(int* arr, size_t s, int& max) {
	unsigned evenCount = 0;
	max = arr[0];
	while(s--) {
		if(arr[s] > max)
			max = arr[s];
		if(arr[s] % 2 == 0)
			++evenCount;
	}
	return evenCount;
}
grzesiek51114 napisał(a):

Racja, w sumie niegłupie. Sugerowałem się tym, że programista może nieopatrznie zmienić r w ciele funkcji i wtedy zmienna ta nie będzie odpowiadała rozmiarowi tablicy. Żeby temu zapobiec wstawiłem const. W tym moim przypadku może i na wyrost ale... Co z tego, że zmienna przekazana jest przez wartość kiedy ktoś może ją zmienić w ciele funkcji (oczywiście kopie, bo przez wartość) i przez to program nie będzie działał prawidłowo. Trochę tutaj jeszcze nie do końca rozumiem dlaczego wstawiłem const źle.

zobacz sobie na mój przykład. Lubię zmieniać liczbę elementów tablicy ;]

1

Jak już optymalizujemy to:

Wersja czytelna:

; 26   :         if(arr[s] % 2 == 0)

	and	ecx, -2147483647			; 80000001H
	jns	SHORT $LN9@f2
	dec	ecx
	or	ecx, -2					; fffffffeH
	inc	ecx
$LN9@f2:
	jne	SHORT $LN1@f2

; 27   :             ++evenCount;
	inc	eax

Wersja nieczytelna: (3 instrukcje ASM, 0 skoków)

; 38   :         evenCount+=1^(1&arr[s]);

	not	ecx
	and	ecx, 1
	add	eax, ecx

Wersja zoptymalizowana 1: (2-3 instrukcje ASM, 1 skok)

; 49   :         if((arr[s] & 1) == 0)

	test	cl, 1
	jne	SHORT $LN1@f4

; 50   :             ++evenCount;

	inc	eax
$LN1@f4:

Wersja zoptymalizowana 2: (2 instrukcje ASM) - z komentarza wyżej

; 61   :         evenCount -= (arr[s] & 1);

	and	ecx, 1
	sub	eax, ecx

Od siebie dodam, że najbliższa by mi była wersja ostatnia - jest czytelna i wydajna (no poza tym odejmowaniem zamiast inkrementacji) - gdybym oczywiście musiał coś optymalizować.

1 użytkowników online, w tym zalogowanych: 0, gości: 1