Index over opgaver i denne lektion   Alfabetisk indeks   Kursets hjemmeside   

Opgaver og løsninger
Introduktion til C


2.1   Et program der adderer tre heltal  

Denne opgave er lavet for at du skal undre dig over hvad du oplever i de givne programmer. Dernæst skal du forsøge at forstå det. Detaljerne fremgår ikke nødvendigvis af lærebogen. Når der bliver åbnet for løsningen til opgaven, vil du få mine korte forklaringer.

Se på følgende program, som adderer tre heltal:

#include <stdio.h>

int main(void) {

  int sum1 =    10  +   11  +  12,
      sum2  =  010 +   011 +  012,
      sum3  = 0x10 +  0x11 + 0x12;

  printf("sum1 =  %d\n", sum1);
  printf("sum2 =  %d\n", sum2);
  printf("sum3 =  %d\n", sum3);

  return 0;
}

Oversæt og kør programmet. Forklar programmets opførsel.

Kør dernæst programmet

#include <stdio.h>

int main(void) {

  int x, y, z, sum;

  printf("Enter three integers: ");
  scanf("%d %d %d", &x, &y, &z);

  sum =    x + y + z;

  printf("sum =  %d\n", sum);

  return 0;
}

og indlæs tallene 010, 011, og 012. Indlæs også 10, 11 og 12. Forklar resultaterne.

Kør så programmet

#include <stdio.h>

int main(void) {

  int x, y, z, sum;

  printf("Enter three integers: ");
  scanf("%o %o %o", &x, &y, &z);

  sum =    x + y + z;

  printf("sum =  %d\n", sum);

  return 0;
}

med samme input som ovenfor. Forklar hvad placeholderen %o i scanf gør i forhold til %d.

Og kør så sluttelig følgende program med 10, 11 og 12 som input

#include <stdio.h>

int main(void) {

  int x, y, z, sum;

  printf("Enter three integers: ");
  scanf("%o %o %o", &x, &y, &z);

  sum =    x + y + z;

  printf("sum =  %o\n", sum);

  return 0;
}

Kør det også med følgende input: 12 13 14.

Forklar hvad du oplever. Har du forstået reglerne? Leg gerne med variationer.

Løsning

#include <stdio.h>

int main(void) {

  int sum1 =    10  +   11  +  12,
      sum2  =  010 +   011 +  012,
      sum3  = 0x10 +  0x11 + 0x12;

  printf("sum1 =  %d\n", sum1);
  printf("sum2 =  %d\n", sum2);
  printf("sum3 =  %d\n", sum3);

  return 0;
}

Tallet 010, skrevet som en konstant i et C kildeprogram betegner et tal i det oktale talsystem. Det tilsvarende decimale tal er 8. Tilsvarende svarer det oktale tal 011 til 9, og 012 til 10 i det sædvanlige decimale talsystem. Tallet 0x10 er et hexadecimalt tal når det optræder i et C kildeprogram. Tallet svarer til det decimale tal 16.


#include <stdio.h>

int main(void) {

  int x, y, z, sum;

  printf("Enter three integers: ");
  scanf("%d %d %d", &x, &y, &z);

  sum =    x + y + z;

  printf("sum =  %d\n", sum);

  return 0;
}

Hvis vi indtaster 010, 011 og 012 som input til ovenstående program får vi resultatet 33. Samme input opnås med 10, 11 og 12. Når vi indlæser heltal med konverteringsspecifikationen %d i scanf, kan vi ikke umiddelbart angive oktale tal.


#include <stdio.h>

int main(void) {

  int x, y, z, sum;

  printf("Enter three integers: ");
  scanf("%o %o %o", &x, &y, &z);

  sum =    x + y + z;

  printf("sum =  %d\n", sum);

  return 0;
}

Ovenstående version viser at konverteringsspecifikationen %o i scanf fortolker input som oktale tal. Det er ligegyldigt om der indlæses 010 eller 10. Resultatet svarer i begge tilfælde til det decimale tal 8.


#include <stdio.h>

