Programmeringsteknik för mediaingenjörer, ht -98
1
Niklas Frykholm, Gunnar Gunnarsson
Mål och innehåll
Kursens mål är
- att orientera om användning av datorn i naturvetenskapliga och tekniska tillämpningar,
- att ge kännedom om ett datorsystems uppbyggnad och funktion,
- att ge kunskaper och färdigheter i programkonstruktion och organisation av
programsystem och
- att orientera om datastrukturer och algoritmer.
Inriktning: Högnivåprogrammering: Genomgång av programspråket C. Träning i
konstruktion av algoritmer, programmeringsmetodik och strukturerad programmering.
Genomgång av algoritmer för sökning och sortering.
Datoranvändning: Datoranvändning och programutveckling i persondatormiljö. Orientering
om ett datorsystems uppbyggnad och funktion illustrerad med aktuellt datorsystem.
Lågnivåprogrammering: Datarepresentation. Pekare och dynamisk minneshantering.
Gränssnitt till operativsystem och perifera enheter.
Programmeringsteknik för mediaingenjörer, ht -98
2
Niklas Frykholm, Gunnar Gunnarsson
hastighet = 100;
tid = 2.5;
stracka = hastighet * tid;
liter_per_mil = 0.9;
bensinforbrukning = stracka/10 * liter_per_mil;
bensinpris = 8.00;
kostnad = bensinforbrukning * bensinpris;
Programmeringsteknik för mediaingenjörer, ht -98
if (hastighet
printf("Du
else {
diff = 110
printf("Du
"%i utan
}
3
Niklas Frykholm, Gunnar Gunnarsson
> 110)
kör för fort.");
– hastighet;
kan öka din hastighet med "
att köra för fort", diff);
Programmeringsteknik för mediaingenjörer, ht -98
4
Niklas Frykholm, Gunnar Gunnarsson
if (hastighet > 140)
printf("Du kan bli av med körkortet.");
else if (hastighet > 110)
printf("Du kör för fort.");
else {
diff = 110 – hastighet;
printf("Du kan öka din hastighet med "
"%i utan att köra för fort", diff);
}
Programmeringsteknik för mediaingenjörer, ht -98
5
Niklas Frykholm, Gunnar Gunnarsson
/* Beräkna 10! = 1*2*3*...*10 */
res = 1;
for (i=1; i<=10; i++)
res = res * i;
/* Hur många tal i serien 1, 1/2, 1/3, 1/4, ...
måste vi addera för att summan skall bli >= 10? */
sum = 0;
i = 0;
while (sum < 10) {
i = i + 1;
sum = sum + 1/i;
}
Programmeringsteknik för mediaingenjörer, ht -98
6
Niklas Frykholm, Gunnar Gunnarsson
y = sin(2*x + 0.1);
/* Returnerar det största av talen x och y. */
int max(int x, int y)
{
if (x > y)
return x;
else
return y;
}
blir_fem = max(3,5);
Programmeringsteknik för mediaingenjörer, ht -98
7
#include <stdio.h>
int main(void)
{
printf("Hello, world!");
}
Niklas Frykholm, Gunnar Gunnarsson
Programmeringsteknik för mediaingenjörer, ht -98
8
Niklas Frykholm, Gunnar Gunnarsson
/* Borsta tänderna */
Applicera tandkräm på borsten
Borsta utsidan av tänderna i överkäken
Borsta tuggsidan av tänderna i överkäken
...osv
/* Ta sig igenom en labyrint. */
Placera handen på högra väggen.
Gå tills du kommer ut ur labyrinten.
/* Största gemensamma delare (Euklides algoritm) */
Givet två tal a och b, där a > b
Sätt r till resten vid division av a genom b
Om r = 0 är vi klara och b är SGD för de två talen.
I annat fall sätt a = b och b = r och fortsätt med steg 2.
Programmeringsteknik för mediaingenjörer, ht -98
9
Niklas Frykholm, Gunnar Gunnarsson
/* Hitta alla primtal mellan 1 och n. (Erastotenes såll) */
Skriv upp alla tal mellan 1 och n.
Sätt k = 2.
Stryk alla tal som är delbara med k utom k själv, dvs stryk
vart k:te tal, med början i talet 2k.
Om det finns något tal > k som inte är struket, så sätt k till
det talet och fortsätt med steg 3.
I annat fall är vi klara.
Programmeringsteknik för mediaingenjörer, ht -98
r = a % b;
while (r != 0) {
a = b;
b = r;
r = a % b;
}
10
Niklas Frykholm, Gunnar Gunnarsson
/* % är rest-operatorn i C */
/* != betyder skilt ifrån */
Programmeringsteknik för mediaingenjörer, ht -98
11
Niklas Frykholm, Gunnar Gunnarsson
/* Returnerar den största gemensamma */
/* delaren för talen a och b. */
int gcd(int a, int b)
{
int r = a % b;
while
a =
b =
r =
}
(r != 0) {
b;
r;
a % b;
return r;
}
Programmeringsteknik för mediaingenjörer, ht -98
12
Niklas Frykholm, Gunnar Gunnarsson
Repetition
 En dator består i princip av processor, minne, indataenheter och utdataenheter.
 Processorn förstår bara enkla instruktioner, maskinkod.
 C-program översätts till maskinkod av en kompilator.
 C skapades för att skriva operativsystem - det var därför viktigt att språket ”låg nära”
maskinkoden, så att det gick att skriva snabba program.
 Att skriva direkt i maskinkod kan ge snabbare program, men det är mycket krångligare.
 Dessutom blir man låst till en viss maskin. C-program kan kompileras om för olika maskiner.
 Det finns strikta regler för hur ett C-program skall se ut - det är bra för det förhindrar
missförstånd.
 Ett datorprogram kan ses som en följd av beräkningar.
 Datorprogram innehåller dock några saker som inte finns i vanliga beräkningar:
Variabler
Val
Slingor/loopar
(platser att lagra värden)
(göra på olika sätt i olika situationer)
(göra samma sak flera gånger)
Programmeringsteknik för mediaingenjörer, ht -98
13
Niklas Frykholm, Gunnar Gunnarsson
Egendefinierade funktioner (egna kodblock som kan användas på många ställen)
Repetition
 En algoritm är en detaljerad beskrivning av hur man kan gå till väga för att lösa ett visst
problem.
 Det finns inga generella metoder för att konstruera algoritmer, men divide & conquer (dela upp
i delproblem och lös dessa) är en bra strategi.
 Det svåraste är i allmänhet att komma på en bra algoritm. När vi har en algoritm är det relativt
enkelt att skriva om den i ett programspråk.
Programmeringsteknik för mediaingenjörer, ht -98
14
Niklas Frykholm, Gunnar Gunnarsson
#include <stdio.h>
int main(void)
{
int i;
/* Deklarerar en heltalsvariabel. */
float f; /* Deklarerar en flyttalsvariabel. */
printf("Hej!\n");
printf("Skriv in ett heltal: ");
scanf("%i",&i);
printf("Du skrev in talet %i.\n", i);
printf("Skriv in ett decimaltal: ");
scanf("%f", &f);
printf("Du skrev in talet %f.\n", f);
}
Programmeringsteknik för mediaingenjörer, ht -98
15
int main(void)
{
int i, k, j;
double x;
long double ld;
unsigned char c;
long r = 14;
float f = 3.75;
...
Niklas Frykholm, Gunnar Gunnarsson
Programmeringsteknik för mediaingenjörer, ht -98
16
Niklas Frykholm, Gunnar Gunnarsson
#include <stdio.h>
int main(void)
{
char c;
printf("Skriv in ett tecken: ");
scanf("%c", &c);
printf("Tecknets talvärde är %i\n",c);
/* Om c ligger mellan 'A' och 'Z' */
if (c >= 'A' && c <= 'Z')
c = c – 'A' + 'a';
printf("Omvandlat till gemener är tecknet %c.\n", c);
}
Programmeringsteknik för mediaingenjörer, ht -98
17
Niklas Frykholm, Gunnar Gunnarsson
#include <stdio.h>
int main(void)
{
int i, j;
int summa;
float x, y, res;
printf("Skriv in två heltal: ");
scanf("%i %i", &i, &j);
summa = i + j;
printf("Summan blir %i.\n", summa);
printf("Beräkningen ser ut som %i + %i = %i.\n",
i, j, summa);
printf("%5i + %5i = %5i\n", i, j, summa);
printf("Skriv in två decimaltal: ");
scanf("%f %f", &x, &y);
res = x * y;
Programmeringsteknik för mediaingenjörer, ht -98
18
Niklas Frykholm, Gunnar Gunnarsson
printf("%f * %f = %f\n", x, y, res);
printf("%6.2f * %6.2f = %6.2f\n", x, y, res);
}
int a[4]; /* Fyra heltal */
int x[4] = {0, 1, 2, 3};
int r[] = {5, 6, 7};
Programmeringsteknik för mediaingenjörer, ht -98
19
Niklas Frykholm, Gunnar Gunnarsson
#include <stdio.h>
int main(void)
{
char namn[50];
char halsning[] = "Hejsan";
printf("Skriv ditt namn: ");
scanf("%s", namn);
printf("%s %s!\n", halsning, namn);
}
Programmeringsteknik för mediaingenjörer, ht -98
20
Niklas Frykholm, Gunnar Gunnarsson
Repetition
 En bit är ett tal som är 0 eller 1. En byte byggs upp av 8 bitar: 00011101.
 En byte betyder i sig ingenting, för att veta hur vi ska tolka bitarna måste vi veta vilken typ av data byten innehåller.
 Vi kan t ex tolka byten som ett positivt binärt tal, då kan vi lagra tal mellan 0 och 255. Vi kan också tolka byten som
ett tal med tecken (där första biten anger tecknet). Då kan vi lagra tal mellan -128 och +127.
 Om vi vill lagra större heltal än så kan vi använda fler bytes. C har fyra heltalstyper: char, short, int och long. En
char rymmer minst och en long mest. Normalt arbetar vi med typen int. Varje heltalstyp kan dessutom vara signed
eller unsigned.
 Ett flyttal (2.35*107) består av decimaldel (2.35) och exponent (7). Ju mer minne vi har för exponenten, desto större
tal kan vi lagra. Ju mer minne vi har för decimaldelen, desto bättre noggrannhet (= mindre avrundningsfel) får vi.
 C:s flyttalstyper heter float, double och long double.
 Om vi skriver ett vanligt tal i koden (3, 45, 6) får det typen int (eller long om det är för stort för en int). Skriver vi ett
decimaltal i koden (3.2, 3., 4e10, .0) så får det typen double.
 En variabeldeklaration kan t ex se ut som const unsigned long u = 70000;
 const talar om att variabelns värde inte kan ändras i programmet. Variabeln får vid programmets start värdet 70000.
(Om vi inte anger något värde får variabeln ett slumpmässigt värde.)
 När man programmerar använder man ofta hexadecimala och oktala tal. I C tolkas 0xab hexadecimalt och ger värdet
(10 * 16 + 11 = 171). 054 tolkas oktalt och ger värdet (5 * 8 + 4 = 44).
 printf och scanf används för in- och utmatning av data.
Programmeringsteknik för mediaingenjörer, ht -98
21
Niklas Frykholm, Gunnar Gunnarsson
Repetition
 Ett fält är en speciell typ av varibel som innehåller ett antal positioner. Varje position fungerar som en egen variabel.
 Om vi skapar ett fält med int a[4] kan vi sedan använda a[0], a[1], a[2] och a[3] som vanliga variabler.
 Vi måste se upp så att vi inte råkar använda a[-1] eller a[5]. Det ger fel och vi får inga varningar från kompilatorn.
 Vi kan inte kopiera fält genom tilldelning: a = b. Vill vi kopiera fält måste vi skriva en loop som kopierar varje
position i fältet för sig.
 Tecken/bokstäver skrivs i C med enkla citationstecken 'a'.
 Varje tecken motsvarar/representeras av ett visst tal. 'A' motsvarar t ex 64.
 C gör ingen skillnad på tal och tecken. Vi kan använda varje tecken precis som det tal det motsvarar, t ex 'A' + 1.
 Tecken lagras i vanliga heltalsvariabel, vanligen används char..
 En sträng är ett stycke text, t ex "Hejsan" och "Hallå".
 I C lagras strängen som ett fält av tecken (char s[20]). En nolla i fältet markerar var strängen tar slut.
 När en beräkning utförs mellan två tal i C måste talen först omvandlas till samma typ. Det tal som är av "mindre
typ" omvandlas till den större typen. I 2.0 + 3 omvandlas 3 till 3.0.
 Resultatet av en beräkning får alltid samma typ som talen i beräkningen. 11/3 ger således ett resultatet 3 (av typen
int), eftersom det riktiga resultatet (3.66666....) inte kan lagras i en int. Vi kan skriva 11.0/3 för att få rätt resultat.
 Skrivsättet (float)x omvandlar värdet i variabeln x till en float. Det är nödvändigt för att få rätt resultat när vi delar
heltalsvariabler. Divisionen x/y, kan alltså skrivas som (float)x/y.
Programmeringsteknik för mediaingenjörer, ht -98
22
Niklas Frykholm, Gunnar Gunnarsson
/* Maskning, plocka ut de 8 bitarna */
/* längst till höger */
j = i & 0xff;
/* Sätta bit – sätta biten i position n */
i = i | (1 << n);
/* Rensa bit - rensa biten i position n */
i = i & ~(1 << n);
/* Inspektera bit – vilket värde har biten */
/* i position n */
j = (i >> n) & 1;
Programmeringsteknik för mediaingenjörer, ht -98
Niklas Frykholm, Gunnar Gunnarsson
23
/* Alla variabler får värdet 0. */
i = j = k = 0;
/* Detta uttryck har värdet 4. */
(i = 3) + (k = j = 1);
i
i
i
i
+= 3;
*= 2;
>>= 2;
&= 0xA;
/*
/*
/*
/*
Samma
Samma
Samma
Samma
som
som
som
som
i
i
i
i
=
=
=
=
i
i
i
i
+ 3 */
* 2 */
>> 2 */
& 0xA */
Programmeringsteknik för mediaingenjörer, ht -98
24
Niklas Frykholm, Gunnar Gunnarsson
Repetition - Operatorer
 Operatorer är symboler som vi räknar med: + - * / .. osv.
 Operander är det som operatorerna arbetar på. Operatorer och operander bildar tillsammans uttryck.
 I vilken ordning operatorerna i ett uttryck skall beräknas bestäms av deras prioritet. Operatorn med högst prioritet
beräknas först. I a = 3 * 4 + 2; beräknas multiplikationen först eftersom * har högst prioritet. Tilldelningen utförs
allra sist eftersom = har lägst prioritet.
 Om operatorerna har samma prioritet bestäms i stället beräkningsordningen av associativiten. Om operatorn är
vänsterassociativ beräknas uttrycket längst till vänster först. Är den högerassociativ beräknas uttrycket längst till
höger först: i = j = 2 - 3 + 4 beräknas som i = (j = ( (2 -3) + 4) ) eftersom + är vänsterassociativ och =
högerassociativ.
 Unära operatorer (en operand) har alltid högre prioritet än binära. Postfixoperatorer (står efter variabeln) har högre
prioritet än prefix.
Programmeringsteknik för mediaingenjörer, ht -98
25
Niklas Frykholm, Gunnar Gunnarsson
Repetition - Operatorer (forts.)
 Matematiska
+ - * / %
% ger resten vid heltalsdivision
 Ökning/minskning
++ --
finns i prefix- och postfix-variant med olika innebörd
 Jämförelse
< > <= >= == !=
skilj på = och ==
 Logiska
&& || !
kortsluten utvärdering
 Bit-operatorer
& | ~ ^ >> <<
kan användas för att sätta/rensa en viss bit
 Konstiga operatorer
[]
elementoperatorn - hämta ett element ur ett fält a[3]
()
funktionsanropsoperatorn - printf(”hej”)
sizeof
ger antalet bytes som en typ eller variabel använder
?:
villkorsoperatorn - liten if-sats: x = b > 3 ? ”j” : ”n”;
,
kommaoperatorn - staplar uttryck
Programmeringsteknik för mediaingenjörer, ht -98
26
Niklas Frykholm, Gunnar Gunnarsson
/* Satser med sidoeffekter. */
i = 3;
printf("Hej");
/* Satser utan sidoeffekter. */
2 + 3;
;;;;
/* Några tomma satser – de är tillåtna i C */
/* Satsblock */
{
a = b + 3;
c = 2 * a;
}
Programmeringsteknik för mediaingenjörer, ht -98
27
/* Variabeldeklarationer */
{
int a, c;
c = 2;
a = 2 * c;
{
int b;
b = 2*c – a;
a = a + b;
}
}
Niklas Frykholm, Gunnar Gunnarsson
Programmeringsteknik för mediaingenjörer, ht -98
28
Niklas Frykholm, Gunnar Gunnarsson
/* En inre variabel döljer en yttre. */
{
int a;
{
long a;
/* a är en long här */
}
/* och en int här */
}
Programmeringsteknik för mediaingenjörer, ht -98
if (uttryck1)
sats1
else if (uttryck2)
sats2
else if ...
...
else
sats_n
29
Niklas Frykholm, Gunnar Gunnarsson
Programmeringsteknik för mediaingenjörer, ht -98
30
Niklas Frykholm, Gunnar Gunnarsson
if (n > 0)
medel = sum / n;
if (a > b) {
temp = b;
b = a;
a = temp;
}
/* Vi kan undvika satsblock genom att skriva
om det sista uttrycket på följande sätt (men
det är inte att rekommendera). */
if (a > b)
temp = b, b = a, a = temp;
Programmeringsteknik för mediaingenjörer, ht -98
31
Niklas Frykholm, Gunnar Gunnarsson
if (command == 'q')
printf("Avslutar programmet.");
else if (command == 's')
printf("Sparar dokumentet.");
else if (command == 'n')
printf("Skapar nytt dokument.");
else
printf("Okänt kommando!");
Programmeringsteknik för mediaingenjörer, ht -98
32
/* Dangling else problem */
if (a < 3)
if (a < -1)
printf("a är för litet");
else
printf("a är för stort");
if (a < 3) {
if (a < -1)
printf("a är för litet");
}
else
printf("a är för stort");
Niklas Frykholm, Gunnar Gunnarsson
Programmeringsteknik för mediaingenjörer, ht -98
33
switch (heltalsuttryck) {
case konstant_heltalsuttryck:
satser
break;
case konstant_heltalsuttryck:
satser
break;
...
default:
satser
break;
}
Niklas Frykholm, Gunnar Gunnarsson
Programmeringsteknik för mediaingenjörer, ht -98
34
Niklas Frykholm, Gunnar Gunnarsson
switch (command) {
case 'q':
printf("Avslutar programmet");
break;
case 's':
printf("Sparar dokumentet");
break;
case 'n':
printf("Skapar nytt dokument");
break;
default:
printf("Ogiltigt kommando");
break;
Programmeringsteknik för mediaingenjörer, ht -98
}
35
Niklas Frykholm, Gunnar Gunnarsson
Programmeringsteknik för mediaingenjörer, ht -98
36
Niklas Frykholm, Gunnar Gunnarsson
switch (command) {
case 'q': case 'Q':
printf("Avslutar programmet");
break;
case 's': case 'S':
printf("Sparar dokumentet");
break;
...
Programmeringsteknik för mediaingenjörer, ht -98
37
Niklas Frykholm, Gunnar Gunnarsson
printf("Vill du fortsätta? (j/n) ");
scanf("%c", &c);
while (c != 'j' && c != 'n')
{
printf("Vill du fortsätta? (j/n) ");
scanf(" %c", &c);
}
Programmeringsteknik för mediaingenjörer, ht -98
38
Niklas Frykholm, Gunnar Gunnarsson
c = 'X';
while (c != 'j' && c != 'n')
{
printf("Vill du fortsätta? (j/n) ");
scanf(" %c", &c);
}
do {
printf("Vill du fortsätta? (j/n) ");
scanf(" %c", &c);
} while (c != 'j' && c != 'n');
Programmeringsteknik för mediaingenjörer, ht -98
39
Niklas Frykholm, Gunnar Gunnarsson
for (i = 1; i < 10; i++)
{
...
for (uttryck_1; uttryck_2; uttryck_3)
sats
uttryck_1;
while (uttryck_2) {
sats
uttryck_3;
}
Programmeringsteknik för mediaingenjörer, ht -98
40
Niklas Frykholm, Gunnar Gunnarsson
for (i = i_start, j = j_start; i < i_max && j < j_max;
i++, j += i)
;
for (;;) /* En oändlig loop */
for (i=1; i<=3;i++)
for (j=1; j<=2; j++)
printf("%i, %i\n", i, j);
/*
1,
1,
2,
2,
3,
3,
Ger utskriften: */
1
2
1
2
1
2
Programmeringsteknik för mediaingenjörer, ht -98
41
Niklas Frykholm, Gunnar Gunnarsson
/* Ännu en variant av ett exempel som vi
har sett tidigare. */
for (;;) {
printf("Vill du fortsätta? (j/n) ");
scanf(" %c", &c);
if (c == 'j' || c == 'n')
break;
printf("Du måste svara med j eller n.\n");
}
Programmeringsteknik för mediaingenjörer, ht -98
42
Niklas Frykholm, Gunnar Gunnarsson
while (uttryck)
sats
do
sats
while (uttryck)
do {
printf("Vill du fortsätta? (j/n) ");
scanf(" %c", &c);
if (c != 'j' && c != 'n')
printf("Du måste svara med j eller n.\n");
} while (c != 'j' && c != 'n');
Programmeringsteknik för mediaingenjörer, ht -98
43
Niklas Frykholm, Gunnar Gunnarsson
/* Läser in tio tal mellan 1 och 10 */
int main(void)
{
int tal[10];
int lasta = 0;
int summa;
while (lasta < 10)
{
scanf("%i", &tal[lasta]);
if (tal[lasta] < 1 || tal[lasta] > 10)
continue;
lasta++;
summa+=tal[lasta];
}
...
Programmeringsteknik för mediaingenjörer, ht -98
}
44
Niklas Frykholm, Gunnar Gunnarsson
Programmeringsteknik för mediaingenjörer, ht -98
45
Niklas Frykholm, Gunnar Gunnarsson
int main(void)
{
int tal[10];
int lasta = 0;
int summa;
while (lasta < 10)
{
scanf("%i", &tal[lasta]);
if (tal[lasta] >= 1 && tal[lasta] <= 10) {
lasta++;
summa+=tal[lasta];
}
}
...
Programmeringsteknik för mediaingenjörer, ht -98
}
46
Niklas Frykholm, Gunnar Gunnarsson
Programmeringsteknik för mediaingenjörer, ht -98
47
Niklas Frykholm, Gunnar Gunnarsson
if (i>10)
goto done;
...
done:
/* Här fortsätter programkoden. */
Programmeringsteknik för mediaingenjörer, ht -98
48
for (i=0; i<a_len; i++)
for (j=i+1; j<a_len; j++)
if (a[i] > a[j]) {
temp = a[i];
a[i] = a[j];
a[j] = temp;
}
Niklas Frykholm, Gunnar Gunnarsson
Programmeringsteknik för mediaingenjörer, ht -98
49
i=0;
loop_1: if (i<a_len) goto out_1;
j=i+1;
loop_2: if (j<a_len) goto out_2;
if (a[j] > a[i]) goto next_2;
temp = a[i];
a[i] = a[j];
a[j] = temp;
next_2: j++;
goto loop_2;
out_2: i++;
goto loop_1;
out_1:
Niklas Frykholm, Gunnar Gunnarsson
Programmeringsteknik för mediaingenjörer, ht -98
Niklas Frykholm, Gunnar Gunnarsson
50
Repetition
 Ett C-program är uppbyggt av satser.
 En enkel sats är ett utryck följt av ett semikolon. Uttrycket behöver inte ha någon mening.
a = 3;
5;
;
a < 7;
i++;
a = 3, b = 2;
 En sammansatt sats består av ett antal satser inom krullparenteser. När satsen utförs så utförs var och en av satserna
inom krullparenteserna i tur och ordning. Fastän en sammansatt sats kan innehålla många satser så är den själv bara
en enda sats och kan användas över allt där satser kan användas.
 Vi kan ha deklarationer av variabler i början av en sammansatt sats.
{
int temp = a;
b = temp * 2;
}
 Förutom enkla och sammansatta satser innehåller C även kontrollsatser i form av val (if / switch) och loopar (while /
for).
 Satsen break hoppar ut ur en loop. Satsen continue hoppar till nästa varv av loopen.
 C innehåller också en goto-sats som låter oss hoppa hur som helst i ett program, men den ska ni inte använda.
Programmeringsteknik för mediaingenjörer, ht -98
51
Niklas Frykholm, Gunnar Gunnarsson
Programmeringsteknik för mediaingenjörer, ht -98
/* En enkel funktion */
int ganger_tva (int i)
{
return 2*i;
}
52
Niklas Frykholm, Gunnar Gunnarsson
Programmeringsteknik för mediaingenjörer, ht -98
53
Niklas Frykholm, Gunnar Gunnarsson
/* Pre: c innehåller något tecken.
Post: om tecknet är en svensk versal returneras
motsvarande gemen, annars returneras
tecknet oförändrat. */
char gemen(char c)
{
if (c >= 'A' && c <= 'Z')
return c – 'A' + 'a';
else
switch (c) {
case 'Å': return 'å';
case 'Ä': return 'ä';
case 'Ö': return 'ö';
}
return c;
}
Programmeringsteknik för mediaingenjörer, ht -98
54
#include <stdio.h>
int dubbla(int a)
{
a = a * 2;
return a;
}
void main(void)
{
int a, b;
a = 3;
b = dubbla(a);
printf("%i\n%i\n",a,b);
}
Niklas Frykholm, Gunnar Gunnarsson
Programmeringsteknik för mediaingenjörer, ht -98
int f_1(int i);
double f_2 (double x);
void main(void)
{
...
int f_1(int i)
{
...
double f_2 (double x)
{
...
55
Niklas Frykholm, Gunnar Gunnarsson
Programmeringsteknik för mediaingenjörer, ht -98
56
Niklas Frykholm, Gunnar Gunnarsson
/* Detta går bra. */
#include <math.h>
/* Men om vi bara använder sin-funktionen är det
ibland enklare att direkt skriva: */
double sin(double x);
/* Det här går också, sin har bara en parameter. */
double sin(double);
/* Svårförståeligt – vad ska parametrarna ges för
värden? */
double effektiv_ranta(double, int, double);
/* Detta är bättre. */
double effektiv_ranta(double lanstorlek, int
aterbetalningstid, double manadskostnad);
Programmeringsteknik för mediaingenjörer, ht -98
57
Niklas Frykholm, Gunnar Gunnarsson
/* Returnerar fakulteten av ett positivt tal n. */
int fak(int n)
{
return n==0 ? 1 : n*fak(n-1);
}
Programmeringsteknik för mediaingenjörer, ht -98
58
Niklas Frykholm, Gunnar Gunnarsson
/* Denna funktion skriver ut ett tals bitmönster.
Talet ska ligga mellan 0 och 255.
Funktionen returnerar det tal som skickas in.
*/
int print_bits(int x)
{
int i;
for (i=128; i>=0; i/=2) {
if (x & i)
printf("1");
else
printf("0");
}
return x;
}
Programmeringsteknik för mediaingenjörer, ht -98
59
Niklas Frykholm, Gunnar Gunnarsson
#include <stdio.h>
void test(int x)
{
printf("I test x = %i.\n", x);
x = 7;
printf("I test x = %i.\n", x);
}
int main(void)
{
int x = 10, y = 12;
printf("x = %i, y = %i\n", x, y);
test(y);
printf("x = %i, y = %i\n", x, y);
test(x);
}
Programmeringsteknik för mediaingenjörer, ht -98
60
Niklas Frykholm, Gunnar Gunnarsson
/* Rekursiv beräkning av funktionen upphöjt till. */
int upphojt_till(int x, int y)
{
if (y==0)
return 1;
else
return x * upphojt_till(x, y-1);
}
Programmeringsteknik för mediaingenjörer, ht -98
61
Niklas Frykholm, Gunnar Gunnarsson
/* Rekursiv funktion för att hitta det största talet
från och med position start till och med position stopp
i en lista. (Notera att vi inte behöver någon
for-loop.) */
void max(int lista[], int start, int stopp)
{
/* Om start == stopp finns det bara ett tal i listan,
och då är det givetvis störst. */
if (start == stopp)
return lista[start];
else { /* Annars delar vi listan i två halvor. */
int mitt, max1, max2;
mitt = (start + stopp)/2;
max1 = max(lista, start, mitt);
max2 = max(lista, mitt + 1, stopp);
return max1 > max2 ? max1 : max2;
}
}
Programmeringsteknik för mediaingenjörer, ht -98
62
Niklas Frykholm, Gunnar Gunnarsson
/* Skriver ut strängen s baklänges med början i
positionen start. */
void print_reverse(char s[], int start)
{
if (s[start]!=0) {
print_reverse(s, start+1);
printf("%c", s[start]);
}
}
Algoritm:
1. Skriv först ut resten av strängen (från start+1 till slutet) baklänges.
2. Skriv sedan ut det första tecknet.
 Problemet blir mindre och mindre (den sträng vi skall skriva ut baklänges blir kortare och kortare).
 När problemet är tillräckligt litet (när strängen vi skall skriva ut inte innehåller några tecken alls) avbryts
rekursionen.
Programmeringsteknik för mediaingenjörer, ht -98
63
Niklas Frykholm, Gunnar Gunnarsson
Repetition
 En funktion är en bit kod som utför någonting, t ex beräknar ett värde eller skriver ut någonting på skärmen.
 När vi väl har skrivit funktionen kan vi använda den på många olika ställen i vårt program. Att använda den kallas
för att göra ett funktionsanrop. När vi anropar funktionen kan vi skicka med ett antal parametrar - dessa värden
skickas till funktionen och används för att beräkna ett returvärde som sedan skickas tillbaka till huvudprogrammet.
 Ett funktionsanrop kan ingå i ett komplicerat uttryck, precis som när vi räknar i matematiken.
x = sin(3 + cos(x)) * a;
 En funktionsparameter "finns bara" i själva funktionskroppen (precis som variabler som skapas i ett satsblock). Det
kan finnas variabler med samma namn på andra ställen i programmet, men dessa har ingenting att göra med
parametrarna och de olika variablerna påverkar inte varandra.
 När vi anropar en funktion så kopieras värdet vi skickar in till den lokala parametern. Vi kan ändra den lokala
parametern i funktionen, men det påverkar inte värdet som vi skickade in.
 När vi definierar funktioner kan vi använda den speciella datatypen void, som betyder ingenting. En funktion vars
returtyp är void returnerar ingenting. En funktion vars parameterlista är void tar inga parametrar.
 Varje funktion i programmet bör ha en tydlig och avgränsad uppgift. Framför varje funktion sätter vi en kommentar,
som beskriver vad funktionen gör, vilka parametrar den tar, vilket värde den returnerar och om den har några
begränsningar. (Detta skall även finnas med i labrapporten under rubriken "Systembeskrivning".)
Programmeringsteknik för mediaingenjörer, ht -98
64
Niklas Frykholm, Gunnar Gunnarsson
Repetition
 Om vi vill placera våra funktioner efter main-funktionen (eller, mer generellt, efter den funktion där de anropas)
måste vi först tala om att de finns. Det gör vi med en funktionsdeklaration (”funktionsprototyp”) överst i
programmet. Funktionsdeklarationen består av funktionshuvudet följt av ett semikolon.
 Syftet med funktionsprototypen är att ange funktionens returtyp och parametertyper, så att kompilatorn kan
kontrollera att den används på rätt sätt.
 Själva funktionsdefinitionen behöver inte finnas i vårt program, det räcker om den finns någonstans. Funktionsdeklarationen måste dock finnas i programmet. Vad som händer när vi använder en #include-sats är att en fil med
funktionsdeklarationer klistras in i programmet.
 En rekursiv funktion är en funktion som anropar sig själv för att lösa ett problem. För att rekursion skall fungera
krävs två saker. Problemet måste bli "mindre och mindre" varje gång vi anropar oss själva. Det måste också finnas
ett stoppfall (”basfall”), när problemet har blivit tillräckligt litet för att lösas utan att vi anropar oss själva.
Programmeringsteknik för mediaingenjörer, ht -98
65
Niklas Frykholm, Gunnar Gunnarsson
Programmeringsteknik för mediaingenjörer, ht -98
66
Niklas Frykholm, Gunnar Gunnarsson
Programmeringsteknik för mediaingenjörer, ht -98
67
Niklas Frykholm, Gunnar Gunnarsson
/* En variabel som står utanför funktioner blir global. */
#include <stdio.h>
int x; /* x är global */
int main(void)
{
/* Vi kan använda x här. */
}
void test(void)
{
/* Och här */
}
void test2(int x)
{
/* Här kommer vi inte åt den globala variabeln x,
eftersom den döljs av funktionens egna parameter x. */
Programmeringsteknik för mediaingenjörer, ht -98
}
68
Niklas Frykholm, Gunnar Gunnarsson
Programmeringsteknik för mediaingenjörer, ht -98
69
Niklas Frykholm, Gunnar Gunnarsson
/* Om vi vill komma åt x i en annan fil måste vi använda
extern. */
extern int x;
/* När vi använder extern får vi en variabeldeklaration,
utan extern får vi en variabeldefinition. Precis som för
funktioner så måste vi deklarera variabeln i varje fil där
vi vill använda den. Vi får dock bara definiera den en
enda gång. */
Programmeringsteknik för mediaingenjörer, ht -98
70
Niklas Frykholm, Gunnar Gunnarsson
/* En funktion som håller reda på hur många
gånger den anropats och returnerar det värdet.
Fråga: Vad skulle hända om count inte
deklarerats static? */
int raknare(void)
{
static int count = 0;
return ++count;
}
Programmeringsteknik för mediaingenjörer, ht -98
71
Niklas Frykholm, Gunnar Gunnarsson
void test(void)
{
static int i=0; /* Skapas när programmet startar. */
int j=0;
/* Skapas varje gång funktionen anropas. */
i++;
j++;
}
Programmeringsteknik för mediaingenjörer, ht -98
72
Niklas Frykholm, Gunnar Gunnarsson
Gör om mig (del 1 av 6)
Före
Efter
#include <math.h>
double sin(double x);
double cos(double x);
double sqrt(double x);
...
int main(void)
{
...
}
int main(void)
{
...
}
Programmeringsteknik för mediaingenjörer, ht -98
73
Niklas Frykholm, Gunnar Gunnarsson
Gör om mig (del 2 av 6)
Före
#define N
#define HEJ
Efter
100
int main(void)
printf("Hej!\n"); {
int a[100], i;
int main(void)
for (i=0; i<100; i++)
{
a[i] = i;
int a[N], i;
printf("Hej!\n");
for (i=0; i<N; i++)
}
a[i] = i;
HEJ
...
}
Programmeringsteknik för mediaingenjörer, ht -98
74
Niklas Frykholm, Gunnar Gunnarsson
Gör om mig (del 3 av 6)
Före
#define MAX(x,y)
#define loop
#define exit_on(x)
Efter
x > y ? x : y
while(1)
if (x) break;
int main(void)
{
loop {
...
exit_on(y == -1);
...
}
a = MAX(sin(b), 0.5);
...
}
int main(void)
{
while(1) {
...
if (y==-1) break;;
...
}
a = sin(b) > 0.5 ?
sin(b) : 0.5;
...
}
Programmeringsteknik för mediaingenjörer, ht -98
75
Niklas Frykholm, Gunnar Gunnarsson
Gör om mig (del 4 av 6)
Före
Efter
#define KVAD(x) x * x
int main(void)
#define KVAD2(x) (x) * (x)
{
#define KVAD3(x) ( (x) * (x) )
...
a = 3+2 * 3+2;
int main(void)
b = (3+2) * (3+2);
{
c = ~(7) * (7);
...
d = ~( (7) * (7) );
a = KVAD(3+2);
e = ( (x++) * (x++) );
b = KVAD2(3+2);
}
c = ~KVAD2(7);
d = ~KVAD3(7);
e = KVAD3(x++);
}
Programmeringsteknik för mediaingenjörer, ht -98
76
Niklas Frykholm, Gunnar Gunnarsson
Gör om mig (del 5 av 6)
Före
Efter
#define LANG 1
int main(void)
{
printf("What is your name?");
...
}
int main(void)
{
#if LANG == 0
printf("Vad heter du?");
#elif LANG == 1
printf("What is your name?");
#elif LANG == 2
printf("Was ist dein name?");
#else
printf("Tu t'apelles quoi?");
#endif
...
}
Programmeringsteknik för mediaingenjörer, ht -98
77
Niklas Frykholm, Gunnar Gunnarsson
Gör om mig (del 6 av 6)
Före
Efter
#define DEBUG
int main(void)
{
...
printf("x = %i\n", x);
...
}
int main(void)
{
...
#ifdef DEBUG
printf("x = %i\n", x);
#endif
...
}
Programmeringsteknik för mediaingenjörer, ht -98
78
Niklas Frykholm, Gunnar Gunnarsson
Repetition
 Ett C-program kompileras i tre steg: Preprocessorn klistrar in och klipper ut text. Kompilatorn omvandlar till
maskinkod och länkaren klistrar ihop flera maskinkodsfiler till ett färdigt program.
 Preprocessorn förbehandlar ett program genom att klippa och klistra i texten. Kommandon till preprocessorn börjar
med #.
 För att dela upp ett projekt på flera filer gör vi en header-fil för varje C-fil. I header-filen lägger vi alla deklarationer
som behövs för att komma åt funktionerna i C-filen.
 En variabel som definieras utanför en funktion blir global och kan användas av alla funktioner i alla filer.
 För att komma åt den i en annan fil är den där den är skapad måste vi dock deklarera variabeln (= tala om att den
finns). En variabeldeklaration ser ut som en variabeldefinition, men med ordet extern framför.
extern int x;
 Nyckelordet static låter oss skapa globala variabler som bara är synliga i vissa delar av koden. En global variabel
som är deklarerad static finns bara i den fil där den definieras.
static int i;
 Vi kan också använda static inuti en funktion. Vi får då en global variabel som vi bara kan komma åt inuti
funktionen. (Notera att variabeln fortfarande är global, så den skapas och förstörs med programmet, inte med
funktionen. Man kan säga att den har global livslängd men lokal räckvidd.)
Programmeringsteknik för mediaingenjörer, ht -98
79
Niklas Frykholm, Gunnar Gunnarsson
void main(void)
{
int i1 = 1, i2 = 2;
int *p1, *p2;
p1 = &i1;
p2 = &i2;
*p1 = *p2;
p1 = p2;
*p1 = 4;
}
/*
/*
/*
/*
/*
p1 pekar nu på i1... */
och p2 på i2 */
i1 får nu värdet 2 */
p1 pekar nu på i2 */
i2 får nu värdet 4 */
Programmeringsteknik för mediaingenjörer, ht -98
80
Niklas Frykholm, Gunnar Gunnarsson
#include <stdio.h>
void dubbel(int *a);
void main(void)
{
int a = 3;
dubbel(&a);
printf("%i\n", a);
}
void dubbel(int *a);
{
*a *= 2;
}
/* Skriver ut 6 */
Programmeringsteknik för mediaingenjörer, ht -98
81
Niklas Frykholm, Gunnar Gunnarsson
#include <stdio.h>
int *test(void);
void main(void)
{
int *a;
a = test();
*a = 3;
/* Inte bra – variabeln finns */
/* inte längre. */
}
int *test(void)
{
int b = 5;
return &b;
Programmeringsteknik för mediaingenjörer, ht -98
}
82
Niklas Frykholm, Gunnar Gunnarsson
Programmeringsteknik för mediaingenjörer, ht -98
83
Niklas Frykholm, Gunnar Gunnarsson
/* Reserverar plats för 100 heltal (int). */
int *a;
a = malloc(sizeof(int)*100);
if (a == NULL)
{error();} /* Det är inte säkert vi får minnet. */
/* Vi kan nu komma åt minnet vi har allokerat som ett
fält (eftersom pekare och fält är utbytbara). */
a[45] = 3;
Programmeringsteknik för mediaingenjörer, ht -98
84
Niklas Frykholm, Gunnar Gunnarsson
/* a är en konstant pekare till en föränderlig variabel.
Deklarationen utläses som "konstant pekare till char". */
char * const a;
/* b är en pekare till en konstant char. */
char const * b;
const char * b;
/* c är en konstant pekare till en konstant char. */
const char * const c;
/* Detta är tillåtna operationer. */
(*a)++;
b++;
/* Detta är otillåtna operationer (ger varning i C, */
/* fel i C++). */
a++;
(*b)++;
c++;
(*c)++;
Programmeringsteknik för mediaingenjörer, ht -98
85
Niklas Frykholm, Gunnar Gunnarsson
/* En vanlig funktion deklareras t ex på följande
sätt. */
int f(int);
/* En funktionspekare till en sådan funktion
deklareras nu som (utläses f pekar på och sedan en
vanlig funktionsdeklaration) */
int (*f)(int);
/* Notera speciellt att följande inte duger ty ()
är en postfix unär operator och har företräde
framför den prefixa unära operatorn *. Detta blir
en funktion som returnerar pekare till int. */
int *f(int);
Programmeringsteknik för mediaingenjörer, ht -98
86
Niklas Frykholm, Gunnar Gunnarsson
#include <stdio.h>
/* Exempel på funktionspekare. */
int kvadrat(int);
int summera_fran_till(int, int, int (*f)(int));
void main(void)
{
int x;
x = summera_fran_till(1,5,kvadrat);
printf("1^2 + 2^2 + ... + 5^2 = %i", x);
}
int kvadrat(int x)
{
return x*x;
}
Programmeringsteknik för mediaingenjörer, ht -98
87
Niklas Frykholm, Gunnar Gunnarsson
int summera_fran_till(int start, int stop, int (*f)(int))
{
int i, sum = 0;
for (i=start; i<=stop; i++)
sum += f(i);
return sum;
}
Programmeringsteknik för mediaingenjörer, ht -98
88
Niklas Frykholm, Gunnar Gunnarsson
Repetition
 En pekare är en variabel som pekar på en annan variabel.
 Vi deklarerar en pekare som en vanlig variabel, men med en * mellan typen och variabelnamnet.
 För att använda pekare behöver vi två nya operatorer: & ger oss en pekare till en variabel (&i ger oss en pekare till
i). * ger oss det som en pekare pekar på (*p ger oss det som p pekar på, dvs i).
 Den speciella konstanten NULL kan användas för en pekare som inte pekar på någonting. (p = NULL)
 Vi kan skriva en funktion som ändrar en variabels värde genom att skicka in en pekare till variabeln till funktionen:
dubbel(&i);
...
void dubbel(int *a)
{ *a = *a * 2; }
 Man kan också låta en funktion returnera en pekare. Man får dock inte returnera pekare till lokala variabler eftersom
de försvinner när funktionen returnerar - vi får i så fall en pekare till någonting som inte finns.
Programmeringsteknik för mediaingenjörer, ht -98
89
Niklas Frykholm, Gunnar Gunnarsson
#include <stdio.h>
char dagar[7][20] = {"Måndag", "Tisdag",
"Onsdag", "Torsdag", "Fredag",
"Lördag", "Söndag"};
int main(void)
{
int i;
for (i=0; i<7; i++)
printf("%i. %s\n", i+1, dagar[i]);
return 0;
}
Programmeringsteknik för mediaingenjörer, ht -98
Niklas Frykholm, Gunnar Gunnarsson
90
Strängar som fält och strängar som pekare
s1
h
e
j
0
h
e
j
0
0
0
0
0
0
0
s2
 s1 pekar på strängen hej som finns lagrad i programkoden.
 Vi kan sätta s1 att peka på en annan sträng, men vi kan inte ändra det som s1 pekar på. (Eftersom vi på de flesta
datorsystem inte får ändra vår egen programkod.)
 Deklarationen av s2 skapar ett fält med tio positioner. s2 pekar på den första positionen.
 Vi kan ändra det som s2 pekar på.
 Däremot kan vi inte sätta s2 att peka på någonting annat. s2 pekar alltid på det fält som den hör till.
Programmeringsteknik för mediaingenjörer, ht -98
91
/* Inte bra - vi läser till en */
/* slumpmässig plats i minnet. */
char *s;
scanf("%s", s);
/* Detta är däremot OK! */
char s[80];
scanf("%s", s);
Niklas Frykholm, Gunnar Gunnarsson
Programmeringsteknik för mediaingenjörer, ht -98
92
/* Utskrift av sträng */
void print_string(char *s)
{
while (*s != ’\0’) {
printf("%c", *s);
s++;
}
}
Niklas Frykholm, Gunnar Gunnarsson
Programmeringsteknik för mediaingenjörer, ht -98
93
Niklas Frykholm, Gunnar Gunnarsson
int main(void)
{
int i, n, *a;
printf("Ange antal poster i fältet: ");
scanf("%i", &n);
a = malloc(n * sizeof(int));
for (i = 0; i<n; i++) {
printf("Post %i: ", i+1);
scanf("%i", &a[i]);
}
printf("Baklänges blir fältet: ");
for (i=n-1; i>=0; i--)
printf("%i ", a[i]);
printf("\n");
free(a);
}
Programmeringsteknik för mediaingenjörer, ht -98
94
Niklas Frykholm, Gunnar Gunnarsson
/* Fält av pekare. */
int main(void)
{
int i;
char *s[5] = {"ett", "två", "tre",
"fyra", "fem"};
for (i=0; i<5; i++)
printf("%s ", s[i]); /* Varför behövs %s? */
return 0;
}
Programmeringsteknik för mediaingenjörer, ht -98
95
Niklas Frykholm, Gunnar Gunnarsson
int main(void)
{
int i, j, *l[5], len[5];
for (i=0; i<5; i++) {
printf("Ange längden på lista %i: ", i);
scanf("%i", &len[i]);
l[i] = malloc(sizeof(int)*len[i]);
for (j=0; j<len[i]; j++) {
printf("Post %i i lista %i: ", j, i);
scanf("%i", &l[i][j]);
}
}
for (i=0; i<5; i++) {
printf("\nLista %i: ",i);
for (j=0; j<len[i]; j++)
printf("%i ", l[i][j]);
}
}
Programmeringsteknik för mediaingenjörer, ht -98
96
/* Pekare till en pekare. */
int main(void)
{
int i1=3, i2=5, *p1, *p2, **p;
p1 = &i1;
p2 = &i2;
p = &p1;
/* Vad gör nu denna sats? */
**p = *p2;
}
Niklas Frykholm, Gunnar Gunnarsson
Programmeringsteknik för mediaingenjörer, ht -98
97
Niklas Frykholm, Gunnar Gunnarsson
/* Pekare till en pekare till en pekare. */
int main(void)
{
int ***p;
p = malloc(sizeof(int **));
*p = malloc(sizeof(int *));
**p = malloc(sizeof(int));
***p = 3;
}
Programmeringsteknik för mediaingenjörer, ht -98
98
Niklas Frykholm, Gunnar Gunnarsson
Repetition
 Namnet på ett fält fungerar som en pekare till första elementet. Det gäller även vid funktionsanrop. Om vi skriver.
int a[10];
funk(a);
 ...så är det alltså en pekare till det första elementet som skickas till funktionen. Funktionen kan vara deklarerad t ex
som
void funk(int x[]);
void funk(int *x);
 Ett flerdimensionellt fält är ett fält med fler än ett index, t ex
int a[3][4] = {{1,2,3,4},{2,3,4,5},{3,4,5,6}};
 Vi kan tänka på ett sådant fält som ett rutnät:
Programmeringsteknik för mediaingenjörer, ht -98
99
Niklas Frykholm, Gunnar Gunnarsson
Repetition
 Med flerdimensionella fält kan vi skapa ett fält av strängar. Eftersom en sträng är ett fält av tecken, blir ett fält av
strängar, ett fält av fält av tecken.
char s[3][10] = {"Hej", "på", "dej"};
 De tre strängarna har nu namnen s[0], s[1] och s[2].
 Ett alternativt sätt att skapa en sträng i ett program är att skriva
char *s = "Hej på dej!";
 Vi har i detta fall inte skapat något fält där strängen kan lagras. Det behövs inte eftersom strängen automatiskt lagras
i maskinkoden för det kompilerade programmet. Uttrycket ovan sätter s att peka på den plats i koden där strängen
finns lagrad.
 Vi kan inte ändra innehållet i strängar som skapas på detta sätt. (Vi kan t ex inte skriva s[0] = 'J'.)
 Fält och pekare har en mycket speciell relation i C. Namnet på ett fält är nämligen samma sak som en pekare till
första positionen i fältet (a==&a[0]). Detta för med sig fyra saker:
1. Vi kan använda ett fältnamn som en pekare.
2. Vi kan använda en pekare som ett fältnamn.
3. Om vi adderar 1 till en pekare som pekar på någon position i ett fält, så får vi en pekare till nästa position i fältet.
4. Att skriva a[5] är exakt samma sak som att skriva *(a + 5).
Programmeringsteknik för mediaingenjörer, ht -98
100
Niklas Frykholm, Gunnar Gunnarsson
Repetition
 Funktionen malloc skapar ett minnesutrymme av en viss storlek åt vårt program och returnerar en pekare till det. Vi
kan sedan använda pekaren för att lagra information där.
int *p;
p = malloc(100 * sizeof(int));
p[45] = 14;
 Det är viktigt att vi håller oss inom det utrymme vi har skapat, annars får vi en krasch.
 Malloc låter oss bestämma hur stort ett fält skall vara när programmet körs, vilket innebär att vi kan göra våra fält
precis lagom stora.
 När vi är klara med minnet använder vi free för att ge tillbaka minnet till operativsystemet. Efter detta kan vi inte
använda minnet mer.
free(p);
 Det är viktigt att ge tillbaka minnet. (Om inga program gjorde det skulle minnet snabbt ta slut.)
 Minnet ges automatiskt tillbaka när programmet avslutas.
Programmeringsteknik för mediaingenjörer, ht -98
101
Niklas Frykholm, Gunnar Gunnarsson
/* Kopplar hjärter till siffran 1, ruter till 2, */
/* spader till 3, osv. */
enum {hjarter = 1, ruter = 2, spader = 3, klover = 4};
/* Ruter blir 2 och klöver 11 (räkningen ökar med */
/* 1 automatiskt). */
enum {hjarter = 1, ruter, spader = 10, klover};
/* Hjärter blir 0, ruter 1, osv (räkningen startar */
/* på 0 automatiskt). */
enum {hjarter, ruter, spader, klover};
Programmeringsteknik för mediaingenjörer, ht -98
102
Niklas Frykholm, Gunnar Gunnarsson
struct {
char titel[50], forfattare[50];
int antal_sidor, pris;
float vikt;
} bok_1;
strcpy(bok_l.titel, "Furstens hus");
strcpy(bok_l.forfattare, "Åke Lundgren");
bok_1.antal_sidor = 162;
bok_1.pris = 140;
bok_1.vikt = 0.35;
Programmeringsteknik för mediaingenjörer, ht -98
103
registrera_inkop(bok_1);
registrera_inkop(&bok_1);
struct {
int i[100];
} a, b;
a = b;
Niklas Frykholm, Gunnar Gunnarsson
Programmeringsteknik för mediaingenjörer, ht -98
104
Niklas Frykholm, Gunnar Gunnarsson
struct bok {
char titel[50], forfattare[50];
int antal_sidor, pris;
float vikt;
};
struct bok bok_1;
struct bok bok_2;
Programmeringsteknik för mediaingenjörer, ht -98
105
struct bok las_bok(void)
{
struct bok boken;
printf("Titel: ");
scanf("%s", boken.titel);
printf("Författare: ");
scanf("%s", boken.forfattare);
printf("Antal sidor: ");
scanf("%i", &boken.antal_sidor);
printf("Pris: ");
scanf("%i", &boken.pris);
printf("Vikt: ");
scanf("%f", &boken.vikt);
return boken;
Niklas Frykholm, Gunnar Gunnarsson
Programmeringsteknik för mediaingenjörer, ht -98
}
106
Niklas Frykholm, Gunnar Gunnarsson
Programmeringsteknik för mediaingenjörer, ht -98
107
Niklas Frykholm, Gunnar Gunnarsson
void skriv_bok(struct bok *b)
{
printf("Titel: %s\n"
"Författare: %s\n"
"Antal sidor: %i\n"
"Pris: %i\n"
"Vikt: %f\n",
b->titel, b->forfattare,
b->antal_sidor, b->pris, b->vikt);
}
Programmeringsteknik för mediaingenjörer, ht -98
108
typedef unsigned char u_char;
typedef int ifalt[100], *ipek;
u_char c;
ifalt if;
ipek ip;
Niklas Frykholm, Gunnar Gunnarsson
Programmeringsteknik för mediaingenjörer, ht -98
109
Niklas Frykholm, Gunnar Gunnarsson
typedef struct nod {
...
} nodtyp;
/* Nu är båda dessa deklarationer tillåtna. */
struct nod n;
nodtyp n;
/* Däremot kan vi inte skriva på följande sätt. */
nod n;
struct nodtyp n;
Programmeringsteknik för mediaingenjörer, ht -98
struct node {
int data;
struct node *next;
};
110
Niklas Frykholm, Gunnar Gunnarsson
Programmeringsteknik för mediaingenjörer, ht -98
111
Niklas Frykholm, Gunnar Gunnarsson
void double_list(struct node *first)
{
struct node *current = first;
while (current != NULL) {
current->data *= 2;
current = current->next;
}
}
Programmeringsteknik för mediaingenjörer, ht -98
112
Niklas Frykholm, Gunnar Gunnarsson
void double_list(struct node *first)
{
if (first != NULL) {
first->data *= 2;
double_list(first->next);
}
}
Programmeringsteknik för mediaingenjörer, ht -98
113
Niklas Frykholm, Gunnar Gunnarsson
/* Skapar ett nytt element efter e. */
void new_element_after(struct node *e, int data)
{
struct node *new_e;
new_e = malloc(sizeof(struct node));
new_e->data = data;
new_e->next = e->next;
e->next = new_e;
}
Programmeringsteknik för mediaingenjörer, ht -98
114
Niklas Frykholm, Gunnar Gunnarsson
/* Tar bort posten efter posten e. */
void delete_element_after(struct node *e)
{
struct node *old = e->next;
e->next = old->next;
free(old);
}
Programmeringsteknik för mediaingenjörer, ht -98
115
Niklas Frykholm, Gunnar Gunnarsson
int main(void)
{
FILE *f;
int tal;
f = fopen("talet.txt", "w");
if (f == NULL) {
printf("Filen talet.txt gick inte att öppna!\n");
exit(1);
}
fprintf(f, "Talet är %d\n", tal);
fclose(f);
}
Programmeringsteknik för mediaingenjörer, ht -98
116
int main(void)
{
int count;
FILE *f = fopen("count.txt", "r");
if (f == NULL)
count = 0;
else
fscanf(f, "%i", &count);
fclose(f);
count++;
f = fopen("count.txt", "w");
if (f==NULL)
perror("error");
else
fprintf(f, "%i", count);
Niklas Frykholm, Gunnar Gunnarsson
Programmeringsteknik för mediaingenjörer, ht -98
fclose(f);
}
117
Niklas Frykholm, Gunnar Gunnarsson
Programmeringsteknik för mediaingenjörer, ht -98
118
int main(void)
{
FILE *f1 = fopen("fil1.txt", "r");
FILE *f2 = fopen("fil2.txt", "w");
int c;
if (f1==NULL || f2==NULL)
exit(1);
while (1) {
c = fgetc(f1);
if (c==EOF)
break;
fputc(c, f2);
}
fclose(f1); fclose(f2);
}
Niklas Frykholm, Gunnar Gunnarsson
Programmeringsteknik för mediaingenjörer, ht -98
119
Niklas Frykholm, Gunnar Gunnarsson
FILE *f = fopen("reg.txt", "r");
while(1) {
char namn[80], anvnamn[80];
int alder;
int res;
res = fscanf(f, "%s", anvnamn);
if (res == EOF)
break;
fscanf(f, "%s", namn);
fscanf(f, "%i", &alder);
if (strcmp("Håkan", namn)==0)
printf("Håkan är %i år gammal.\n", alder);
}
Programmeringsteknik för mediaingenjörer, ht -98
120
Niklas Frykholm, Gunnar Gunnarsson
Programmeringsteknik för mediaingenjörer, ht -98
121
Niklas Frykholm, Gunnar Gunnarsson