2. Lektion

Denne lektion handler om Løkker

Emnerne behandles i lærebogen på siderne  til 56 og 88

I første lektion blev der gjort mest ud af C's formaterede output-funktion.

I denne lektion startes med at vende tilbage til den formaterede input-funktion. Nemlig scanf(..). I modsætning til Pascal's input funktioner, må der ikke stå tekst i scanf(strengen). Hvis der skal være en input-prompt i et C-program, skal den skrives før scanf(). Følgende eksempel er en del af løsningen til den ene øvelsesopgave fra 1. lektion.

float aar, dage;
printf(\nIndtast din alder i aar: ");
scanf("%f", &aar);
dage = aar * 365;
printf("\nDu er %.1f dage gammel!", dage);

Bemærk, at der står & foran aar i scanf(), hvorfor der skal være et &, vendes der tilbage til i en senere lektion.

Lad os se på et eksempel mere:

printf(\nIndtast løbsnummer, bogstav for heat og opnået tid: ");
scanf("%d %c %f", &loeb, &heat, &tid);
printf(\nI løb nummer %d blev der", loeb);
printf(" opnået en tid på %f i heat %c!", tid, heat);

Ovenstående er en del af løsningen til øvelse 2, det virker kun, hvis loeb, heat og tid indtastes med blanktegn imellem tal og bogstaver. Hvis der skrives , (komma) ; (semikolon) eller lignende mellem input'ene, vil indtastningen give anledning til fejlmeldinger.

Man kan i de fleste tilfælde anvende følgende tre forskellige delinger mellem indtastningerne. Det er Mellemrum, Return og Tabulator, de vil alle blive opfattet som "white space".

Man bemærker, at der foran variabelnavnene i scanf var skrevet et &. Denne mærkelige regel betyder, at scanf() skal forsynes med adressen på variablen i stedet for variablens navn, sådan som man ville skrive i de fleste andre programsprog. Denne "særhed" ved C er en af de mere brugerfjentlige egenskaber. Man skal være en meget rutineret C-programmør for ikke at glemme et & af og til, når man anvender scanf().

Prøv at lave et program med følgende linier i en void main()

int num = 2;
printf(\nVaerdien af num er = %d og adressen er = %u ",num, &num);

Næste emne er løkker

Der startes med tælle-løkken for

Eksempel 1
/* ==================================== *\
 * File : Loop.c                        *
 * Påbegyndt : 12.2.01 Henning Karlby   *
 * Færdig :                             *
 * Ændret :                             *
\* ==================================== */
Ovenstående programhoved vil af pladshensyn blive udeladt i alle følgende eksempler.
/* ---- INCLUDES ------- */
#include <stdio.h>
#include <conio.h>

void main(void)
{
   int tal, ialt;
   char a;
   printf("---------- tal -------- ialt -");
   ialt = 0;
   for ( tal = 0; tal < 10; tal++)
   {
      ialt = ialt + tal;
      printf("\n tal = %5d, ialt = %5d", tal, ialt);
   }
   a = getch();
}

Løkken kan også skrives med nulstilling af begge variabler i kaldet til løkken, dette er igen en af "særhederne" ved C.

for ( tal = 0, ialt = 0; tal < 10; tal++)
{
   ialt = ialt + tal;
   printf("\n tal = %5d, ialt = %5d", tal, ialt);
}

Mange C-programmører ville skriv teksten således:

for ( tal = 0, ialt = 0; tal < 10; tal++) {
  ialt = ialt + tal;
  printf("\n tal = %5d, ialt = %5d", tal, ialt);}

Jeg syntes, at koden bliver mindre læsevenlig ved at spare to linier, som i ovenstående. Hvis man compilerer koden til de to eksempler, vil EXE-filen få samme størrelse, så der er ingen grund til at nedsætte læsevenligheden i kildekoden i dette tilfælde.

Det er også muligt at skrive sætningen:
ialt = ialt + tal;

kortere, følgende konstruktion også er gyldig:
ialt += tal;

Næste eksempel er en multiplikationstabel, for at lave det skal man "neste" løkker, dvs. sætte løkker inden i løkker.

Eksempel 2
#include <stdio.h>
void main(void)
{
   int rows, cols;
   char a;

   for(rows = 1; rows < 13; rows++) // Den ydre løkke
   {
      printf("\n");
      for(cols = 1; cols < 13; cols++) // Den indre løkke
         printf("%3d ", cols*rows );
   }
   a = getch();
}

Den næste løkke, der skal ses på, er while (så længe som)

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

void main(void)
{
   int tal = 0;

   printf("\nIndtast en sætning:\n"); // Indtast en tekst

   while ( getche() != '\r' )// Snup et tegn af gangen indtil RETURN
      tal++; // Tæl op antal gange løkken gennemløbes

   printf("\nTeksten indeholdt %d tegn og bogstaver", tal);//Udskriv resultat
} // Slut på programmet

Løkken i programmet kunne også have været skrevet således:
void main(void)
{
   int tal = 0;
   char ch = 'a';

   printf("\nIndtast en tekst og afslut med Return: ");
  
while ( ch != '\r' )
   {
      ch = getch();
      tal++;
      printf("%c", ch);
   }
   printf("\nTeksten indeholdt %d tegn og bogstaver", tal); //Udskriv resultat

}
Passer antallet af tegn der optælles, med det antal I har indtastet?

WHILE kan nestes i FOR og FOR kan nestes i WHILE osv.

Lad os vende tilbage til tælleløkken, den kan også laves med en helt anden form for løkke nemlig en do-løkke.

Eksempel 4
void main(void)
{
   char a;
   int tal = 0;
   int ialt = 0;
   
   do
   {
      ialt += tal;
      printf("\n tal = %5d, ialt = %5d", tal++, ialt);
   }
   while ( tal < 10 );
   a = getch();
}

Oversigt over løkker
Nu kender I de samme typer LOOP, som vi også havde i PASCAL, det var

1. Tælleløkken.
2. "Så længe som"-løkken, der vurderes inden løkken starter.
3. DO-løkken, der vurderes ved enden af løkken. (Repeat . . . . Until)

break anvendes til at stoppe gennemløbet af en løkke, mens continue sender programmet tilbage til starten af løkken.

Øvelse 1
Konstruer et program, hvor standardtegnsættets værdier fra 32 til 255 udskrives på skærmen.
Tip: Anvend f.eks. følgende udskriftslinie i en tælleløkke: printf("%3d = %c\t", n, n);

Øvelse 2
Konstruer et program, der viser, hvilken tast der er trykket på. Der skal vises både tegnets udseende og tegnets decimalværdi.

Øvelse 3
Konstruer et program, hvor man indtaster et tal, hvorefter tallets fakultet beregnes og udskrives. Sæt programmet til at køre i en uendelig løkke, som f.eks. kan stoppes ved indtastning af [Return], [y], [q] eller noget andet I selv vælger.
Tip: Fakultet til n er n!, dvs. 1*2*3 . . . . *n.

Eksempler og løsningerne kan hentes her
Eksempel 1
Eksempel 2
Eksempel 3
Eksempel 4
Øvelse 1
Øvelse 2
Øvelse 3