3. Lektion

Denne lektion handler grundlæggende om Forgreninger

Emnerne behandles i lærebogen på siderne 100 til 133

Jeg starter med et program, vi har set på tidligere, det var det program, der talte op hvor mange tegn og bogstaver, der var i en sætning. Nu indføjer jeg en funktion, der også kan optælle, hvor mange ord der er i sætningen.

For at optælle antallet af ord, skal vi finde ud af hvor mange mellemrum, der er i teksten. Hver gang der optræder et mellemrum, skal der laves en forgrening, hvor der tilføjes en optælling af mellemrummene (= et afsluttet ord). Ved det direkte gennemløb optælles kun tegn incl. mellemrummene.

Vis et eksempel på en overskrift til et program.

Eksempel 1
#include <stdio.h> // Til printf()
#include <conio.h> // Til getche()

void main(void)
{
   int bogstavtal = 0;
   int ordtal = 1;
   char ch;
   printf("\nIndtast en sætning:\n"); // Indtast en tekst
   while ( (ch=getche()) != '\r' ) // Snup et tegn af gangen indtil RETURN
   {
      bogstavtal++;   // Tæl op antal gange løkken gennemløbes
      if ( ch == ' ' )
         ordtal++;
   }
   printf ("\nTeksten indholdt %d tegn og bogstaver", bogstavtal);
   printf("\nTeksten indeholdt %d ord", ordtal);
} // Slut på programmet

Ovenstående er et program med en enkelt forgrening. I næste eksempel får forgreningen tilføjet et alternativ, idet der anvendes else i konstruktionen.

Koderne i nedenstående eksempel virker kun i compilere, som arbejder i et DOS-vindue. Brug f.eks. programmet fra øvelse 2 fra 2. lektion til at finde en passende værdi til at erstatte med i den C-compiler du anvender. Værdien skal være en, som sætter en fuldt udfyldt firkant som et tegn.

Følgende program tegner et skakbræt på skærmen. Koden kan tolkes således: (x + y) % 2 giver restværdien efter heltalsdivision med 2. Dvs. at (x + y) %2 hver anden gang i en bestemt linie giver værdien 1, altså != 0. I den næste linie vil (x + y) % 2 give 1 forskudt 1 felt i forhold til felterne i den foregående linie osv.

Eksempel 2
void main(void)
{
   int x, y;
   char a;
   printf("\n");
   for ( y = 1; y < 24; y++)
   {
      for ( x = 1; x < 24; x++)
         if ( (x+y)%2 == 0 )
            printf("\xdb\xdb");
    // Bemærk disse koder virker kun med Cpp 5.02
         else
            printf(" ");
      printf("\n");
   }  // Slut på ydre tælleløkke
a = getch();
}

Det er også muligt at indlejre forgreninger i forgreninger. I eksempel 3 indlejres en if - sætning i en if - sætning. Denne gang går opgaven ud på at sætter felter af som to diagonaler, der skal krydse hinanden ned over skærmen. Da der kun skal sættes 2 tegn af i hver linie, skal vi bruge en if - sætning til hvert af tegnene. Det ene tegn skal sættes hver gang x == y, det andet skal sættes når x == (24 - y), idet jeg har sat en tælle-løkke til at gentage 23 gange, og y til at starte med værdien 1.


Eksempel 3
void main(void)
{
   int x, y;
   char a;
   
        printf("\n");
   for ( y = 1; y < 24; y++)
   {
      for ( x = 1; x < 24; x++)
         if (x == y)
            printf("\xdb");
         else
           if ( x == (24 - y))
              printf("\xdb");
           else
              printf("\xb0");
      printf("\n");
   }
   a = getch();
}

Lads os prøve at se på Kryds-programmet en gang til, der må kunne spares noget kode.

Der findes en række logiske operatorer, vi kan tage fat i. Det er:

||        = or (eller)

&&   = and (og)

! =     = not ( ikke eller forskellig fra)

Der begyndes med kommandoen til en ny linie fra eksempel 3

printf("\n");
for ( y = 1; y < 24; y++)
{
   for ( x = 1; x < 24; x++)// Ændringen ligger i næste linie
      if (x == y || x == 24-y )
         printf("\xdb");
      else
         printf("\xb0");
   printf("\n");
}
a = getch();

Det gjorde koden lidt fiksere og en compilering vil vise at programmet er blevet lidt mindre.

Næste udfordring går på at bruge multiple choice

