Kapitel 3
Kontrolstrukturer

Kurt Nørmark
Institut for Datalogi, Aalborg Universitet


Sammendrag
Forrige lektion Næste lektion
Stikord Referencer Indhold
I denne lektion gennemgår vi forskellige former for konstrolstrukturer, i hovedsagen forskellige former for selektion og iteration. Som en vigtig og relevant detalje, ser vi også på logiske udtryk, som styrer de fleste kontrolstrukturer.


Kontrolstrukturer - Motivation og Oversigt

Oversigt over basale kommandoer
Slide Indhold Stikord
Referencer 

Vi starter med en oversigt over de kommandoer vi har mødt indtil nu

  • Assignment

    • Udtryk med en assignment operator efterfulgt af semicolon

  • Printf og scanf kommandoerne

    • Disse bruges typisk som funktionskald efterfulgt af semicolon

  • Den tomme kommando

    • Blot et semicolon

Henvisning

Oversigt over konstrolstrukturer
Slide Indhold Stikord
Referencer 

Begrebet kontrolstruktur: En kontrolstruktur styrer og kontrollerer rækkefølgen af udførelsen af et antal kommandoer

  • Udvælgelse

    • Én kommando udvælges blandt flere mulige.

    • Udvælgelsen foretages typisk ud fra værdien af et logisk udtryk.

    • if (logiskUdtryk) kommando1; else kommando2;

  • Gentagelse

    • En kommando gentages et antal gange.

    • Antallet af gentagelser styres typisk af et logisk udtryk

    • while (logiskUdtryk) kommando;

  • Sekventiel kontrol

    • Kommandoer følger efter hinanden i den angivne rækkefølge

    • kommando1; kommando2;

  • Sammensætning

    • En antal kommandoer sammensættes til én enkelt kommando: en blok.

    • {kommando1; kommando2;}

Motivation: Primitiv kontrol med hop
Slide Indhold Stikord
Referencer 

Programmering med goto - før indførelsen af struktureret programmering

Program: Et uddrag af et C program med gotos.
  if (i <= j) goto p1;
  res = i;
  goto p2;
  p1: res = j;

  p2: printf("res: %d\n", res);

Program: Et helt C program med to goto kommandoer.
#include <stdio.h>

int main(void) {

  int i, j, res;
  printf("Enter two integers: ");
  scanf("%d %d", &i, &j);

  if (i <= j) goto p1;
  res = i;
  goto p2;
  p1: res = j;

  p2: printf("res: %d\n", res);
  
  return 0;
}

Program: Goto programmet reformuleret med en if-else kontrolstruktur.
#include <stdio.h>

int main(void) {

  int i, j, res;
  printf("Enter two integers: ");
  scanf("%d %d", &i, &j);

  if (i <= j)
    res = j;
  else 
    res = i;

  printf("res: %d\n", res);
  
  return 0;
}

Programmer med goto kommandoer kan være meget vanskelige af forstå.

Goto kommandoer er kun acceptable i undtagelsessituationer, eksempelvis for at komme ud af en 'dyb løkke'.


Logiske udtryk

Logiske udtryk
Slide Indhold Stikord
Referencer 

Begrebet logisk udtryk: Et logisk udtryk beregnes til en værdi i datatypen boolean.
Begrebet boolean: Datatypen boolean indeholder værdierne true og false.

Program: Et uddrag af et C program med logiske udtryk.
  int n = 6, result;
  
  n == 5
  n >= 5
  n != 5
  n >= 5 && n < 10
  result = n >= 5 && n < 10
  !(n >= 5 && n < 10)
  n < 5 || n >= 10

Henvisning

Program: De boolske udtryk vist i realistiske sammenhænge i et C program.
#include <stdio.h>

int main(void) {

  int n = 6, b, result;

  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);

  /* n is 10: */
  result = (n >= 5 && n < 10);             /* LOGISK ASSIGNMENT */
  printf("the result is %d\n %d", result, n);

  if ( !(n >= 5 && n < 10) == (n < 5 || n >= 10))
    printf("OK\n"); 
  else printf("Problems\n");
  
  return 0;
}

