Kapitel 2
Introduktion til C

Kurt Nørmark
Institut for Datalogi, Aalborg Universitet


Sammendrag
Forrige lektion Næste lektion
Stikord Referencer Indhold
Dette sæt af slides udgør den faglige introduktion til programmering i C. Lektion er koncentreret om udtryk, operatorer, assignment operatorerne, samt udskrivning og indlæsning.


Hello World og Programmeringsstil

Hello World i C
Slide Indhold Stikord
Referencer 

'Hello world' er et program som viser hvor let eller svært det er at skrive en velkomst-tekst ud på skærmen

Program: Hello World.
/* The traditional first program in honor of
   Dennis Ritchie, who invented C while
   at Bell Labs in 1972.
*/

#include <stdio.h>

int main(void)
{
   printf("Hello, world!\n");
   return 0;
}

Program: Lærebogens første program - som vist på side 67.
/*
 * Converts distance in miles to kilometers.
 */
#include <stdio.h>              /* printf, scanf definitions */
#define KMS_PER_MILE 1.609      /* conversion constant       */

int
main(void)
{
      double miles,  /* distance in miles.            
             kms;    /* equivalent distance in kilometers  */

      /* Get the distance in miles. */
      printf("Enter the distance in miles> ");
      scanf("%lf", &miles); 

      /* Convert the distance to kilometers. */
      kms = KMS_PER_MILE * miles;

      /* Display the distance in kilometers. */
      printf("That equals %f kilometers.\n", kms);

      return (0);
}

Program: Lærebogens første program - nu OK.
/*
 * Converts distance in miles to kilometers.
 */
#include <stdio.h>              /* printf, scanf definitions */
#define KMS_PER_MILE 1.609      /* conversion constant       */

int
main(void)
{
      double miles,  /* distance in miles.                 */    
             kms;    /* equivalent distance in kilometers  */

      /* Get the distance in miles. */
      printf("Enter the distance in miles> ");
      scanf("%lf", &miles); 

      /* Convert the distance to kilometers. */
      kms = KMS_PER_MILE * miles;

      /* Display the distance in kilometers. */
      printf("That equals %f kilometers.\n", kms);

      return (0);
}

Program: Lærebogens første program - dårlig stil.
/*
 * Converts distance in miles to kilometers.
                          */
#include <stdio.h>              /* printf, scanf definitions */
#define KMS_PER_MILE 1.609        /* conversion constant       */

int
main(void)
{
   double miles,  /* distance in miles.                 */    
      kms;    /* equivalent distance in kilometers  */

      /* Get the distance in miles. */
      printf("Enter the distance in miles> ");
    scanf("%lf", &miles); 

          /* Convert the distance to kilometers. */
      kms = KMS_PER_MILE * miles;

      /* Display the distance in kilometers. */
      printf("That equals %f kilometers.\n", kms);     return (0);
                }

Program: Lærebogens første program - små og store bogstaver i navne.
/*
 * Converts distance in miles to kilometers.
 */
#include <stdio.h>              /* printf, scanf definitions */
#define KMS_PER_MILE 1.609      /* conversion constant       */

int
main(void)
{
      Double miles,  /* distance in miles.                 */    
             kms;    /* equivalent distance in kilometers  */

      /* Get the distance in miles. */
      printf("Enter the distance in miles> ");
      scanf("%lf", &miles); 

      /* Convert the distance to kilometers. */
      Kms = KMS_PER_MILE * miles;

      /* Display the distance in kilometers. */
      printf("That equals %f kilometers.\n", kms);

      Return (0);
}

Program: Lærebogens første program - som jeg ville have skrevet det.
/* Converts distance in miles to kilometers. */

#include <stdio.h>              
#define KMS_PER_MILE 1.609      

int main(void){
  double miles,  /* distance in miles.                 */    
         kms;    /* equivalent distance in kilometers  */

  /* Get the distance in miles. */
  printf("Enter the distance in miles> ");
  scanf("%lf", &miles); 

  /* Convert the distance to kilometers. */
  kms = KMS_PER_MILE * miles;

  /* Display the distance in kilometers. */
  printf("That equals %f kilometers.\n", kms);

  return 0;
}