int main(void) {

  int x, y, z, sum;

  printf("Enter three integers: ");
  scanf("%o %o %o", &x, &y, &z);

  sum =    x + y + z;

  printf("sum =  %o\n", sum);

  return 0;
}

Hvis der indlæses 10, 11 og 12 som input til ovenstående program udskrives resultatet 33. Internt adderes de tre decimale heltal 8, 9 og 10. Summen af disse er 27 som svarer til det oktale tal 33. Regn selv efter!


2.2   Anvendelse af assignments  

Denne opave er lavet med det formål at du/I selv skal få styr på nogle forhold omkring assignments i C.

Se på følgende program:

#include <stdio.h>

int main(void) {

  int v = 8, w = 5,
      r, s;
    
  r = v = w;     /* Forklar denne */

  r = v + w;     /* Forklar denne */

  r + v = w;     /* Forklar denne */

  r + (v = w);   /* Forklar denne */

  return 0;
}

Forsøg på at forklare hver af de fire midterste programlinier, hvor de indgår et assignment. Skriv - i en kommentar efter hver line - de forventede værdier af v, w og r.

Undersøg om der er nogle af linierne, der giver problemer i forhold til compilering. Forklar i så fald hvilke problemer der opstår (og udkommenter disse linier, så du kan komme videre i opgaven).

Indsæt en passende printf kommando af v, w og r efter hvert assignment, som gerne skulle bekræfte de værdier af variablene, som du/I har forudsagt.

Løsning

Her er min kommenterede løsning på opgaven.

#include <stdio.h>

int main(void) {

  int v = 8, w = 5,
      r, s;
    

  r = v = w;  // v is first assigned to the value of w (5). 
              // Next r is assigned to 5.

  printf("r = %d, v = %d, w = %d\n", r, v, w);    // 5, 5, 5

  r = v + w;  // r is assigned to the sum of v and w.
  printf("r = %d, v = %d, w = %d\n", r, v, w);    // 10, 5, 5

  // r + v = w;  // Illegal. r + w is not an illegal left hand side value.
                 // Commented out of the program.

  r + (v = w);   // v is assigned to the value of w. 
                 // 5 and 10 is added together, but the value is lost.
  printf("r = %d, v = %d, w = %d\n", r, v, w);    // 10, 5, 5

  return 0;
}


2.3   Increment og decrement operatorerne  

Se på følgende program, som indholder en række increments og decrements:

#include <stdio.h>

int main(void) {
  
  int i = 3, j = 4, k = 5;
  int res1, res2, res3;
  
  i++; j--; ++k;

  printf("i: %d, j: %d, k: %d\n", i,j,k);

  res1 = --i;
  res2 = j++;
  res3 = --k;

  printf("res1: %d, res2: %d, res3: %d\n", res1, res2, res3);
  printf("i: %d, j: %d, k: %d\n", i,j,k);
  
  return 0;
}

Lav en skrivebordsudførelse af programmet, og forklar hvad der udskrives i de tre kald af printf. I en skrivebordsudførelse gennemgås programmets enkelte trin manuelt - med papir og blyant eller ved en tavle - uden først at køre programmet på en computer.

Når du er færdig med skrivebordsudførelsen, anbefales at du sammenligner dine resultater med det resultat du får ved at køre programmet på din computer.

Vær sikker på at diskutere dine resultater med dine medstuderende i gruppen.

Løsning

Du finder resultater og forklaringer i denne kommenterede udgave af programmet:

#include <stdio.h>

int main(void) {
  
  int i = 3, j = 4, k = 5;
  int res1, res2, res3;
  
  i++; j--; ++k;  /* i bliver talt op til 4.
                     j bliver talt ned til 3.
                     k bliver talt op til 6. 
                     I denne sammenhæng kan vi frit vælge mellem 
                     prefix og postfix increment/decrement. */

  printf("i: %d, j: %d, k: %d\n", i,j,k);  /* 4, 3, 6 */

  res1 = --i;     /* i er 4 før dette assignment.  i tælles ned til 3.
                     Da prefix assignment benyttes bliver res1 værdien af i efter nedtælling, altså 3. */
  res2 = j++;     /* j er 3 før dette assignment.  Denne værdi huskes.  j tælles op og bliver 4.
                     Den huskede værdi, altså 3, assignes til res2 */
  res3 = --k;     /* k er 6 før dette assignment.  k tælles ned til 5. 
                     Da vi har et prefix decrement bliver res3 værdien af k efter nedtællingen, altså 5. */

  printf("res1: %d, res2: %d, res3: %d\n", res1, res2, res3);  /* 3, 3, 5 */
  printf("i: %d, j: %d, k: %d\n", i,j,k);                      /* 3, 4, 5 */
  
  return 0;
}