Hvordan det virker kan vises ved at lave en lille regnemaskine. Vi skal her have et valg for hver regneart, som maskinen skal kunne behandle.

Eksempel 4
void main(void)
{
   float num1 = 1.0, num2 = 1.0;
   char op;

   while ( !(num1 == 0.0 && num2 == 0.0) )
   {
      printf("\n\nIndtast et tal, et regnetegn og et tal \n");
      scanf("%f %c %f", &num1, &op, &num2);
      if (op == '+') 
// Her lægges tal sammen
         printf(" = %f", num1 + num2);
      else if (op == '-') 
// Her trækkes tal fra hinanden
              printf(" = %f", num1 - num2);
           else if (op == '*')
// Her ganges
                   printf(" = %f", num1 * num2);
                else if (op == '/') 
// Her divideres
                        printf(" = %f", num1 / num2);
                     else
                        printf("Du har indtastet en ulovlig operator");
                                                           // Tal pænt til brugeren, hvis der laves fejl!
   } // Slut på "Så længe som"
}   // Slut på programmet

Konstruktionen af regnemaskinen kan ændres, idet der findes en kommando, som er kortere at anvende end alle if - konstruktionerne indlejret i hinanden. Kommandoen svarer til CASE . . OF i Pascal. I C hedder den switch. Hvert valg i switch skal derpå markeres med det reserverede ord case.

Eksempel 5
void main(void)
{
   float num1 = 1.0, num2 = 1.0;
   char op;

   while ( !(num1 == 0.0 && num2 == 0.0) )
   {
      printf("\n\nIndtast et tal, et regnetegn og et tal \n");
      scanf("%f %c %f", &num1, &op, &num2);
      switch (op)
      {
         case '+' : printf(" = %f", num1 + num2);
                    break;
         case '-' :
printf(" = %f", num1 + num2);
                    break;
         case '*' : // Tilføj f.eks. case 'x' :
                    printf(" = %f", num1 * num2);
                    break;
         case '/' : // Tilføj f.eks. case '\' :
                    printf(" = %f", num1 / num2);
                    break;
         default :
                    printf("Du har indtastet en ulovlig operator");
      } // Slut på switch
   } // Slut på while
} // Slut på programmet

Bemærk, at efter CASE kommer der et : (kolon) og der er ingen { (Tuborg-klamme) om de sætninger, der følger efter CASE. Til gengæld er der en BREAK-kommando for at få programmet til at forlade SWITCH efter at et alternativ er udført.

Ud over de ovenfor nævnte operatorer findes der i C også en såkaldt Conditional operator.

I modsætning til de fleste andre operatorer tager denne operator tre argumenter:

Condition ? udtryk1 : udtryk2;

f.eks. max = ( num1 > num2 ) ? num1 : num2;

resultatet af denne operation er det samme som traditionelt at skrive:

if (num1 > num2)
max = num1;
else
max = num2;

Vi kan med denne kommando elegant lave en funktion, der altid giver den numeriske værdi af et tal:

Abs = (num < 0) ? -num : num;

Når I nu har lært at lave forgreninger skal I til at tænke lidt mere over konstruktion af et program. Udviklingen at et program består af 3 trin. Vi kan kalde det mini-SPU.

  1. Design af interface, dvs. hvad skal programmet udføre, hvad skal vi have ud af programmet, hvilke data skal det forsynes med for at kunne levere resultatet. Hvordan skal det bede om inddata og hvordan skal de præsenteres. Hvilke algoritmer skal anvendes til beregningen (arbejdet).
  2. Indtastning af kildekoden.
  3. Test af programmet, her gælder det om at opstille et system, så alle forgreninger = alle betingelser bliver afprøvet.

Øvelse 1
Prøv at ændre programmet fra eksempel 2, således at der tilføjes bogstaverne A, B, C . . . . osv. vandret over skatbrættet og vandret under dette. Desuden tilføjes tal lodret på begge sider af brættet.

Øvelse 2
Konstruer et program som kan beregne om et indtastet årstal er et skudår.
Tip: Skudårsreglen er følgende: Et år er et skudår, hvis 4 går op i årstallet og 100 ikke går op i årstallet. Dog er året også et skudår, hvis 400 går op i årstallet.
Forslag til testdata: 1836, 1956, 2000 er skudår, 1900, 1903 og 2100 er ikke skudår.

Eksempler og løsningerne kan hentes her.
Eksempel 1
Eksempel 2
Eksempel 3
Eksempel 4
Eksempel 5
Øvelse 1
Øvelse 2a
Øvelse 2b