![]() ![]() ![]() | Kontrolstrukturer |
Logiske udtryk bruges til at styre udvælgelse og gentagelse. Derfor er det vigtigt at vi har god styr på logiske udtryk. Dette vil vi få i dette afsnit.
|
6.1. Logiske udtryk
Indhold Op Forrige Næste Slide Aggregerede slides Stikord Programindeks Opgaveindeks
Logiske udtryk kan naturligt sammenlignes med aritmetiske udtryk. Aritmetiske udtryk beregnes til talværdier. Logiske udtryk beregnes til sandhedsværdier, enten sand eller falsk (true eller false på engelsk). På samme måde som vi har set aritmetiske operatorer vil i dette afsnit studere logiske operatorer, som returnerer sandhedsværdier.
Vi skal vænne os til at håndtere sandhedsværdier på samme måde som vi håndterer tal, tegn, mv. Vi kan putte sandhedsværdier i variable, vi kan sammenligne dem mv. For en del af jer tager det måske lidt tid inden I finder den rette og naturlige melodi for håndteringen af sandhedsværdier.
|
Her følger en række eksempler på logiske udtryk, som alle anvender heltalsvariablen n. Eksemplerne er vist inden for rammerne af et komplet C program i program 6.2.
1 2 3 4 5 6 7 8 | int n = 6; n == 5 n >= 5 n != 5 n >= 5 && n < 10 !(n >= 5 && n < 10) n < 5 || n >= 10 | |||
|
Først tester vi om n er lig med 5. == er altså en lighedoperator, som her returnerer false, idet n har værdien 6. Bemærk den afgørende forskel på assignment operatoren = og lighedsoperatoren ==. I anden linie tester vi om n er større end eller lig med 5. Dette er sandt. I tredje linie tester vi om n er forskellig fra 5. Dette er også sandt. I fjerde line tester vi om n er større eller lig med 5 og mindre end 10. Bemærk && svarer til 'logisk and'. (Se afsnit 6.2). Værdien er true igen. Udråbstegnet foran det tilsvarende udtryk betyder 'not', og det negerer altså værdien true til false. Det sidste logiske udtryk fortæller hvorvidt n er mindre end 5 eller større eller lig med 10. Når n stadig er 6 er dette naturligvis falsk. || betyder altså 'logisk eller'.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 | #include <stdio.h> int main(void) { int n = 6, b; printf("%d\n", n == 5); if (n >= 5) printf("stor\n"); else printf("lille\n"); b = n != 5; printf("%d\n", b); while (n >= 5 && n < 10) n++; printf("%d\n", n); if ( !(n >= 5 && n < 10) == (n < 5 || n >= 10)) printf("OK\n"); else printf("Problems\n"); return 0; } | |||
|
Nedenstående er en vigtig detalje i C. Nul står for false, og ikke-nulværdier står alle for true.
I C repræsenteres false af en nulværdi, og true af en vilkårlig ikke-nulværdi |
6.2. Sandhedstabeller
Indhold Op Forrige Næste Slide Aggregerede slides Stikord Programindeks Opgaveindeks
Nu hvor vi er igang med at diskutere logiske udtryk benytter vi lejligheden til præcise definitioner af negering (not), konjunktion (and) og disjunktion (or) via sandhedstabellerne i hhv. tabel 6.1, tabel 6.2 og tabel 6.3. Negering håndteres af ! operatoren i C. Tilsvarende hedder and operatoren && i C, og or operatoren hedder ||.
Da der kun findes to forskellige sandhedsværdier er det let at tabellægge alle forskellige muligheder for input og output af de nævnte operatorer. Bemærk her forskellen til heltal. Da der findes uendelig mange forskellige heltalsværdier vil tilsvarende definitioner af +, -, * og / være umulig.
A | !A |
true | false |
false | true |
Tabel 6.1 Sandhedstabel for not operatoren |
A | B | A && B | A || B |
true | true | true | true |
true | false | false | true |
false | true | false | true |
false | false | false | false |
Tabel 6.2 Sandhedstabel for and operatoren |
A | B | !(A && B) | !A || !B |
true | true | false | false |
true | false | true | true |
false | true | true | true |
false | false | true | true |
Tabel 6.3 Sandhedstabel for or operatoren |
Bemærk her at tabel 6.3 faktisk beviser DeMorgans boolske lov, som på et mere matematisk sprog siger at
I slide materialet viser vi en særlig udgave af operatorprioriteringstabellen i C, hvor de logiske og de sammenlignende operatorer er fremhævet. Se slide siden.
6.3. Short Circuit evaluering
Indhold Op Forrige Næste Slide Aggregerede slides Stikord Programindeks Opgaveindeks
Vi vil nu beskæftige os med nogle binære, logiske operatorer, som under nogle omstændigheder ikke vil beregne værdien af den højre operand.
Direkte oversat 'kortsluttet beregning' |
|
|
6.4. Short Circuit evaluering: eksempler
Indhold Op Forrige Næste Slide Aggregerede slides Stikord Programindeks Opgaveindeks
Vi ser først på et eksempel, som er ganske kunstig, men dog illustrativ. Dernæst, i program 6.6 følger et 'real life' eksempel.
Vi viser eksempler på C programmer med short circuit evaluering |
Herunder ses en række assignment operatorer som indgår i logiske udtryk. Dette kan lade sig gøre i C idet assignment operatorer returnerer en værdi, ligesom alle andre operatorer. Dette diskuterede vi i kapitel 3. En anden essentiel observation for nedenstående er at tallet nul spiller rollen som sandhedsværdien false, og at andre tal spiller rollen som true. Dette blev diskuteret i afsnit 6.1.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 | #include <stdio.h> int main(void) { int i = 0, j = 0; (i = 1) && (j = 2); printf("%d %d\n", i, j); (i = 0) && (j = 3); printf("%d %d\n", i, j); i = 0 || (j = 4); printf("%d %d\n", i, j); (i = 2) || (j = 5); printf("%d %d\n", i, j); return 0; } | |||
|
De to første assignments udføres begge, idet værdien af den første er 1 (true). Af de to næste assignment udføres kun det første. Årsagen er at i assignes til 0, som er false, hvilket forårsager undertrykkelse af beregningen af højre operand af &&. Det næste assignment skal fortolkes som i = (0 || (j = 4)). Husk igen af 0 er false. Højre operand af || skal derfor beregnes, jf. reglerne fra afsnit 6.3. Endelig gennemføres assignmentet til j ikke i sidste røde linie, idet venstre operand beregnes til 2 (true).
Med ovenstående observationer er program 6.4 ækvivalent med program 6.3.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 | #include <stdio.h> int main(void) { int i = 0, j = 0; (i = 1) && (j = 2); printf("%d %d\n", i, j); (i = 0); printf("%d %d\n", i, j); i = 0 || (j = 4); printf("%d %d\n", i, j); (i = 2); printf("%d %d\n", i, j); return 0; } | |||
|
Outputtet fra de to ovenstående (ækvivalente) programmer ses her:
1 2 3 4 | 1 2 0 2 1 4 2 4 | |||
|
Og nu til et mere dagligdagsprogram. I den røde linie ses et logisk udtryk, hvor den venstre operator beskytter den højre. Det skal forstås således at sqrt(x) kun bliver beregnet hvis x er ikke-negativ. Dette er helt essentielt for at undgå en regnefejl i kvadratrodsfunktionen sqrt, som jo kun kan tage ikke-negative parametre.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 | #include <math.h> #include <stdio.h> double sqrt(double); int main(void) { double x; printf("Enter a number: "); scanf("%lf", &x); if (x >= 0 && sqrt(x) <= 10) printf("x is positive, but less than or equal to 100.0\n"); else printf("x is negative or greater than 100.0\n"); return 0; } | |||
|
Prøvekør meget gerne programmet. Bemærk at på nogle C systemer skal der en ekstra option -lm på kompileren for at håndtere kvadratrodsfunktionen.