2.4   Indlæsning af doubles  

Følgende simple program forsøger på at indlæse tre tal af typen double, beregne deres gennemsnit, og udskrive dette resultat:

#include <stdio.h>

int main(void) {

  double d, e, f;

  printf("Enter three real numbers: ");
  scanf("%f %f %f", &d, &e, &f);
  
  printf("The average is: %d\n", (d + e + f) / 3.0);
    
  return 0;
}

Prøverkør programmet, og forklar hvorfor det ikke virker efter hensigten.

Ret programmet, så det virker.

Når du har forstået problemet, så prøv meget gerne forskellige andre variationer af tilsvarende fejl.

Læs gerne på side 85-86 af lærebogen Problem Solving and Program Design in C, 8th edition for at forstå udfordringen.

Løsning

Der er to fejl i programmet:

  1. Variablene d, e og f er erklæret som doubles, men de indlæses med konverterings specifikationen %f i scanf, som knytter sig typen float. Når der læses en double skal %lf (long float) bruges i scanf.
  2. Typen af udtrykket d + e + f / 3.0 er double, men det udskrives med konverterings specifikationen %d, som knytter sig til typen int. Brug %f i stedet for %d.

Her er en version af programmet, som virker:

#include <stdio.h>

int main(void) {

  double d, e, f;

  printf("Enter three real numbers: ");
  scanf("%lf %lf %lf", &d, &e, &f);
  
  printf("The average is: %f\n", (d + e + f) / 3.0);
    
  return 0;
}


2.5   Uger, dage, timer, minutter og sekunder  

Skriv et C program, som indlæser et helt antal sekunder og som omregner dette tal til uger, dage, timer, minutter og sekunder på sædvanlig vis. Programmet skal udskrive antallet af uger, dage, timer, minutter og sekunder på skærmen.

Mere præcist skal de omregnede sekunder være i intervallet 0..59, de omregnede minutter skal være i intervallet 0..59, de omregnede timer skal være i intervallet 0..23, og de omregnede dage i intervallet 0..6. Ugetallet kan være vilkårligt stort.

Målet med opgaven er primært at træne dig i brugen af heltalsdivision / og rest operatoren ved heltalsdivision %. Sekundært sætter opgaven fokus på symbolske konstanter og simpel brug af scanf og printf.

Her er eksempler på input og ønsket output:


2.6   Erfaringer med scanf  

Formålet med denne opgave er at give jer erfaring med formateret input med scanf funktionen fra stdio bibliotektet.

Der vises et antal programmer herunder, hvor hvert program indlæser nogle data med scanf. Der gives et antal forslag til input linier. I skal afprøve hvert problem et antal gange, med den foreslåede input. I hvert tilfælde skal I forklare hvad der indlæses, og hvilken værdi der returneres af kaldet af scanf. Endvidere er det helt fint at variere både programmerne og input, for at få endnu mere indsigt og erfaring!

Jeg anbefaler at I nedskriver den række af erfaringer, som I får ved at lege med eksemplerne i denne opgave. Læg mærke til tallet scanRes, og den pejling som scanRes giver for indlæsningen med scanf. Disse erfaringer er gode at vende tilbage til siden hen på dette kursus.

I lærebogen kan du læse om scanf side 85 - 87. Jeg kan også anbefale afsnittet Formatted Input (scanf) fra Steve Summit's noter om C programmering (introductory og intermediate) som beskriver flere variationer af scanf end lærebogen.

Her er første version af programmet, som indlæser tegn:

