Różnica pomiędzy if i else if

0

Witam.

Jestem pewien, że pytanie, które chcę zadać jest bardzo trywialne, ale ta kwestia ciągle nie daje mi spokoju.
Mianowicie zastanawiam się, jaka jest różnica pomiędzy takimi dwoma tworami:

Twór pierwszy:


int main()
{
	int warunek;

	if(warunek == 1) Jakas instrukcja1;
	else if(warunek == 2) Jakas instrukcja2;
	else Jakas instrukcja3;
	return 0;
}
int main()
{
	int warunek;

	if(warunek == 1) Jakas instrukcja1;
	if(warunek == 2) Jakas instrukcja2;
	else  Jakas instrukcja3;
	return 0;
}

Myślę, że chociaż to tylko nic nie robiący pseudokod, dostatecznie wyraźnie ilustruję, co mnie zastanawia. Z góry dziękuję za odpowiedzi. Pozdrawiam

1

Ten kod jest bardzo pseudo :D Ale skoro to tylko dla przykładu...
No więc jeśli sprawdzasz ten sam warunek to skoro coś się równa 1 to nie równa się 2 (oczywistość). Jeśli pominiesz else to kompilator sprawdzi najpierw czy coś = 1, jeśli tak to wykona warunek, później sprawdzi, czy to samo = 2. Oczywiście nie równa się, skoro = 1, więc zmarnowałeś właśnie zasoby na bezsensownie porównanie :)

0

Oczywiście chodziło mi o program, a nie kompilator. Ech, nie ma jak to gafa przed snem :)

0

A, w tym rzecz. Już rozumiem. Dzięki serdeczne.

Pozdrawiam

2

[edit: ups! kliknąlem na Odpowiedz i coś się nie mogłem zebrać z napisaniem posta -- w międzyczasie pojawiło się info, że autor już zrozumiał. No nic, zostawiam moje szczegółowe wypociny dla potomnych]

Chodzi o to, że w ciągu instrukcji if-else if-else (else jest opcjonalne -- jeśli będzie, to na końcu) tylko jeden z bloków zostanie wykonany: pierwszy, którego warunek pasuje. Gdy któryś z warunków będzie prawdziwy, to jego instrukcje zostaną wykonane i dalsze warunki nie są już sprawdzane. Paweł napisał Ci już, że to zwiększa wydajność. Bo skoro w pierwszym warunku sprawdzasz, czy n jest równe 1, a w drugim czy jest równe 2, to jeśli n jest faktycznie równe 1 i instrukcja przy pierwszym warunku zostanie wykonana, to nie ma sensu sprawdzać, czy n nie jest przypadkiem równe 2:

int n = 1;
if (n == 1) {
  printf("Jeden\n");
} else if (n == 2) {
  printf("Dwa\n");
} else {
  printf("Coś innego niż jeden i dwa\n");
}

Ponieważ n jest tu równe 1, pasuje już pierwszy warunek (przy instrukcji if). Wyświetlone zostanie "Jeden" i dalsze warunki (else if oraz else) nie są nawet sprawdzane.

Zauważ też inną rzecz: ciąg if-else if-else pozwala Ci na zastosowanie wygodnego else. Tj. mówisz, że jeśli n jest równe 1 to to, jeśli jest równe 2 to co innego, a W PRZECIWNYM WYPADKU jeszcze coś innego. Chodzi o to, że masz 100% pewności, że ten "przeciwny wypadek" to taki, że n nie jest równe 1 i nie jest równe 2.

Rozważmy to na przydatnym przykładzie. Sprawdzamy w nim, czy n jest liczbą ujemną (ściśle mniejszą od zera), dodatnią (ściśle większą od zera), czy równą zero:

/* załóżmy, że n to int wprowadzany przez użytkownika */
if (n > 0) {
  printf("Liczba dodatnia\n");
} else if (n < 0) {
  printf("Liczba ujemna\n");
} else {
  printf("Zero\n");
}

Zauważ, że w dwóch pierwszych warunkach sprawdzamy, czy n jest -- odpowiednio -- większe, czy mniejsze od zera. Jeśli ani pierwszy, ani drugi warunek nie zostanie spełniony, to wykonywany jest kod z else. Ale zauważ, co to oznacza. Jeśli ani nasz if, ani else if nie zostanie spełniony, to możemy z całą pewnością założyć, że liczba nie jest ani większa, ani mniejsza od zera. A jak jest ani większa, ani mniejsza od zera, to znaczy to po prostu, że jest równa zero -- cudów nie ma!

Zauważ, że bez else if to już nie działa:

/* załóżmy, że n to int wprowadzany przez użytkownika */
if (n > 0) {
  printf("Liczba dodatnia\n");
} 

if (n < 0) {
  printf("Liczba ujemna\n");
} else {
  printf("Zero\n");
}