Program: Misforståede logiske udtryk.
#include <stdio.h>

int main(void) {

  int a = 7, b = 8, c = 6;
  
  /* Both a and b are greater than c */
  a && b > c;                 /* WRONG  */

  a > c && b > c;             /* Correct */

  
  /* Both a, b, and c are non-zero  */
  a, b, c != 0                /* WRONG  */

  a != 0 && b != 0 && c != 0  /* Correct  */


  /* The value of a is in between c and b */
  c <= a <= b;                /* WRONG  */

  c <= a && a <= b;           /* Correct */

 

  
  return 0;
}

I C repræsenteres false af en nulværdi, og true af en vilkårlig ikke-nulværdi

Opgave 3.2. Inden i eller uden for en cirkel

Det er ofte nyttigt at kunne afgøre, om et punkt i et koordinatsystem er placeret inden i eller udenfor en bestemt cirkel.

Skriv et program med tre doubles r, x og y.   r fortolkes som radius af en cirkel omkring punktet (0,0). x og y er koordinaterne (x, y) af et punkt.

Programmet skal afgøre om punktet (x, y) er placeret inden i cirklen, på cirkelperiferien, eller uden for cirklen. Der er altså tre tilfælde. I bedes have tre logiske udtryk, assignet til tre logiske variable, som afspejler de tre forskellige situationer.

Kan I lave én printf med brug af betingede udtryk (?:), der udskriver 'inden i'/'uden for' og 'på' cirklen, baseret på de logiske udtryks værdi?

Hint: Det kan være svært at ramme periferien eksakt, fordi vi regner med doubles. Derfor kan I antage at punktet er 'på periferien' hvis det er ganske tæt på periferien. Indfør en symbolsk konstant DELTA, der fortæller hvor meget vi ønsker at kunne afvige fra et "perfect hit".

Sandhedstabeller
Slide Indhold Stikord
Referencer 

Tabel. Sandhedstabel for not operatoren
A!A
truefalse
falsetrue
 

Tabel. Sandhedstabel for and operatoren
ABA && BA || B
truetruetruetrue
truefalsefalsetrue
falsetruefalsetrue
false falsefalsefalse
 

Tabel. Sandhedstabel for or operatoren
AB!(A && B)!A || !B
truetruefalsefalse
truefalsetruetrue
falsetruetruetrue
false falsetruetrue
 

Henvisninger

Prioriteter af logiske operatorer
Slide Indhold Stikord
Referencer 

Tabel.
NiveauOperatorerAssociativitet
15()      []      ->      .      ++postfix      --postfix left to right
14++prefix      --prefix      !      ~      sizeof(type)      +unary      -unary      &      * right to left
13*      /      %left to right
12+      -left to right
11<<      >>left to right
10<      <=      >      >=left to right
9==      !=left to right
8&left to right
7^left to right
6|left to right
5&&left to right
4||left to right
3?:right to left
2=      +=      -=      *=      /=      >>=      <<=      &=      ^=      |=right to left
1, left to right
 

Short Circuit evaluering
Slide Indhold Stikord
Referencer 

Direkte oversat 'kortsluttet beregning'

Begrebet short circuit evaluering: Short circuit evaluering betegner en beregning hvor visse operander ikke evalueres, idet deres værdi er uden betydning for resultatet

  • x && y

    • y beregnes kun hvis x er true

  • x || y

    • y beregnes kun hvis x er false

Henvisning

Short Circuit evaluering: eksempler
Slide Indhold Stikord
Referencer 

Vi viser eksempler på C programmer med short circuit evaluering

Program: Short circuit beregning i kombination med assignments.
#include <stdio.h>

