Według mnie to zadanie jest źle sformułowane. Rozumiem, że ktoś miał pomysł aby praktykować if'y w ten sposób ale realnie porównywanie więcej niż 2 elementów w ten sposób jest bardzo(bardzo) złą praktyką.
Znalazłem tego typu kod (znajduje on minimum 4 liczb bez pętli). (https://stackoverflow.com/questions/19199473/biggest-and-smallest-of-four-integers-no-arrays-no-functions-fewest-if-stat):
int a = 5, b=4, c=7, d=9;
int min_ab, min_cd, min;
min_ab = a < b ? a : b;
min_cd = c < d ? c : d;
min = min_ab < min_cd ? min_ab : min_cd;
printf("%d", min);
Wadą tego rozwiązania jest to, że działa w tylko jednym przypadku, zaleta jest taka, że jest bardzo szybki.
Zasadniczo maksymalną wartość można ustalić podczas podawania wejścia od użytkownika. Używając pętli można uogólnić problem dla dowolnej liczby wartości, można nawet uogólnić typ danych jaki ma zostać porównany.
Poniżej jest mój przykład(c++11), działa dla dowolnej ustalonej liczby wejść i typu danych (przynajmniej prymitywnych).
#include <iostream>
#include <array>
#include <limits>
#include <algorithm>
//Wolna funkcja szablonowa
template<typename T, std::size_t arr_size>
void GetMaxValue()
{
//Tworzysz nową tablice typu T o wielkości arr_size
std::array<T, arr_size> num_array{};
//Zmienna na przechowywanie wartości maksymalnej
T max_val{T()};
//Pętla do wprowadzania liczb
for(std::size_t i{std::size_t()}; i<arr_size; ++i)
{
//Wypisz wiadomość, który element
std::cout << "Type in [" << i << "] value.\n";
//Tymczasowa zmienna na przechowywanie wejścia
T input_value{};
//Pobiera wejście ze standardowego strumienia,
//jeśli std::cin nie otrzyma typu zmiennej T
//będzie powtarzać pętle dopóki nie otrzyma poprawnego typu T
while(!(std::cin >> input_value))
{
std::cout << "Value is invalid. Try again.\n";
//Te dwie linie czyszczą flage błędu i ignorują resztę wejścia
std::cin.clear();
std::cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
}
//Komunikat sukces, kopiuje wartość do tablicy
std::cout << "[OK]\n";
num_array[i] = input_value;
//Sprawdź czy ostatnie wejście jest większe od max,
//jeśli tak to zapisz nową wartość max
max_val = max_val < input_value ? input_value : max_val;
}
//Wypisujesz zawartość tablicy
std::cout << "User input:\n";
for(auto number : num_array)
{
std::cout << number << '\n';
}
//Wypisz zmienną na ekran
std::cout << "Max number: " << max_val << '\n';
}
int main()
{
//tego typu stała jest znana w czasie kompilacji i może służyć jako argument szablonu
constexpr int num_count{4};
//Wywołanie funkcji z argumentami szablonu
std::cout << "===INT\n";
GetMaxValue<int, num_count>();
//Wywołanie dla innego typu
std::cout << "===FLOAT\n";
GetMaxValue<float, num_count>();
return 0;
}
Edit:
Zastanawiałem się trochę nad tym zadaniem i znalazłem nowe roziązanie. Nie jest to do końca rekurencja, bo wywoływane są kolejne specjalizacje funkcji szablonowej. Wadą tego rozwiązania jest to, że ilość wygenerowanych funkcji jest proporcjonalna do ilośći argumentów. Działa też dla róźnych typów ale wynik zależy od zasad konwertowania typów, w tym przypadku jest (chyba) zawężony do int.
Przykład c++ 14
#include <iostream>
template<typename T>
constexpr T GetMax(T val)
{
return val;
}
template<typename T, typename ... Args>
constexpr T GetMax(T val, Args ... args)
{
auto max_val(GetMax(args...));
return val > max_val ? val : max_val;
}
int main()
{
//**Wprowadziliśmy 4 liczby z konsoli**
int a{3}, b{244}, c{6}, d{74};
std::cout << "Max 4 liczb : " << GetMax(a,b,c,d) << '\n';
//Wynik GetMax(...) obliczony w czasie kompilacji
constexpr int e{45}, f{654}, g{87}, h{35};
std::cout << "Max 4 liczb : " << GetMax(e,f,g,h) << '\n';
//Inne typy danych, magiczne liczby w parametrach :)
std::cout << "Max, different types: " << GetMax(34.0, 54.0f, 14, 213L, true, false) << '\n';
std::cout << "Max, bool type: " << GetMax(true, false, true) << '\n';
return 0;
}