czwartek, 28 stycznia 2016

C - Instrukcja warunkowa If else

Ten post będzie zawierał informacje dotyczące instrukcji warunkowej If else.

[Źródło: https://icons8.com/icon/40670/c-programming]

Zapis tej instrukcji przedstawiłem poniżej:

  1. if(warunek)
  2. {
  3.   //....
  4. }
  5. else if(warunek)
  6. {
  7.   //...
  8. }
  9. else
  10. {
  11.   //...
  12. }

Działanie jest bardzo proste. Jeśli warunek wpisany w nawiasie jest prawdziwy, wtedy zostaje wykonany kod zdeklarowany w danej jej części. Jeśli natomiast warunek nie jest spełniony, to następuje sprawdzenie kolejnego. Natomiast jeśli żaden z nich nie jest prawdziwy to wykonywana jest część opisana po słowie else, jeśli oczywiście została ona zdeklarowana.

Poniżej przedstawię kilka przykładowych programów pozwalających na łatwe zrozumienie tego zagadnienia.

W pierwszym programie sprawdzana jest wartość zmiennej, jeśli jest ona prawdziwa to zostanie wypisany tekst na ekranie.

  1. #include <stdio.h>
  2. #include <stdlib.h>
  3.  
  4. int main()
  5. {
  6.     int zmienna = 5;
  7.  
  8.     if(zmienna == 5)
  9.     {
  10.         printf("Warunek prawdziwy");
  11.     }
  12.     return 0;
  13. }

Kolejny program zawiera trochę rozbudowaną liczbę warunków:

  1. #include <stdio.h>
  2. #include <stdlib.h>
  3.  
  4. int main()
  5. {
  6.     int zmienna = 2;
  7.  
  8.     if(zmienna == 5)
  9.     {
  10.         printf("Warunek prawdziwy");
  11.     }
  12.     else if(zmienna == 3)
  13.     {
  14.         printf("Drugi warunek");
  15.     }
  16.     else
  17.     {
  18.         printf("Inna wartosc");
  19.     }
  20.     return 0;
  21. }

Poszczególne instrukcje można także zagnieżdżać, przez co będzie sprawdzanie kilka warunków.

  1. #include <stdio.h>
  2. #include <stdlib.h>
  3.  
  4. int main()
  5. {
  6.     int zmienna = 1;
  7.     int pomocnicza = 10;
  8.     if(zmienna > 0)
  9.     {
  10.         if((zmienna == 12-pomocnicza) && (zmienna <= 4))
  11.         {
  12.             printf("Warunek prawdziwy");
  13.         }
  14.         else
  15.         {
  16.             printf("Warunek bledny");
  17.         }
  18.     }
  19.     else if(zmienna < 0)
  20.     {
  21.         if(zmienna <= -13 && zmienna >= -43)
  22.         {
  23.             printf("Drugi warunek");
  24.         }
  25.         else
  26.         {
  27.             printf("Znowu zle");
  28.         }
  29.     }
  30.     else
  31.     {
  32.         printf("Inna wartosc");
  33.     }
  34.     return 0;
  35. }

Tak samo sytuacja wygląda z innymi typami zmiennych jak char, boolean, long, float, double itp.

Należy także pamiętać, że w przypadku wejścia do któregoś z warunków, żaden następny nie będzie sprawdzany. 

Można to zaobserwować na następującym przykładzie. Gdzie warunek będzie sprawdzany w osobnej funkcji:

  1. int CheckValue(int var, int ref)
  2. {
  3.     printf("Spradzam warunek dla %d\r\n", ref);
  4.     if(var == ref)
  5.     {
  6.         return 1;
  7.     }
  8.     return 0;
  9. }
  10.  
  11. int main()
  12. {
  13.     int zmienna = 3;
  14.  
  15.     if(CheckValue(zmienna, 1) == 1)
  16.     {
  17.         printf("if..\r\n");
  18.     }
  19.     else if(CheckValue(zmienna, 3) == 1)
  20.     {
  21.         printf("else if 1..\r\n");
  22.     }
  23.     else if(CheckValue(zmienna, 5) == 1)
  24.     {
  25.         printf("else if 2..\r\n");
  26.     }
  27.     else
  28.     {
  29.         printf("else..\r\n");
  30.     }
  31.     return 0;
  32. }

Po wywołaniu funkcji zostanie zwrócona następująca informacja:

  1. Spradzam warunek dla 1
  2. Spradzam warunek dla 3
  3. else if 1..

Czyli sprawdzone zostały pierwsze dwa warunki ponieważ, druga instrukcja była poprawna. 

Kolejnym elementem o jakim należy pamiętać to wywoływanie kilku warunków z jednej instrukcji. Ma to głównie znaczenie kiedy w instrukcji wywoływana jest jakaś zmiana. Czyli oprócz sprawdzenia warunku ustawiamy jakieś parametry (czego oczywiście nie powinno się robić). Wprowadzę małą zmianę w powyższym programie:

  1. #include <stdio.h>
  2.  
  3. int CheckValue(int var, int ref)
  4. {
  5.     printf("Spradzam warunek dla %d\r\n", ref);
  6.     if(var == ref)
  7.     {
  8.         return 1;
  9.     }
  10.     return 0;
  11. }
  12.  
  13. int main()
  14. {
  15.     int zmienna = 3;
  16.  
  17.     if((CheckValue(zmienna, 1) == 1) && (CheckValue(zmienna, 5) == 1))
  18.     {
  19.         printf("if..\r\n");
  20.     }
  21.     else if(CheckValue(zmienna, 3) == 1 && (CheckValue(zmienna, 4) == 1))
  22.     {
  23.         printf("else if 1..\r\n");
  24.     }
  25.     else if(CheckValue(zmienna, 5) == 1)
  26.     {
  27.         printf("else if 2..\r\n");
  28.     }
  29.     else
  30.     {
  31.         printf("else..\r\n");
  32.     }
  33.     return 0;
  34. }

W odpowiedzi dostaję:

  1. Spradzam warunek dla 1
  2. Spradzam warunek dla 3
  3. Spradzam warunek dla 4
  4. Spradzam warunek dla 5
  5. else..

Jak widać warunków do sprawdzenia do wejścia do instrukcji else było 5, natomiast zostały sprawdzone tylko 4. Stało się tak ponieważ w pierwszej instrukcji if, po sprawdzeniu pierwszego warunku, który był nieprawdziwy nie było sensu sprawdzać drugiego. Zastosowano tam operator &&, dla którego oba warunki muszą być poprawne, by całe wyrażenie było prawdziwe. 

Podobnie wygląda sytuacja z operatorem ||. W takim przypadku sprawdzony będzie drugi warunek tylko gdy pierwszy okaże się nieprawdziwy.

Należy także pamiętać o stosowaniu nawiasów klamrowych. Oprócz poprawy czytelności kodu, pozwala na obrazowe stwierdzenie która część kodu ma się wykonać w instrukcji. Jeśli go zabraknie tylko jedna linia po instrukcja zostanie wykonana dla spełnionego warunku. Reszta będzie się wykonywać za każdym razem.

  1. int main()
  2. {
  3.     int zmienna = 3;
  4.  
  5.     if(zmienna == 3)
  6.         printf("w intruckji if\r\n");;
  7.    
  8.     if(zmienna == 5)
  9.         printf("w intruckji if2\r\n");
  10.         printf("za intruckja if2\r\n");
  11.     return 0;
  12. }

W przypadku konstrukcji zawierającej dodatkowe warunki else if, taka operacja się nie uda. Ponieważ zostanie zgłoszony błąd kompilacji. Przez brak nawiasów klamrowych, kompilator nie widzi, w którym miejscu instrukcja if się zaczyna. Taki problem nie wystąpi gdy każdy z instrukcji będzie zawierał tylko jedną operację.

  1. #include <stdio.h>
  2.  
  3. int main()
  4. {
  5.     int zmienna = 3;
  6.  
  7.     if(zmienna == 3)
  8.         printf("w intruckji if\r\n");
  9.     else if(zmienna == 7)
  10.         printf("w intruckji zz\r\n");
  11.     else if(zmienna == 5)
  12.         printf("w intruckji if2\r\n");
  13.         printf("za intruckja if2\r\n");
  14.     return 0;
  15. }

Warto zwracać także uwagę na sprawdzanie zmiennej operatorem ==. Bardzo łatwo wprowadzić następujący błąd do kodu:

  1. if(zmienna = 3) {
  2.    printf("w intruckji if\r\n");
  3. }

Dla takiego wyrażenia warunek będzie zawsze spełniony, ponieważ do zmiennej jest przypisana wartość. Kompilator może to zauważy i zwróci ostrzeżenie (warning), ale nie każdy. Można się przed tym uchronić wykonując sprawdzenie warunku w następujący sposób:

  1. if(3 = zmienna) {
  2.     printf("w intruckji if\r\n");
  3. }

Spowoduje to wywołanie błędu podczas kompilacji. Ponieważ do wartości stałej zostaje przypisana wartość zmiennej:

  1. main.c:25:10: error: lvalue required as left operand of assignment
  2.    25 |     if(3 = zmienna) {
  3.       |          ^