int main(void) {

  int i = 0, j = 0,
      r1, r2, r3, r4;

  printf("i j  r*\n");

  /* Illustrerer short circuiting i urene udtryk. */
  /* Illustrer IKKE god programmeringspraksis.    */

  r1 = (i = 1) && (j = 2);
  printf("%d %d  %d\n", i, j, r1);  

  r2 = (i = 0) && (j = 3);
  printf("%d %d  %d\n", i, j, r2);  

  r3 = (i = 0 || (j = 4));     
  printf("%d %d  %d\n", i, j, r3);  

  r4 = (i = 2) || (j = 5);
  printf("%d %d  %d\n", i, j, r4);  

  return 0;
}

Program: Et ækvivalent program.
#include <stdio.h>

int main(void) {

  int i = 0, j = 0,
      r1, r2, r3, r4;

  printf("i j  r*\n");

  /* Illustrerer short circuiting i urene udtryk. */
  /* Illustrer IKKE god programmeringspraksis.    */

  r1 = (i = 1) && (j = 2);
  printf("%d %d  %d\n", i, j, r1);  

  r2 = (i = 0);
  printf("%d %d  %d\n", i, j, r2);  

  r3 = (i = 0 || (j = 4));     
  printf("%d %d  %d\n", i, j, r3);  

  r4 = (i = 2);
  printf("%d %d  %d\n", i, j, r4);  

  return 0;
}

Program: Output fra ovenstående programmer.
i j  r*
1 2  1
0 2  0
1 4  1
2 4  1

Program: Short circuit beregning som beskyttelse mod fejlberegning.
#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;
}

De øverste programmer er kunstige og konstruerede

Mønstret i det nederste program forekommer ofte i rigtige programmer

Opgave 3.3. Operator prioriteter i logiske udtryk

Denne opgaver giver dig træning i at anvende operator prioritering i logiske udtryk. Det er ikke nødvendigt at beregne værdierne af udtrykkene. Lad blot computeren foretage de faktiske beregninger.

Se på følgende C program:

#include <stdio.h>

int main(void){

  int a = 1, b = 2, c = 3;
  double x = 1.0;

  int res1, res2, res3, res4;

  res1 = a > b && c < x;
  res2 = a < ! b || ! ! a;
  res3 = a + b < ! c + c;
  res4 = a - x || b * c && b / a;

  printf("res1 = %d, res2 = %d, res3 = %d,  res4 = %d \n", 
	 res1, res2, res3, res4);

  return 0;
}

Sæt parenteres i de fire sammensatte, logiske udtryk, hvis værdier assignes til variablene res1, ..., res4. Ved at sætte parenteser bliver det klart, hvorledes de sammensatte udtryk beregnes. Vær sikker på at du anvender operator prioriteringerne i C, for at sætte parenteserne korrekt.

Check at overstående program, og dit modificerede program, er ækvivalente (giver det samme output når værdierne af res1, ..., res4 udskrives).


Sammensætning af kommandoer

Sammensætning
Slide Indhold Stikord
Referencer 

Begrebet blok: En sammensat kommando, også kaldet en blok, er en gruppering af kommandoer til én kommando, hvori der i starten kan forekomme erklæringer af variable

Syntax: En blok

{declaration-or-command-list}

Blokke er ofte nødvendige i forbindelse med udvælgende og gentagende kontrolstrukturer i C.

Blokke kan indlejres i hinanden.

Program: Tre indlejrede blokke med lokale erklæringer af heltal.
#include <stdio.h>

int main(void) {  

  int a = 5, b = 7, c;

  c = a + b;

  { 
    int a = 15, b = 17, c;

    {
      int a = 25, b = 27, c;
      c = a + b;  
      printf("Inner: c er %d\n", c);
    }

    c = a + b;  
    printf("Middle: c er %d\n", c);
  }   

  c = a + b;  
  printf("Outer: c er %d\n", c);
  
  return 0;
}   

Program: Program output.
Inner: c er 52
Middle: c er 32
Outer: c er 12

Henvisning


Udvælgelse af kommandoer

Udvælgelse med if (1)
Slide Indhold Stikord
Referencer 