Observationer om de første programmer
Slide Indhold Stikord
Referencer 

Vi fastholder her nogle forhold om de første programmer, vi har set

  • Præ-processor directives

    • #include og #define

  • Funktionen main

    • Her starter programmet når vi kører det

  • Navne

    • Reserverede ord, variable, navne på standard biblioteks-funktioner

    • Forskel på små og store bogstaver

  • Programmeringsstil og layout

    • Indrykning, mellemrum, tomme linjer

  • Tegnsætning - punctuation

    • Semikolon, komma, ...

  • Kommentarer

    • Så vi selv og andre kan forstå programmet

    • /* ... */


Variable og Assignment

Assignment til variable
Slide Indhold Stikord
Referencer 

Variable er pladser i lageret, hvis værdier kan ændres ved udførelse af assignment kommandoer.

Alle variable skal erklæres før brug.

Begrebet variabel: En variabel er en navngiven plads i arbejdslageret, som kan indeholde en værdi af en bestemt type.
Begrebet erklæring: En variabel skal introduceres i en erklæring (declaration) - hvor også typen angives.
Begrebet assignment: Et assignment er en kommando, som ændrer værdien af en variabel.

Syntax:

type variable1, variable2..., variablen; 

variablei = expression;

Program: Et simpelt program med variable og assignments.
#include <stdio.h>

int main(void) {

  int courses, groups, students, average_pr_group;

  courses = 1;       
  groups = 26;
  students = 176;

  average_pr_group = students / groups;

  printf("There are %d students pr. group in %d course(s)\n", 
         average_pr_group, courses);
  
  return 0;
}

Program: En variation af programmet - typen angives for hver variabel.
#include <stdio.h>

int main(void) {

  int courses;
  int groups;
  int students;
  int average_pr_group;

  courses = 1;       
  groups = 26;
  students = 176;

  average_pr_group = students / groups;

  printf("There are %d students pr. group in %d course(s)\n", 
         average_pr_group, courses);
  
  return 0;
}

Program: Program output.
There are 6 students pr. group in 1 course(s)

Program: En variant af programmet som illustrerer 'små og store bogstaver' i variabelnavne - compilerer ikke.
#include <stdio.h>

int main(void) {

  int courses, groups, students, average_pr_group;

  Courses = 1;       /* compile time error: Undeclared variables */         
  GROUPS = 22;
  studentS = 148;

  averagePrGroup = students / groups;

  printf("There are %d students pr. group in %d course(s)\n", 
         average_pr_group, courses);
  
  return 0;
}

Program: En variant af programmet med flere ulovlige navne - compilerer ikke.
#include <stdio.h>

int main(void) {

  int 1course;             /* must begin with a letter       */
  int number of groups,    /* no spaces in variable names    */
  int student*,            /* * disallowed in variable names */
  int average-pr-group;    /* - disallowed in variable names */

  1course = 1;       /* compile time error: Undeclared variables */         
  number of groups = 22;
  student* = 148;

  average-pr-group = student* / number of groups;

  printf("There are %d students pr. group in %d course(s)\n", 
         average-pr-group, 1course);
  
  return 0;
}

Initialisering
Slide Indhold Stikord
Referencer 

Variabel bør eksplicit tildeles en startværdi i programmet

Begrebet initialisering: Ved initialisering forstås tilskrivning af en startværdi til en variabel

Program: En variation af programmet fra forrige slide.
#include <stdio.h>

int main(void) {

  int courses = 1, groups = 26, students = 176,
      average_pr_group = 0;

  average_pr_group = students / groups;

  printf("There are %d students pr. group in %d course(s)\n", 
         average_pr_group, courses);
  
  return 0;
}

Program: Et program med en uinitialiseret variabel.
#include <stdio.h>
#include <stdlib.h>