#include <stdio.h>

int main(void) {

  int c1, c2, c3, c4,   scanRes;

  printf("Enter input on the following line\n");

  scanRes = scanf("%c%c%c%c", &c1, &c2, &c3, &c4);

  printf("c1 = %c, c2 = %c, c3 = %c, c4 = %c\n", c1, c2, c3, c4);
  printf("scanRes = %d\n", scanRes);

  return 0;
}

Afprøv programmet med følgende input (i et tilsvarende antal kørsler af programmet). Forklar dine observationer:

abcd
ab
a b c d

Her er næste version af programmet, som indlæser heltal:

#include <stdio.h>

int main(void) {

  int i1, i2,
      scanRes;

  printf("Enter input on the following line\n");

  scanRes = scanf("%d%d", &i1, &i2);

  printf("i1 = %d, i2 = %d\n", i1, i2);
  printf("scanRes = %d\n", scanRes);

  return 0;
}

Afprøv programmet med følgende input (i et tilsvarende antal kørsler af programmet). Forklar dine observationer:

123 456
123    456
123.456
123-456
123_456
123

Her er endnu en version af programmet, som indlæser heltal. I denne version er der foretaget en lille forandring af kontrolstrengen af scanf:

#include <stdio.h>

int main(void) {

  int i1, i2,
      scanRes;

  printf("Enter input on the following line\n");

  scanRes = scanf("%d;%d", &i1, &i2);

  printf("i1 = %d, i2 = %d\n", i1, i2);
  printf("scanRes = %d\n", scanRes);

  return 0;
}

Afprøv programmet med følgende input (i et tilsvarende antal kørsler af programmet). Forklar dine observationer:

123;456
123; 456
123 ; 456
123:456
123.456;

Og endnu en version af programmet, som indlæser heltal. Igen er der i denne version foretaget en mindre forandring af kontrolstrengen af scanf:

#include <stdio.h>

int main(void) {

  int i1, i2,
      scanRes;

  printf("Enter input on the following line\n");

  scanRes = scanf("%d abe %d", &i1, &i2);

  printf("i1 = %d, i2 = %d\n", i1, i2);
  printf("scanRes = %d\n", scanRes);

  return 0;
}

Afprøv programmet med følgende input (i et tilsvarende antal kørsler af programmet). Forklar dine observationer:

123 456
123abe456
123 abe 456
123 kat 456
-123abe-456

I den sidste version indlæser vi doubles:

#include <stdio.h>

int main(void) {

  double d1, d2;
  int scanRes;

  printf("Enter input on the following line\n");

  scanRes = scanf("%lf %lf", &d1, &d2);

  printf("d1 = %10.5f, d2 = %8.4f\n", d1, d2);
  printf("scanRes = %d\n", scanRes);

  return 0;
}

Afprøv programmet med følgende input (i et tilsvarende antal kørsler af programmet). Forklar dine observationer:

12.34 56.78
12.34   56.78
12.34.56.78
12.34 56 . 78
12 34
012 034
12,34
.12e3 .4e-2
12a34
12-34
12 - 34	


2.7   Uinitialiserede variable  

Alle i gruppen bedes compilere og køre programmet med den uinitialiserede variabel fra denne slide.

Kan programmet compileres? Kan I køre programmet? Får I et output fra det kørende program? Får I - i så fald - det samme output fra programmet? Forklar hvorfor - eller hvorfor ikke.


2.8   Opgave 3 side 106 i 'Problem Solving and Program Design in C', 8. ed, global  

Der henvises til bogen formulering af opgaven: 'Problem Solving and Program Design in C', 8. ed, global. Opgaven er med her for at kunne formidle løsningen.

Løsning

Her er løsningen på denne opgave:

   a. 3                 g. undefined    m. -3.14159 
   b. ??                h. undefined    n. 1.0 
   c. 1                 i. ??           o. 1 
   d. -3.14159          j. 3            p. undefined 
   e. ??                k. -3.0         q. 3 
   f. 0.0               l. 9            r. 0.75 


Genereret: Onsdag 15. september 2021, 08:42:34