En selektiv kontrolstruktur udvælger én kommando til udførelse blandt en mængde af muligheder

Struktureret Programmering

Syntax: En if-else kontrolstruktur.

if (logicalExpression)
  command1
else
  command2

Figur. Flow graf for if

  • Betydning af if-else:

    • Først beregnes det logiske udtryk

    • Hvis værdien er sand udføres command1

    • Hvis værdien er falsk udføres command2

Udvælgelse med if (2)
Slide Indhold Stikord
Referencer 

Else delen kan udelades, hvilket svarer til at command2 er tom på forrige side

Betinget udførelse af kommendo

Syntax: En if kontrolstruktur uden else

if (logicalExpression)
  command1

Figur. Flow graf for if uden else

Eksempler på if (1)
Slide Indhold Stikord
Referencer 

På denne side diskuterer vi en problematisk anvendelse af if

Program: To assignments til boolske konstanter i en if - unødvendig omstændeligt.
#include <stdio.h>

int main(void) {

  double x, y;
  int is_x_smaller_than_y;

  printf("Enter two real numbers: ");
  scanf("%lf %lf", &x, &y);

  /* Find out if x is less than y - in a primitive way ... */
  if (x < y)
    is_x_smaller_than_y = 1; 
  else
    is_x_smaller_than_y = 0; 

  /* Print result */
  if (is_x_smaller_than_y)
    printf("%f is smaller than %f\n", x, y);
  else
    printf("%f is greater than or equal to %f\n", x, y);

  return 0;
}

Program: Bedre program - med ét assignment til værdien af et logisk udtryk.
#include <stdio.h>

int main(void) {

  double x, y;
  int is_x_smaller_than_y;

  printf("Enter two real numbers: ");
  scanf("%lf %lf", &x, &y);

  /* Find out if x is less than y - the better way. The text book calls it a logical assignment. */
  is_x_smaller_than_y = (x < y);

  /* Print result */
  if (is_x_smaller_than_y)
    printf("%f is smaller than %f\n", x, y);
  else
    printf("%f is greater than or equal to %f\n", x, y);

  return 0;
}

Eksempler på if (2)
Slide Indhold Stikord
Referencer 

På denne side diskuterer vi forskellige coding styles af if

Program: Et program som beregner det største af to doubles - coding style.
#include <stdio.h>

int main(void) {

  double x, y, max;

  printf("Enter two real numbers: ");
  scanf("%lf %lf", &x, &y);

  /* Find the maximum of x and y */
  if (x < y)
    max = y;
  else
    max = x;

  printf("The maximum of x and y is %12.8f\n", max);
  
  return 0;
}

Program: En variant med blokke - alternativ 'coding style'.
#include <stdio.h>

int main(void) {

  double x, y, max;

  printf("Enter two real numbers: ");
  scanf("%lf %lf", &x, &y);

  /* Find the maximum of x and y */
  if (x < y){ 
    max = y;
  }
  else{ 
    max = x;
  }   

  printf("The maximum of x and y is %12.8f\n", max);
  
  return 0;
}

Program: Endnu en variant med blokke - alternativ 'coding style'.
#include <stdio.h>

int main(void) {

  double x, y, max;

  printf("Enter two real numbers: ");
  scanf("%lf %lf", &x, &y);

  /* Find the maximum of x and y */
  if (x < y)
  {   
    max = y;
  }
  else
  {   
    max = x;
  }      

  printf("The maximum of x and y is %12.8f\n", max);
  
  return 0;
}

Program: Et attraktivt alternativ - som ikke handler om coding style.
#include <stdio.h>

int main(void) {

  double x, y, max;

  printf("Enter two real numbers: ");
  scanf("%lf %lf", &x, &y);

  /* Find the maximum of x and y */
  max = (x < y) ? y : x;   

  printf("The maximum of x and y is %12.8f\n", max);
  
  return 0;
}

Henvisning

Vær altid konsekvent i din anvendelse if coding style

'Sekvens af if' kontra if-else
Slide Indhold Stikord
Referencer 