int main(void) {

  /* The variable groups is uninitialized */
  int classes = 2, groups, students = 280;

  int average_pr_group = 0, average_pr_course = 0;

  average_pr_group = students / groups;
  average_pr_course = students / classes;

  printf("Classes: %d, Groups: %d, Students: %d \n", classes, groups, students);

  printf("There are %d students pr. group.\n", average_pr_group);
  printf("There are %d students pr. class.\n", average_pr_course);
  
  return EXIT_SUCCESS;
}

Program: Muligt program output.
Groups: 6773728
There are 0 students pr. group in 1 course(s)

Hvis man undlader at initialisere variable i et C program risikerer man at der opstår tilfældige fejl, når man kører programmet

Eksplicit initialisering foretrækkes altid frem for evt. implicit initialisering til en default værdi

Typer i C
Slide Indhold Stikord
Referencer 

C understøtter forskellige fundamentale datatyper, og vi kan selv lave vore egne typer i C.

Begrebet type: En type er en mængde af værdier med fælles egenskaber

Tabel.
Fundamentale typer i CEksempler på værdier i typerne
Heltalint
short int
long int
10
5
111L
Reelle taldouble
float
long double
10.5
5.5F
111.75L
Tegnchar'C'
'a'
Tekststrengechar *"Computer"
"C"
 

Henvisninger

Program: Illustration af konkrete typer i et C program.
#include <stdio.h>

int main(void) {

  int i = 10;
  short int j = 5;
  long int k = 111L;

  double x = 10.5;
  float y = 5.5F;
  long double z = 111.75L;

  char c = 'C';
  char d = 'a';

  char *s = "Computer", *t = "C";  

  printf("i = %d", i);

  return 0;
}

Opgave 2.2. 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.

Foruden de forskellige typer af decimale tal understøtter C også heltal i oktal og hexadecimal notation (eksempelvis 0123 og 0x1bc ).

Assignments på formen i = i + 1
Slide Indhold Stikord
Referencer 

Der er ofte behov for at tælle en variabel op eller ned.

Dermed optræder variablen både på venstre og højre side af assignmentsymbolet

  • Antag at i har værdien 7

  • Beregning af i = i + 1

    • Udtrykket i + 1 på højre side af assignmentsymbolet beregnes til 8

    • Værdien af variablen i ændres fra 7 til 8

Program: Et program med forskellige optællinger og nedtællinger. annotation
#include <stdio.h>