Celowo wstawiłem tam nową linię pomiędzy pierwszym a drugim ifem. Bo else teraz tyczy się tylko tego drugiefo if-a. Co się stanie, jeśli n będzie wynosiło na przykład 5?

Pierwszy warunek zostanie spełniony, bo 5 jest większe od zera. Czyli zostanie wyświetlone Liczba dodatnia. Warunek przy drugim ifie nie będzie spełniony, bo 5 nie jest mniejsze od zera. Czyli co się wykona? Klauzula else przy tym ifie! Więc oprócz tego, że przed chwilą wyświetliliśmy, że to liczba dodatnia, teraz wyświetlimy jeszcze napis Zero! Katastrofa! Trzeba było jednak zostawić else if. Bo else if pozwala połączyć klauzulę else z więcej niż jednym warunkiem (czyli możemy podpiąć else do jednego ifa, albo do jednego ifa i dowolnej liczby else if).

No i jeszcze jedna sprawa. Nic nie stoi na przeszkodzie żebyś napisał warunki, które na siebie nachodzą lub które są sobie dokładnie równe. Np. coś takiego, bez else if:

int n = 1;
if (n == 1) {
  printf("Jeden\n");
}

if (n == 1) {
  printf("Wciąż jeden\n");
}

Jeśli n jest równe 1, a w tym kodzie jest, to pierwszy if zostanie spełniony -- wyświetlone zostanie Jeden. Ale dalej stoi drugi if, nie połączony z pierwszym, bo to nie jest else if. Więc drugi if też jest sprawdzany. On też sprawdza, czy n jest równe 1. Ponieważ n nadal jest równe 1, wyświetlimy też tekst Wciąż jeden.

A co jeśli użylibyśmy else if?

int n = 1;
if (n == 1) {
  printf("Jeden\n");
} else if (n == 1) {
  printf("Wciąż jeden\n");
}

Mam nadzieję, że sam to wykombinujesz. Teraz te warunki są połączone i wykonane zostaną instrukcje stojące tylko pod jednym z nich. Pierwszym, który pasuje.

Czyli tutaj warunek przy ifie będzie spełniony, wyświetlimy Jeden. A potem... już niczego nie wyświetlimy, bo nie obchodzą nas pozostałe warunki.

To nawet można zrozumieć wprost, tłumacząc sobie instrukcje z angielskiego na polski. W pierwszym kodzie, bez else if, mamy: "Jeśli n jest równe 1, wyświetl Jeden. Następnie, jeśli n jest równe 1, wyświetl Wciąż jeden". Widać tu, że gdy n jest równe 1, zostaną wyświetlone dwa teksty. Z else if mamy natomiast inaczej: "Jeśli n jest równe 1, wyświetl Jeden. W przeciwnym wypadku [jeśli poprzedni warunek nie został spełniony], jeśli n jest równe 1, wyświetl Wciąż jeden". Kluczowe jest tutaj stwierdzenie w przeciwnym wypadku. Komputer nie patrzy na to, że warunki przy if oraz przy else if są takie same. Komputer, gdy widzi else if, to pierwsze co robi to patrzy, czy poprzedni warunek (ten przy ifie, pod którym jest else if) nie został przypadkiem spełniony. Jeśli został spełniony, to warunek else if nie zostaje nawet sprawdzany. Komputer tak jakby czyta "w przeciwnym wypadku...", czyli "jeśli poprzedni warunek nie został spełniony" i patrzy, czy ten poprzedni warunek został spełniony. Jak nie został, to leci dalej z else if. A jeśli poprzedni warunek został spełniony, to komputer nie leci z dalszymi else if i else -- bo je sprawdza tylko "w przeciwnym wypadku".

1

Różnica pomiędzy:

if (flaga) {
  flaga = false;
} else if (!flaga) {
  flaga = true;
}

a:

if (flaga) {
  flaga = false;
}
if (!flaga) {
  flaga = true;
}

Jest dość znaczna. Ogólnie jeżeli, któryś z elementów warunku jest zmieniony wewnątrz ifa to jest duża szansa, że wartość warunku się zmieni i przez to inne będzie działanie programu.

Else tyczy się ostatniego ifa bez elsa, tak więc trzeba uważać. W NetBeans jest taki magiczny skrót klawiaturowy Alt+Shift+F, polecam go często naciskać, ładnie formatuje kod - dzięki wcięciom widać łatwiej co jest źle.

0

Dziękuje wam wszystkim serdecznie. No już prościej tego chyba wytłumaczyć nie mogliście :)

Pozdrawiam

0

Najlepiej to sobie wyobrazić, że nie ma czegoś takiego jak „else if”.

ten kod:

if (flaga) {
  flaga = false;
} else if (!flaga) {
  flaga = true;
}

jest równoznaczny temu:

if (flaga) {
  flaga = false;
}
else
{
  if (!flaga) {
    flaga = true;
  }
}

drugi if jest po prostu tym, co ma się wykonać w else pierwszego.

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