Brug af if-else i forhold til to if sætninger i sekvens

I tilfælde hvor to alternative udelukker hinanden - og hvor netop et alternativ ønskes udført - fortrækker vi en if-else

Program: Brug af if-else.
#include <stdio.h>

int main(void) {

  int i = 7, j = 7;

  if (i < j) 
    printf("i is less than j\n");
  else
    printf("i is greater than or equal to j\n");    

  return 0;
}

Program: Brug af to if sætninger i sekvens.
#include <stdio.h>

int main(void) {

  int i = 7, j = 7;

  if (i < j)  
    printf("i is less than j\n");
  if (i >= j)
    printf("i is greater than or equal to j\n");     

  return 0;
}

Program: Brug af to if sætninger i sekvens - variant nummer et.
#include <stdio.h>

int main(void) {

  int i = 7, j = 7;

  if (i <= j)   
    printf("i is less than j\n");
  if (i >= j)
    printf("i is greater than or equal to j\n");      

  return 0;
}

Program: Brug af to if sætninger i sekvens - variant nummer to.
#include <stdio.h>

int main(void) {

  int i = 7, j = 7;

  if (i < j)   
    printf("i is less than j\n");
  if (i > j)
    printf("i is greater than or equal to j\n");       

  return 0;
}

Program: Brug af to if sætninger i sekvens - med en ganske lille ændring.
#include <stdio.h>

int main(void) {

  int i = 7, j = 7;

  if (i < j);
    printf("i is less than j\n");
  if (i >= j);
    printf("i is greater than or equal to j\n");    

  return 0;
}

I en if-else ved vi at netop en af grenene udføres

I en sekvens af if sætninger har vi ikke en tilsvarende garanti

'Dangling else' problemet
Slide Indhold Stikord
Referencer 

Hvis if og if-else kontrolstrukturer indlejres i hinanden kan der opstå tvetydighedsproblemer

Program: Illustration af dangling else problemet.
#include <stdio.h>

int main(void) {

  int a = 3, b = 4;

  if (a == 1)
    if (b == 2)
      printf("A\n");
    else 
      printf("B\n"); 

  if (a == 1) 
    if (b == 2)
      printf("C\n");
  else 
    printf("D\n"); 

  if (a == 1){ 
    if (b == 2)
      printf("E\n");} 
  else 
    printf("F\n"); 
  
  return 0;
}

Program: Output fra ovenstående program.
F

En else knytter sig altid til den inderste if.

Det kan anbefales at bruge sammensætning med {...} hvis man er i tvivl om fortolkningen.

Udvælgelse med switch (1)
Slide Indhold Stikord
Referencer 

Syntax: Opbygningen af en switch kontrolstruktur.

switch (expression) {
  case const1: command-list1
  case const2: command-list2
  ...
  default: command-list  
}

  • Betydning:

    • Udtrykket beregnes - skal være et heltal eller heltalsagtigt

    • Hvis værdien svarer til en af konstanterne, flyttes kontrollen til den tilsvarende kommando. De efterfølgende cases udføres.

    • Hvis værdien ikke svarer til en af konstanterne, og hvis der er et default tilfælde, flyttes kontrollen til default kommandoen

    • Hvis værdien ikke svarer til en af konstanterne, og hvis der ikke er et default tilfælde, flyttes kontrollen til afslutningen af switchen

  • Begrænsning:

    • En bestemt case må højst optræde én gang i en switch

Udvælgelse med switch (2)
Slide Indhold Stikord
Referencer 

Programeksempler med switch

Program: Et program der udskriver en ECTS karakter fra en dansk 7-trins karakter.
#include <stdio.h>