int main(void) {

  int i = 3, j = 7, k = 9;

  j = j - i;
  i = i + j;
  k = k * i;

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

Program: Output fra ovenstående program.
i: 7, j: 4, k: 63

Opgave 2.3. 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.

Symbolske konstanter
Slide Indhold Stikord
Referencer 

En symbolsk konstant giver et navn til en konkret værdi - så som et tal

I C benytter vi et preprocessor directive til at lave en symbolsk konstant

Program: Et program med flere symbolske konstanter.
#include <stdio.h>
#include <math.h>

#define PI 3.14159
#define E  2.71828
#define MAX_NUM 5

double log_two(double x){
  return 1.0 / log(2.0) * log(x);
}

int main(void) {

  double radius = 4.0, d;
  int i;

  printf("Area of circle = %f\n", radius * radius * PI);
  printf("Circumference of circle =  %f\n", 2 * radius * PI);

  printf("log(e) = %f\n", log(E));
  printf("log10(e) = %f\n", log10(E));
  printf("log2(e) = %f\n\n", log_two(E));

  printf("%d examples with log2:\n", MAX_NUM);
  for (i = 1, d = 2.0; i <= MAX_NUM; i++, d *= 2)
    printf("log2(%f) = %f\n", d, 1.0 / log(2.0) * log(d));

  return 0;
}

Program: Et program uden brug af symbolske konstanter.
#include <stdio.h>
#include <math.h>

double log_two(double x){
  return 1.0 / log(2.0) * log(x);
}

int main(void) {

  double radius = 4.0, d;
  int i;

  printf("Area of circle = %f\n", radius * radius * 3.14159);
  printf("Circumference of circle =  %f\n", 2 * radius * 3.14159);

  printf("log(e) = %f\n", log(2.71828));
  printf("log10(e) = %f\n", log10(2.71828));
  printf("log2(e) = %f\n\n", log_two(2.71828));

  printf("%d examples with log2:\n", 5);
  for (i = 1, d = 2.0; i <= 5; i++, d *= 2)
    printf("log2(%f) = %f\n", d, 1.0 / log(2.0) * log(d));

  return 0;
}

Program: Program output.
Area of circle = 50.265440
Circumference of circle =  25.132720
log(e) = 0.999999
log10(e) = 0.434294
log2(e) = 1.442694

5 examples with log2:
log2(2.000000) = 1.000000
log2(4.000000) = 2.000000
log2(8.000000) = 3.000000
log2(16.000000) = 4.000000
log2(32.000000) = 5.000000

Undgå ALTID 'magiske værdier' rundt omkring i dit program. Brug symbolske konstanter.

Der afsættes ikke lagerplads til symbolske konstanter - de indsættes tekstuelt af præprocessoren

Variable og konstanter
Slide Indhold Stikord
Referencer 

Det er også muligt at markere en variabel som konstant med brug af en const modifier

Det er ikke muligt at assigne til en sådan variabel

Program: De to matematiske konstanter pi og e, og forsøg på assignments til disse.
#define PI 3.14159

int main(void) {
  
  const double pi = 3.14159, e =  2.71828;

  pi = pi + 1;   // compile time error:
                 // assignment of read-only variable 'pi'

  e = e - 1;     // compile time error:
                 // assignment of read-only variable 'e'

  PI = 4.0;      // compile time error:
                 // lvalue required as left operand of assignment

  return 0;
}

Der afsættes lager til de to konstante variable pi og e, men indholdet af variablene kan ikke ændres efter initialiseringerne


Udtryk og Operatorer

Udtryk
Slide Indhold Stikord
Referencer 

Begrebet udtryk: Et udtryk er et programfragment der beregnes med henblik på at opnå en værdi, som tilhører en bestemt type.

Et udtryk er sammensat af operatorer og operander.

Antag at både x og y er af typen int, at værdien af x er 14 og at y er 3:

Tabel. Forskellige udtryk med udtrykkenes typer og værdier.
UdtrykTypeVærdi
7Heltal7
xHeltal14
x + 6Heltal20
x / 3Heltal4
x % 3Heltal2
x <= yBooleanfalse
x + y * 3 >= y % x - 5Booleantrue
 

En værdi i en C programudførelse har en bestemt type

Et udtryk i en C programbeskrivelse har også en bestemt type

Beregning af sammensatte udtryk
Slide Indhold Stikord
Referencer 

Problemstilling: Hvordan fortolkes udtryk som er sammensat af adskillige operatorer og operander?

  • Indsæt parenteser som bestemmer beregningsrækkefølgen

    • x + y * 3 >= y % x - 5

    • (x + (y * 3)) >= ((y % x) - 5)

  • Benyt regler som definerer hvilke deludtryk (operander) der beregnes før andre

    • Multiplikation, division og modulus beregnes før addition og subtraktion

    • Addition og subtraktion beregnes før sammenligning

C prioriterer operatorer i ca 15 niveauer. Men det er også muligt - og ofte nødvendigt - at sætte parenteser omkring deludtryk

Se appendix C i bogen, eller C Reference Card side 2, eller en slide senere i lektionen

Henvisninger

Prioritering af operatorer
Slide Indhold Stikord
Referencer 

En simplificeret operator prioriterings tabel med de mest anvendte operatorer.

Udtryk som bruger operatorer fra et højt niveau beregnes før udtryk med operatorer fra et lavere niveau.

Tabel. En operatorprioriteringstabel for udvalgte operatorer.
NiveauOperatorer
15+unary      -unary
13*      /      %
12+      -
10<      <=      >      >=
9==      !=
5&&
4||
 

Associering af operatorer
Slide Indhold Stikord
Referencer 

Problemstilling: Prioriteringstabellen fortæller ikke hvordan vi beregner udtryk med operatorer fra samme niveau

  • 10 - 1 - 9 / 3 / 2

    • Operator prioriteringen fortæller at divisionerne foretages før subtraktionerne

    • Associeringsreglerne fortæller at der sættes parenteser fra venstre mod højre

    • ((10 - 1) - ((9 / 3) / 2))

    • Resultatet er 8

Program: Et C program med udtrykket 10 - 1 - 9 / 3 / 2.
#include <stdio.h>

int main(void) {

  int res1, res2, res3;

  res1 =  10 - 1 - 9 / 3 / 2;

  res2 =  ((10 - 1) - ((9 / 3) / 2));    
  /* left to right associativity */

  res3 =  (10 - (1 - (9 / (3 / 2))));   
  /* right to left associativity */

  printf("res1 = %d, res2 = %d, res3 = %d\n", res1, res2, res3);
  
  
  return 0;
}

Program: Output fra ovenstående program.
res1 = 8, res2 = 8, res3 = 18

De fleste operatorer i C associerer fra venstre mod højre

Operatortabel for C
Slide Indhold Stikord
Referencer 

Tabel. Den fulde operator prioriteringstabel for C.
NiveauOperatorerAssociativitet
16()      []      ->      .      ++postfix      --postfix left to right
15++prefix      --prefix      !      ~      sizeof(type)      +unary      -unary      &unary,prefix      *unary,prefixright to left
14(type name) Castright 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
 


Assignment operatorer i C

Eksempler på assignments i C
Slide Indhold Stikord
Referencer 

Vi ser eksempler på forskellige former for assignments på denne slide

På næste slide ser vi på principper, begreber og terminologi

Program: Assignments på formen a = b = c = d = 7.
#include <stdio.h>

int main(void) {

  int a, b, c, d;

  a = b = c = d = 7;        /* a = (b = (c = (d = 7)))  */
  printf("a: %d, b: %d, c: %d, d: %d\n", a,b,c,d);
  
  return 0;
}

Program: Assignments på formen a = (b = 2) + (c = 3) - (d = 1).
#include <stdio.h>

int main(void) {

  int a, b, c, d;

  a = (b = 2) + (c = 3) - (d = 1);

  /* b = 2; c = 3; d = 1;
     a = b + c - d;             */

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

Program: Assignments på formen a++, ++b, c-- og --d.
#include <stdio.h>

int main(void) {

  int a = 0, b = 0, 
      c = 2, d = 2;

  a++; ++b;
  c--; --d;  

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

Program: Assignments ækvivalente til forrige eksempel.
#include <stdio.h>

int main(void) {

  int a = 0, b = 0, 
      c = 2, d = 2;

  a = a + 1; b = b + 1;
  c = c - 1; d = d - 1;

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

Program: Assignments på formen a += 1 og c -= 1.
#include <stdio.h>

int main(void) {

  int a = 0, b = 0, 
      c = 2, d = 2;

  a += 1; b += 1;
  c -= 1; d -= 1;

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

Program: Assignments samme form - men lidt mere generelt.
#include <stdio.h>

int main(void) {

  int a = 0, b = 0, 
      c = 2, d = 2;

  a += 2; b += 3;
  c -= 4; d -= 5;

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

Program: Assignments på formen a++, ++b, c-- og --d - den fulde sandhed.
#include <stdio.h>

int main(void) {

  int a = 0, b = 0, 
      c = 2, d = 2,
      res1, res2, res3, res4;

  res1 = a++;  res2 = ++b;
  res3 = c--;  res4 = --d;  

  printf("a: %d, b: %d, c: %d, d: %d\n", a,b,c,d);
  /* 1 1 1 1 */

  printf("res1: %d, res2: %d, res3: %d, res4 = %d\n", res1, res2, res3, res4);  
  /* 0 1 2 1 */
  
  return 0;
}

Assignments i C
Slide Indhold Stikord
Referencer 

  • Et assignment a = b + c er et udtryk

    • Værdien af a = b + c er værdien af b + c

    • Assignmentet har en (side)effekt på a

    • Udtrykket er urent

  • Assignment operatorer har lav prioritet, og associerer fra højre mod venstre

    • Tildelingen af variablen sker derfor næsten altid efter beregningen af højresiden

  • Compound assignments

    • Assignments på form a op= b

    • Eksempelvis: a -= b

  • Postfix increment og postfix decrement

    • Eksempler: a++ og b--

    • Tæller op/ned, men returnerer værdien før op/nedtælling

  • Prefix increment og prefix decrement

    • Eksempler: ++a og --b

    • Tæller op/ned, men returnerer værdien efter op/nedtælling

Opgave 2.4. 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.


Udskrivning og Indlæsning

Udskrivning med printf
Slide Indhold Stikord
Referencer 

Kommandoen printf kan udskrive data af forskellige fundamentale typer.

Formateringen af output styres af en kontrolstreng, som altid er første parameter.

Program: Udskrivning af variable af forskellige typer med printf.
#include <stdio.h>

int main(void) {

  int i = 10;
  short j = 5;
  long k = 111L;
  printf("i: %d, j: %3hd, k: %10.5ld\n", i, j, k);

  double x = 10.5;
  float y = 5.5F;
  long double z = 111.75L;
  printf("x: %f, y: %5.2f, z: %Le\n", x, y, z);

  char c = 'A';
  char d = 'a';
  printf("c: %c, d: %d\n", c, d);

  char *s = "Computer", *t = "C";
  printf("s: %s,\nt: %s\n", s, t);  

  return 0;
}

Program: Udskrivning af variable af forskellige typer med printf - med forklaringer.
#include <stdio.h>

int main(void) {

  int i = 10;
  short j = 5;
  long k = 111L;
  printf("i: %d, j: %3hd, k: %10.5ld\n", i, j, k);
    /* i: %d        Simple printing of an integer.  %i can also be used (same meaning).
       j: %3hd      Minimum field width is 3.  h is size modfier for short int.
       k: %10.5ld   Minimum field width is 10. At least 5 ciffers must be printed.  
                    l is size modifier for long int.
       \n forces print of a new line char.
    */

  double x = 10.5;
  float y = 5.5F;
  long double z = 111.75L;
  printf("x: %f, y: %5.2f, z: %Le\n", x, y, z);
    /*  x   %f     Simple printing of double.
        y:  %5.2f  Printing of float. Same conversion letter as double. Minimum field width is 5. 
                   Number of digits after decimal point is 2. 
        z:  %Le    Printing af long double. L is size modifier for long. 
                   e is conversion letter for scientific notation: 
       \n forces print of a new line char.
    */
   

  char c = 'A';
  char d = 'a';
  printf("c: %c, d: %d\n", c, d);

  char *s = "Computer", *t = "C";
  printf("s: %s,\nt: %s\n", s, t);  

  return 0;
}

Program: Output fra ovenstående program.
i: 10, j:   5, k:      00111
x: 10.500000, y:  5.50, z: 1.117500e+02
c: A, d: 97
s: Computer,
t: C

Henvisninger

  • Egenskaber af printf kommandoen:

    • Opbygget af formateringsstreng med placeholders efterfulgt af en print liste.

    • Indlejring af formaterede parametre i en fast tekst.

    • Én til én korrespondance mellem konverteringstegn og parametre efter kontrolstrengen.

    • Mulighed for at bestemme antal tegn i output, antal cifre før og efter 'komma', venstre/højrestilling, output talsystem, mm.

    • Antallet af udskrevne tegn returneres

Indlæsning med scanf
Slide Indhold Stikord
Referencer 

Kommandoen scanf fortolker tegn med henblik på indlæsning af værdier af de fundamentale datatyper

Fortolkning og styring af input sker med en kontrolstreng, analogt til kontrolstrengen i printf.

Program: Indlæsning og summering af tal.
/* Sums are computed. */

#include <stdio.h>

int main(void)
{
   float  sum = 0.0, x;

   printf("Input three numbers:  ");

   scanf("%f", &x);
   sum += x;

   scanf("%f", &x);
   sum += x;

   scanf("%f", &x);
   sum += x;

   printf("Sum: %6f\n", sum);

   return 0;
}

Henvisninger

  • Egenskaber af scanf kommando:

    • De indlæste data indlæses i angivne lageraddresser

    • Antallet af gennemførte indlæsninger/konverteringer returneres

Opgave 2.5. 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.

Et input output eksempel
Slide Indhold Stikord
Referencer 

Program: Et program der beregner arealet af en cirkel.
#include <stdio.h>

#define PI 3.141592653589793

int main(void)
{
   double radius;

   printf("This program computes the area of a circle.\n\n");

   printf("Input the radius:   ");
   scanf("%lf", &radius);

   printf("\nArea = PI * radius * radius\n");
   printf("     = %.2f * %.2f * %.2f\n", PI, radius, radius);
   printf("     = %.5f\n", PI * radius * radius );

   return 0;
}

Program: Samme program med farvede fremhævninger af placeholders i format strengen printf og scanf.
#include <stdio.h>

#define PI 3.141592653589793

int main(void)
{
   double radius;

   printf("This program computes the area of a circle.\n\n");

   printf("Input the radius:   ");
   scanf("%lf", &radius);

   printf("\nArea = PI * radius * radius\n");
   printf("     = %.2f * %.2f * %.2f\n", PI, radius, radius);
   printf("     = %.5f\n", PI * radius * radius );

   return 0;
}

Program: Input til og output fra programmet.
This program computes the area of a circle.

Input the radius:   5.3

Area = PI * radius * radius
     = 3.14 * 5.30 * 5.30
     = 88.24734

Program: Alternativ udgave af programmet - mere kompleks brug af format strengen.
#include <stdio.h>

#define PI 3.141592653589793

int main(void)
{
   double radius;

   printf("\n%s\n\n%s",
      "This program computes the area of a circle.",
      "Input the radius:  ");
   scanf("%lf", &radius);
   printf("\n%s\n%s%.2f%s%.2f%s%.2f\n%s%.5f\n\n",
      "Area = PI * radius * radius",
      "     = ",  PI, " * ",  radius, " * ",  radius,
      "     = ", PI * radius * radius );
   return 0;
}

Program: Alternativ udgave med farvede fremhævninger af kontrolstreng og parametre til printf.
#include <stdio.h>

#define PI 3.141592653589793

int main(void)
{
   double radius;

   printf("\n%s\n\n%s",
      "This program computes the area of a circle.",
      "Input the radius:  ");
   scanf("%lf", &radius);
   printf("\n%s\n%s%.2f%s%.2f%s%.2f\n%s%.5f\n\n",
      "Area = PI * radius * radius",
      "     = ",  PI, " * ",  radius, " * ",  radius,
      "     = ", PI * radius * radius );
   return 0;
}

Program: Input til og output fra det alternative program.
This program computes the area of a circle.

Input the radius:  5.3

Area = PI * radius * radius
     = 3.14 * 5.30 * 5.30
     = 88.24734

Opgave 2.7. 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:

  • Hvis der indlæses 650 sekunder udskrives der 0 uger, 0 dage, 0 timer, 10 minutter og 50 sekunder.
  • Hvis der indlæses 4000 sekunder udskrives der 0 uger, 0 dage, 1 timer, 6 minutter og 40 sekunder.
  • Hvis der indlæses 1000000 sekunder udskrives der 1 uger, 4 dage, 13 timer, 46 minutter og 40 sekunder.

Opgave 2.7. 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	

Flere Opgaver
Slide Indhold Stikord
Referencer 

Her er flere opgaver som er knyttet til denne lektion

Opgave 2.9. 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.

Opgave 2.9. 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.


Samlede referencer
Indhold Stikord
Oversigt over typer fra 5. lektion
Lektion om typer i C
C Reference Card
Operatortabel for C
Oversigt over floating point typer - herunder konverteringstegn
Oversigt over heltalstyper - herunder konverteringstegn
Mere detaljeret beskrivelse af printf
Mere detaljeret beskrivelse af scanf

 

Kapitel 2: Introduktion til C
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:02