int main(void) {
  int grade7;
  
  /* Prompt for input */
  printf("Enter Danish 7 step grade: ");
  scanf("%d", &grade7);

  /* Find and print the corresponding ECTS grade */
  printf("The corresponding ECTS grade is: ");
  switch(grade7){
    case 12: 
      printf("A"); break;
    case 10: 
      printf("B"); break;
    case 7: 
      printf("C"); break;
    case 4: 
      printf("D"); break;
    case 2: 
      printf("E"); break;
    case 0: 
      printf("Fx"); break;
    case -3: 
      printf("F"); break;
    default: 
      printf("Illegal");
  }
  printf("\n");
  
  return 0;
}

Program: Et program konverterer en 13 skala karakter til 7-trin skalaen.
#include <stdio.h>

int main(void) {
  int grade7, grade13, legal13;
  
  /* Prompt for input */
  printf("Enter Danish 13 scale grade: ");
  scanf("%d", &grade13);

  /* Find the corresponding 7 step grade */
  legal13 = 1;
  switch(grade13){
    case 13: case 11: 
      grade7 = 12; break;
    case 10: 
      grade7 = 10; break;
    case 9: case 8: 
      grade7 = 7; break;
    case 7: 
      grade7 = 4; break;
    case 6: 
      grade7 = 2; break;
    case 5: case 3: 
      grade7 = 0; break;
    case 0: 
      grade7 = -3; break;
    default: 
      legal13 = 0;
  }

  /* Print the result */
  if (legal13)
    printf("The 13 scale grade %d corresponds "  
           "to the 7 step grade %d\n",
           grade13, grade7);
  else
    printf("The 13 scale grade %d is illegal\n");

  
  return 0;
}

Program: Et program der beregner antal dage i en måned.
#include <stdio.h>
#include <stdlib.h>

int main(void) {

  int month, numberOfDays, leapYear;

  printf("Enter a month - a number between 1 and 12: ");
  scanf("%d", &month);
  printf("Is it a leap year (1) or not (0): ");
  scanf("%d", &leapYear);

  switch(month){
    case 1: case 3: case 5: case 7: case 8: case 10: case 12: 
      numberOfDays = 31; break;
    case 4: case 6: case 9: case 11: 
      numberOfDays = 30; break;
    case 2:
      if (leapYear) 
         numberOfDays = 29; 
      else 
         numberOfDays = 28;
      break;
    default: exit(-1);  /* Stop the program */
  } 

  printf("There are %d days in month %d\n", numberOfDays, month);

  return 0;
}

Vi ønsker næsten altid at afslutte et tilfælde i en switch med break

If-else kæder
Slide Indhold Stikord
Referencer 

En if-else kæde er en if-else kontrolstruktur, hvor else-delen igen kan være en if-else struktur

Bogen kalder if-else kæder for multiple alternative decision forms

Program: Et program med en if-else kæde der løser en andengradsligning.
#include <stdio.h>
#include <math.h>

int main(void) {
  
  double a, b, c, discriminant;

  printf("Enter coeficients a, b, and c: ");
  scanf("%lf %lf %lf", &a, &b, &c);

  discriminant = b * b - 4 * a * c;

  if (discriminant < 0)
    printf("No roots\n");
  else if (discriminant == 0)
    printf("One root: %f\n", -b/(2*a));
  else 
    printf("Two roots: %f and %f\n",
           (-b + sqrt(discriminant))/(2*a), 
           (-b - sqrt(discriminant))/(2*a) );  
}

Henvisning

Program: Et program med en if-else kæde der beregner beregner en 13-skala karakter ud fra et antal procentpoint.
#include <stdio.h>

int main(void) {

  int percent, grade;

  printf("How many percent? ");
  scanf("%d",&percent);

  if (percent >= 90)
    grade = 11;
  else if (percent >= 82)
    grade = 10;
  else if (percent >= 74)
    grade = 9;
  else if (percent >= 66)
    grade = 8;
  else if (percent >= 58)
    grade = 7;
  else if (percent >= 50)
    grade = 6;
  else if (percent >= 40)
    grade = 5;
  else if (percent >= 10)
    grade = 3;
  else grade = 0; 

  printf("%d percent corresponds to the Danish grade %d\n\n", 
          percent, grade);
  
  return 0;
}

Program: Alternativt og uønsket layout af if-else kæde.
#include <stdio.h>

int main(void) {

  int percent, grade;

  printf("How many percent? ");
  scanf("%d",&percent);

  if (percent >= 90)
   grade = 11;
  else if (percent >= 82)
        grade = 10;
       else if (percent >= 74)
             grade = 9;
            else if (percent >= 66)
                  grade = 8;
                 else if (percent >= 58)
                       grade = 7;
                      else if (percent >= 50)
                            grade = 6;
                           else if (percent >= 40)
                                 grade = 5;
                                else if (percent >= 10)
                                      grade = 3;
                                     else grade = 0; 

  printf("%d percent corresponds to the Danish grade %d\n\n", 
          percent, grade);
  
  return 0;
}

En if-else kæde kan generelt ikke programmeres med en switch kontrolstruktur

Opgave 3.4. pH værdier

I denne opgave antages det, at du lige har løst self-check opgave 3 side 236 i lærebogen Problem Solving and Program Design in C, eighth edition.

Målet med opgaven er at træne din evne til at arbejde med nestede if-else konstrolstrukturer, herunder if-else kæder (multiple alternative if statements).

Sammenlign din løsning med følgende if-else kæde (som bogen kalder en multiple-alternative if):

  if (ph <= 2)
     printf("Very acidic");  
  else if (ph < 7) 
     printf("Acidic");       
  else if (ph == 7)
     printf("Neutral");      
  else if (ph < 12)
     printf("Alkaline");     
  else 
     printf("Very alkaline");

Er ovenstående if-else kæde ækvivalent med din løsning på bogens opgave? Som en hjælp til afgørelsen, skriv en kommentar efter hvert printf kald som viser præcist, for hvilket interval pH værdier udskriften er gældende. Du skal være meget omhyggelig og systematisk - ellers laver du let en fejl.

Observationer om if-else kæder
Slide Indhold Stikord
Referencer 

  • En if-else kæde i forhold til switch:

    • En if-else kæde kan generelt ikke programmeres med en switch kontrolstruktur

    • En switch kan altid programmeres med en if-else kæde, men if-else kæden vil som regel være mindre effektiv

  • Rækkefølge af tilfældene i en if-else kæde:

    • De mest specielle tilfælde kommer før de mere generelle tilfælde

  • Viden som oparbejdes i en if-else kæde:

    • I en given udvalgt kommando vides at det tilhørende udtryk er beregnet til true, og at alle foregående udtryk er beregnede til false

Betingede udtryk
Slide Indhold Stikord
Referencer 

I C findes en betinget operator med med tre operander som modsvarer en if-else kontrol struktur.

En forekomst af en betinget operator er et udtryk, hvor imod en forekomst af if-else er en kommando.

Syntax: Opbygningen af den betingede operator i C.

logicalExpression ? expression1 : expression2

  • Betydning af et betinget udtryk:

    • Først beregnes logicalExpresssion

    • Hvis værdien er sand beregnes expression1 ellers beregnes expression2, hvorefter den udregnede værdi returneres

Program: Et program der bestemmer fortegnet af et tal.
#include <stdio.h>

int main(void) {

  int x;

  printf("Enter an integer: ");
  scanf("%d", &x);

  printf("The sign of %d is %s\n\n", 
         x,
         x < 0 ? "negative" : x == 0 ? "neutral" : "positive");
  
  return 0;
}

Program: Et ækvivalet program - med parenteser i udtrykket.
#include <stdio.h>

int main(void) {

  int x;

  printf("Enter an integer: ");
  scanf("%d", &x);

  printf("The sign of %d is %s\n\n", 
         x,
         (x < 0) ? "negative" : ((x == 0) ? "neutral" : "positive")
        );
  
  return 0;
}

Henvisninger

Opgave 3.5. Timer, minutter og sekunder - igen

Denne opgave er en fortsættelse af en tidligere opgave, hvor vi konverterede hele sekunder til uger, dage, timer, minutter og sekunder efter sædvanlige principper. I denne opgave begrænser vi os til timer, minutter og sekunder (vi dropper altså interessen for uger og dage).

Målet med opgaven er at træne dig i at bruge af if-else kæder, if'er i sekvens og betingede udtryk (med ?: operatoren). Målet er endvidere at opdele et lidt større program i mindre og markerede dele inden for main.

Det er sjusket og utilfredsstillende når det oprindelige program giver output som dette:

  • 75 sekunder svarer til 0 timer, 1 minutter og 15 sekunder
  • 3700 sekunder svarer til 1 timer, 1 minutter og 40 sekunder
  • 55 sekunder svarer til 0 timer, 0 minutter og 55 sekunder
  • 3661 sekunder svarer til 1 timer, 1 minutter og 1 sekunder

Vi ønsker at blive fri for '0 timer' og '0 minutter'. Endvidere ønsker vi korrekt angivelse af ental og flertal. Derfor foretrækker vi et program der giver følgende output:

  • 75 sekunder svarer til 1 minut og 15 sekunder
  • 3700 sekunder svarer til 1 time, 1 minut og 40 sekunder
  • 55 sekunder svarer til 55 sekunder
  • 3661 sekunder svarer til 1 time, 1 minut og 1 sekund

Skriv en ny version af programmet, som opfylder disse krav.

Overvej ombyggelig brugen af if-else kæder kontra sekvenser af if kontra betingede udtryk med brug af den ternære operator ?:

Flere opgaver
Slide Indhold Stikord
Referencer 

Opgave 3.6. Ordningen af betingelser i en if-else kæde

Vi har på en tidligere slide set på følgende program med en if-else kæde:

#include <stdio.h>

int main(void) {

  int percent, grade;

  printf("How many percent? ");
  scanf("%d",&percent);

  if (percent >= 90)
    grade = 11;
  else if (percent >= 82)
    grade = 10;
  else if (percent >= 74)
    grade = 9;
  else if (percent >= 66)
    grade = 8;
  else if (percent >= 58)
    grade = 7;
  else if (percent >= 50)
    grade = 6;
  else if (percent >= 40)
    grade = 5;
  else if (percent >= 10)
    grade = 3;
  else grade = 0; 

  printf("%d percent corresponds to the Danish grade %d\n\n", 
          percent, grade);
  
  return 0;
}

Nu bytter vi om på tilfældene i if-else kæden (dog bevarer vi else-delen):

#include <stdio.h>

int main(void) {

  int percent, grade;

  printf("How many percent? ");
  scanf("%d",&percent);

  if (percent >= 10)
    grade = 3;
  else if (percent >= 40)
    grade = 5;
  else if (percent >= 50)
    grade = 6;
  else if (percent >= 58)
    grade = 7;
  else if (percent >= 66)
    grade = 8;
  else if (percent >= 74)
    grade = 9;
  else if (percent >= 82)
    grade = 10;
  else if (percent >= 90)
    grade = 11;
  else grade = 0; 

  printf("%d percent corresponds to the Danish grade %d\n\n", 
          percent, grade);
  
  return 0;
}

Ændrer dette betydningen af programmet? Uddrag en generel tommelfingerregel for ordningen af de logiske udtryk i en if-else kæde.


Samlede referencer
Indhold Stikord
Assignment fra lektion 1
Operator prioriteringer i C
Video om logiske operatorer
Operator tabellen i C
Sandhedstabeller
En senere diskussion af 'scope' ud fra dette eksempel
Det betingede udtryk
Senere udgave som løser andengradsligningen i en parameterløs funktion
Video om betingede udtryk
Operator prioriterings og associeringstabel

 

Kapitel 3: Kontrolstrukturer
Kursets hjemmeside     Forfatteren's hjemmeside     Om frembringelsen af disse sider     Forrige lektion (top)     Næste lektion (top)     Forrige lektion (bund)     Næste lektion (bund)     
Genereret: 9. maj 2022, 13:58:27