.c och.h filer. Programmeringsteknik 113

Relevanta dokument
Dagens föreläsning. Specialtecken. Mer om printf. Formateringssträngar. Mer om scanf. Programmeringsteknik för Ingenjörer VT05

Programmeringsteknik för Ingenjörer VT06. Föreläsning 10

Programmeringsteknik med C och Matlab

Strängar. Strängar (forts.)

Övning från förra gången: readword

Exempel. Rekursion. Iterativ motsvarighet. fakultet.c. fibonacci.c Fibonaccisekvensen definieras som följer ƒ 0 =0, ƒ 1 =1, ƒ i+1 =ƒ i +ƒ i-1, i=1,2,

2 Pekare och dynamiska variabler.

Poster ( structar ) Postdeklarationer

Enkla datatyper minne

Pekare och arrayer. Indexering och avreferering

Dynamiskt minne. Vad är dynamiskt minne Motivering Hur gör man i C Övningar

Tentamen i. för D1 m fl, även distanskursen. lördag 19 januari 2013

Pekare. Pekare. Varför använder vi pekare? Vad är en pekare? Pekare. Deklaration/initiering av pekare

Johan Karlsson Datavetenskap för teknisk kemi, 10p, moment 1 Datavetenskap Umeå Universitet. Tentamen

Tentamen i. Programmering i språket C

Tentamen i Programmering grundkurs och Programmering C

Agenda. Arrayer deklaration, åtkomst Makron Flerdimensionella arrayer Initiering Strängar Funktioner och arrayer. Övningar nu och då

Innehållsförteckning. Exempel. Åtkomst & användarhandledning

Tentamen i Programmering grundkurs och Programmering C

Grundläggande C-programmering del 2 Pekare och Arrayer. Ulf Assarsson

Funktionspekare, inledning: funktionsanropsmekanismen. Anrop via pekare

*Pekarvärden *Pekarvariabler & *

Grundläggande C-programmering del 2 Pekare och Arrayer. Ulf Assarsson

4 Sammansatta datatyper

Tentamen i Programmering grundkurs och Programmering C

Tentamen i Programmering grundkurs och Programmering C

Kompilering och exekvering. Föreläsning 1 Objektorienterad programmering DD1332. En kompilerbar och körbar java-kod. Kompilering och exekvering

TDIU01 - Programmering i C++, grundkurs

Vad har vi lärt oss så här långt Vad är en sträng? Strängkonstanter. Att skriva ut och läsa in strängar. Att arbeta med strängar.

Programmering i C++ EDA623 Typer. EDA623 (Föreläsning 4) HT / 33

Lite om felhantering och Exceptions Mer om variabler och parametrar Fält (eng array) och klassen ArrayList.

Programmera i C Varför programmera i C när det finns språk som Simula och Pascal??

Repetition C-programmering

Föreläsning 13. In- och utmatning

TDIU01 - Programmering i C++, grundkurs

Programmering i C, 7,5 hp

Programmering, grundkurs, 8.0 hp HI1024, HI1900 etc., Tentamen TEN1. Måndagen den 10 januari 2011,

Introduktion C-programmering

Ulf Assarsson. Grundläggande C-programmering del 2 Pekare och Arrayer. Läromoment:

Innehåll. Pekare Syntax

Föreläsning 10. Pekare (Pointers)

Att använda pekare i. C-kod

Datatyper och kontrollstrukturer. Skansholm: Kapitel 2) De åtta primitiva typerna. Typ Innehåll Defaultvärde Storlek

6.1 Kompilering och lite grundläggande information

Översikt Introduktion DST 1. Nicholas Wickström. IDE, Högskolan i Halmstad. N. Wickström

Lösningar till tentauppgifterna sätts ut på kurssidan på nätet idag kl 19. Omtentamen i Programmering C, 5p, fristående, kväll,

Tentamen i Programmering grundkurs och Programmering C

Programmering av inbyggda system. Pekare och Arrayer. Viktor Kämpe

Grundkurs Programmering

Tentamen *:58/ID100V Programmering i C Exempel 3

Dagens föreläsning. Repetition. Repetition - Programmering i C. Repetition - Vad C består av. Repetition Ett första C-program

F5: Högnivåprogrammering

Programmering i C. Vad är C? Målsättning. Litteratur. Jämförelse med Java. Exempel : Ett program som skriver ut texten Hello, world

C-programmering, föreläsning 2 Jesper Wilhelmsson

F5: Högnivåprogrammering

Deklarera en struct som kan användas för att representera en rät linje

Heltal(int) Programmeringsteknik 54

BINÄRA TRÄD. (X = pekarvärdet NULL): struct int_bt_node *pivot, *ny; X X X 12 X X 12 X X -3 X X

Fortsä'ning Pekare. Ulf Assarsson. Originalslides av Viktor Kämpe

Planering Programmering grundkurs HI1024 HT TIDAA

Lösningar till uppgifterna sätts ut på kurssidan på nätet i dag kl Omtentamen i Programmering C, Fri, Kväll,

Föreläsning 5: Introduktion av pekare

Programmering med Java. Grunderna. Programspråket Java. Programmering med Java. Källkodsexempel. Java API-exempel In- och utmatning.

Funktionens deklaration

Planering Programmering grundkurs HI1024 HT data

Det finns många flaggor till g++,

#include <stdio.h> #include <string.h>

Lösningar till uppgifterna sätts ut på kurssidan på nätet idag kl Omtentamen i Programmering C, 5p, A1, D1, E1, Fri, Pr1, Te/Ek1,

GPT föreläsning 8. Förra veckan: Man kan ta tiden på en sorterad teckensträng Förra gången: Problemlösning på lägre nivå kan sortera funktioner

Typkonvertering. Java versus C

Tentamen ges för: Tentamensdatum: Tid:

Föreläsning 2 Objektorienterad programmering DD1332. Typomvandling

Övning 3 i 2D1324. Strukturering h filer deklaration vs definition Debuggning gdb Preprocessorn #define assert(s) FILE LINE Länkning

Programmeringsteknik med C och Matlab

Fortsä'ning Pekare. Ulf Assarsson. Originalslides av Viktor Kämpe

Föreläsning 2. Variabler, tilldelning och kodblock{} if-satsen Logiska operatorer Andra operatorer Att programmera

Loopar och datatyper. Föreläsning 3

Lösningar till uppgifterna sätts ut på kurssidan på nätet i dag kl Tentamen i Programmering C, Fri, Kväll,

1 Texthantering. 1.1 Typen char. Exempel, skriv ut alfabetet

Loopar och datatyper. Föreläsning 3

Dagens föreläsning. Repetition. Repetition - Programmering i C. Repetition - Vad C består av. Repetition Ett första C-program

Hantering av textsträngar och talsträngar. William Sandqvist

Skriv i mån av plats dina lösningar direkt i tentamen. Skriv ditt kodnummer längst upp på varje blad.

Idag. Javas datatyper, arrayer, referenssemantik. Arv, polymorfi, typregler, typkonvertering. Tänker inte säga nåt om det som är likadant som i C.

Lösningar till uppgifterna sätts ut på kurssidan och på WebCT (Gamla Tentor) i dag kl 19. Tentamen i Programmering C, 5p, Distans, övriga,

En kort text om programmering i C.

SCB :-0. Uno Holmer, Chalmers, höger 2 Ex. Induktiv definition av lista. // Basfall

Föreläsning 11. Strängar

C++-programmets beståndsdelar

Filer och structer Del 2

Grundläggande programmering med C# 7,5 högskolepoäng

Byggstenar. C++-programmets beståndsdelar. C++-programmets beståndsdelar. Grundläggande datatyper

GU / Chalmers Campus Lindholmen Tentamen Programutveckling LEU 482 / TIG167

Data, typ, selektion, iteration

C-programmering, föreläsning 1 Jesper Wilhelmsson

Enklast att skriva variabelnamn utan ; innehåll och variabelnamn skrivs ut

Exempelsamling Assemblerprogrammering

Minnestilldelning (allokering) och frigörande (avallokering) av minne

Programmering i C. Vad är C? Målsättning. Litteratur. Jämförelse med Java. Exempel : Ett program som skriver ut texten Hello, world

Pekare ( )

Transkript:

.c och.h filer När programmen blir större är det nödvändigt att dela upp det i mindre enheter. Varje enhet definieras oftast som en del i programmet som hanterar en väl avgränsad uppgift. Denna enhet bildar oftast en samling typdeklarationer (typedef), ev. Globala variabler och en samling funktioner. Då andra delar ev. programmet vill kunna använda innehållet samlas alla deklarationer (typdeklarationer och funktionsprototyper) i en s.k. header-fil som slutar på.h. Denna headerfil kan sedan inkluderas på samma sätt som t.ex. stdio.h i andra filer och funktionerna kan användas. Funktionsdefinitionerna däremot återfinns i en.c fil. Varje.c fil kan sedan separatkompileras. Programmeringsteknik 113

Assertions Header-filen assert.h innehåller makrot assert(). Det är bra programmeringsvana att använda sig av assert() för att kontrollera att argumenten till en funktion är korrekta. #include <assert.h> double div (double a, double b) { assert(b!= 0); return a/b; int main(void) { div(2, 0); /* assertion will fail */ Programmeringsteknik 114

Assertions Om ett argument till assert() är falskt, kommer programmet att skriva ut ett felmeddelande, t.ex. Assertion failed on line 23 och programmet kommer att avslutas. Assertions är enkla att skriva och gör källkoden robustare. Andra läsare av källkoden kan dessutom lättare förstå innehållet. Använd assert()!!! Programmeringsteknik 115

Räckvidd (scope) Grundregeln är att identifierare är bara tillgängliga inne i det block där de deklarerades. De finns inte utanför blocket. Detta låter som en enkel regel, men programmerare väljer ofta att använda samma identifierare på olika variabler. Frågan uppstår då vilken objekt identifieraren refererar till... Programmeringsteknik 116

{ Exempel int a = 2; printf("a = %d\n", a); { int a = 5; printf("a = %d\n", a); printf("a = %d\n", a); Vad skrivs ut? Programmeringsteknik 117

Räckvidd int a = 1; int b = 2; int c = 3; void fkn (int b) { int a = 4; return (a + b); int main (void) { int a = 5; fkn(c); Programmeringsteknik 118

Exempel { int a = 1, b = 2, c = 3; printf("a = %d b = %d c = %d\n", a, b, c); { int b = 4; float c = 5.0F; printf("a = %d b = %d c = %f\n", a, b, c); a = b; { int c = b; printf("a = %d b = %d c = %d\n", a, b, c); printf("a = %d b = %d c = %f\n", a, b, c); printf("a = %d b = %d c = %d\n", a, b, c); Programmeringsteknik 119

{ Partiella och nästlade block int a, b; { float a;... /* int b is known but not int a */ { float b;... /* int a is known but not int b */ Huvudsyftet med att använda block är att spara minne. Minne reserveras bara när variabeln behövs. Vid andra tillfällen kan minnet användas till annat. Programmeringsteknik 120

Lagringsklasser Varje variabel och funktion i C har två attribut: datatyp och lagringsklass. De fyra lagringsklasserna är auto, extern, register och static. Den vanligaste lagringklassen är auto, men den vi ska beröra är static. Programmeringsteknik 121

Lagringsklassen static Statiska deklarationer låter en lokal variabel behålla sitt gamla värde. void f (void) { static int cnt = 0; ++cnt; if (cnt % 0) /* do something */ else /* do something else */ Varannan gång funktionen ovan anropas kommer den att göra en sak och varannan gång något annat. Programmeringsteknik 122

Statiska funktioner En funktion kan också deklareras som static och blir därmed privat för den filen. static int g(void) /* funktionsprototyp */ /*g() är tillgänglig här men inte i andra filer*/ void f (int a) {... static void g(void) {... Programmeringsteknik 123

Initiering Variabler innehåller normalt skräpvärden om de inte har initialiserats. Däremot så initialiseras statiska variabler till noll om inte programmeraren anger ett värde. Vissa C-kompilerare sätter dock värdet på autovariabler till noll om programmeraren inte anger något annat. Detta kan dock skilja sig åt och som programmerare bör man inte lita på detta utan istället explicit sätta värden. Programmeringsteknik 124

Rekursion En funktion är rekursiv om den anropar sig själv, direkt eller indirekt. Alla funktioner kan anropas rekursivt. I sin enklaste form är rekursion enkel att förstå. #include <stdio.h> int main(void) { printf("the universe is never ending\n"); main(); return 0; /* Kommer aldrig att nås */ Programmeringsteknik 125

Exempel För att summera de fem första heltalen kan man skriva int sum(int n) { if (n >= 1) return n; else return n + sum(n-1) sum(1) 1 sum(2) 2 + sum(1) eller 2 + 1 sum(3) 3 + sum(2) eller 3 + 2 + 1 sum(4) 4 + sum(3) eller 4 + 3 + 2 + 1 Programmeringsteknik 126

fakultet.c Matematiskt så lyder definitionen av fakultet som följer 0!=1, n!=n (n-1) 2 1 n>0 eller ekvivalent 0!=1, n!=n (n-1)! n>0 I C kan detta skrivas rekursivt som int factorial (int n) { assert (n >= 0); return (n <= 1? 1 : n * factorial(n-1) ); Programmeringsteknik 127

Iterativ motsvarighet Funktionen kan också skrivas iterativt int factorial (int n) { int product = 1; assert(n >= 0); for ( ; n > 1; n-- ) product *= n; return product; Programmeringsteknik 128

Effektivitet Många algoritmer har både rekursiva och iterativa lösningar. Normalt så är den rekursiva formuleringen vackrare och använder färre variabler för att göra samma beräkning. Vissa datorspråk använder bara rekursion för att åstadkomma upprepning (dvs. de har inte t.ex. while eller for). Rekursion orsakar att datorn lägger gamla värden av variabler i en stack för att komma ihåg dem. Ofta kan rekursion orsaka många funktionsanrop. Programmeringsteknik 129

fibonacci.c Fibonaccisekvensen definieras som följer ƒ 0 =0, ƒ 1 =1, ƒ i+1 =ƒ i +ƒ i-1, i=1.2, int fibonacci (int n) { return (n <= 1? n : fibonacci(n-1) + fibonacci(n-2); N fibonacci(n) Antalet funktionsanrop 0 0 1 1 1 1 2 1 3 42 267.914.296 86.698.873 43 433.494.437 1.402.817.465 Programmeringsteknik 130

Rekursion vs. iteration Vissa programmerare anser att rekursion inte ska användas p.g.a. de många funktionsanropen ineffektivitet. Rekursion har dock många fördelar de är ofta enklare att skriva lättare att förstå lättare att underhålla Därför kan det vara motiverat att använda rekursion trots dess nackdelar. Programmeringsteknik 131

Endimensionella vektorer Har man relaterat data kan man lagra detta i vektorer istället för i enkla variabler. Vektorer deklareras och indexeras med hjälp av hakparenteser ([ och ]) direkt efter variabelnamnet. Exempel: int x0; int x[3]; int x1; int x2; x[0] = 2; x[1] = 1; x0 = 2; x[2] = x[0]; x1 = 1; x2 = x0; Vektorer har en fix längd, n, och indexeras från 0, dvs 0,1,2,,n-1. Programmeringsteknik 132

Endimensionella vektorer Vektorer kan liksom enkla variabler initieras med ett värde vid deklarationen. int x0 = 2; int x[3] = {2, 1, 4; int x1 = 1; int x2 = 4; Om listan med initieringsvärden är kortare än vektorn, initieras resterande element till 0. int x[100] = {1,0; /* första elementet i x blir 1 resten 0 */ int y[100] = {0; /* nollställer alla element i y */ Programmeringsteknik 133

Endimensionella vektorer Om en vektor är deklarerad utan längd, men initierad med en lista av initierare, är dess storlek implicit satt till antalet initierare. Följande två deklarationer är därmed ekvivalenta int x[] = {5, 1, -3, 4; int x[4] = {5, 1, -3, 4; För vektorer av tecken finns en alternativ notation. Följande två deklarationer är ekvivalenta. char s[] = { a, b, c, \0 char s[] = "abc"; Programmeringsteknik 134

Endimensionella vektorer #include <stdio.h> #define N 5 /* Läs in heltal till en vektor. Beräkna och skriv ut dess summa */ int main(void) { int values[n]; int i; int sum = 0; for (i=0; i<n; i++) { printf("enter value %d: ",i); scanf("%d",&values[i]); for (i=0; i<n; i++) { sum += values[i]; printf("\nsum: %d\n",sum); Programmeringsteknik 135

Flerdimensionella vektorer I C kan man deklarera vektorer av alla typer, inklusive vektorer av vektorer. På så vis kan man skapa vektorer i flera dimensioner. int a[100]; /* en endimensionell vektor */ int b[2][7]; /* en två-dimensionell vektor */ int c[6][1][5]; /* en tredimensionell vektor */ Initiering sker på liknande sätt som med endimensionella vektorer. int a[2][2] = {{1, 2, {4, 0; int b[2][3][1] = {{{4,{6,{1, {{7,{2,{1; int b[][][] = { {{4, 2, {6, 1, {{1, 0, {2, 0 ; Programmeringsteknik 136

Två-dimensionella vektorer Det är lättast att tänka på två-dimensionella vektorer som en matris, med rader och kolumner. Deklarationen int a[3][5] kan ses på följande vis: I minnet lagras dock flerdimensionella vektorer kontinuerligt. Programmeringsteknik 137

Två-dimensionella vektorer #include <stdio.h> #define N 5 #define M 3 int main(void) { double A[M][N]; int i, j; for (i=0; i<n; i++) { for (j=0; j<i; j++) { A[i][j] = 0; printf("%4.0lf", A[i][j]); for (j=i; j<m; j++) { A[i][j] = pow(j-i+1, 2); printf("%4.0lf", A[i][j]); printf("\n"); /*Ny rad för varje rad i A */ Programmeringsteknik 138

Pekare Varje variabel i ett program har en unik minnesadress. Med pekare kan man referera och manipulera minnesadresser. Värdet i en pekarvariabel är minnesadressen till en variabel. Om vi har en variabel v så anger &v minnesadressen till v. Deklarationer av pekare görs med en * före variabelnamnet. int *ip; char *cp; double *dp; Programmeringsteknik 139

Pekare Bland de tillåtna adresserna att referera finns alltid adressen 0. Adressen 0 har i C ett speciellt namn, nämligen NULL. Adressen NULL används som defaultvärde hos pekare då inga variabler kan ha den adressen, d.v.s. &v kan aldrig vara 0 (NULL). Några exempel på tilldelning av pekare kan vara: int i; int *p; p = 0; p = NULL; p = &i; Programmeringsteknik 140

Pekare int a = 3; int *p; int a = 3; int *p = NULL; int a = 3; int *p = &a; Programmeringsteknik 141

Pekare Man kan referera värdet på variabler med hjälp av pekare. Om p är en pekare som pekar på b:s minnesadress, ger *p värdet av b, en s.k. indirekt adressering. Exempel: int b = 3; int *p = &b; /* Initiering till adressen av b */ printf(" b: %d\n p: %p\n*p: %d\n", b, p, *p); Ger utskriften b: 3 p: effffbac /*Adressen skriven i hexadecimal form */ *p: 3 Programmeringsteknik 142

Pekare int a = 1; int *p; p = &a; printf(" a = %d *p = %d\n\n", a, *p); *p = 2; /* ekvivalent med a = 2 */ printf(" a = %d *p = %d\n\n", a, *p); a = 3; /* ekvivalent med *p = 3 */ printf(" a = %d *p = %d\n", a, *p); Ger utskriften: a = 1 *p = 1 a = 2 *p = 2 a = 3 *p = 3 Programmeringsteknik 143

Pekare I C används void * som generell pekartyp. Jämför med void.... int a = 3; char c = c ; void *p; p = &a; p = &c;... I ANCI C kan man inte göra konverteringar mellan olika pekartyper om inte den ena är av typen void *. Programmeringsteknik 144

Call-by-Reference När en variabel skickas som argument till en funktion kopieras dess värde till funktionens parameter och värdet på variabeln är oför ändrat. Detta kallas Call-by-value. Om i stället en referens till variabeln skickas som argument kan variabelns värde ändras i den anropade funktionen. Detta kallas Call-by- Reference. C använder alltid Call-by-value, men pekare kan användas for att åstadkomma samma effekt som i Call-by-reference. Programmeringsteknik 145

Programmen Call-by-Reference #include <stdio.h> #include <stdio.h> void set(int a, int value){ void set(int *a, int value){ a = value; *a = value; int main(void) { int main(void) { int a = 5; int a = 5; set(a, 2); set(&a, 2); printf("a = %d\n",a); printf("a = %d\n",a); ger utskrifterna: a = 5 a = 2 Programmeringsteknik 146

Pekare vs. vektorer En vektorvariabel, ex. float x[20], är i sig själv en adress (ett pekarvärde). Medan pekare kan anta nya pekarvärden så är vektorvariabler fixa. Både pekare och vektorer kan indexeras. Om a är en vektor, är a[3] ekvivalent med *(a + 3). a + 3 är ett pekaruttryck som anger tredje elementpositionen efter a. Ekvivalent, om p är en pekare, är p[3] ekvivalent med *(p + 3). Programmeringsteknik 147

Pekare vs. vektorer #define N 5 int main(void) { int a[n] = {0, 1, 2, 3, 4; int i; for (i=0; i<n; i++) { printf("a[%d]=%d *(a + %d)=%d &a[%d]=%p (a + %d)=%p\n, i, a[i], i, *(a + i), i, &a[i], i, (a + i)); Ger utskriften: a[0]=0 *(a + 0)=0 &a[0]=effffb98 (a + 0)=effffb98 a[1]=1 *(a + 1)=1 &a[1]=effffb9c (a + 1)=effffb9c a[2]=2 *(a + 2)=2 &a[2]=effffba0 (a + 2)=effffba0 a[3]=3 *(a + 3)=3 &a[3]=effffba4 (a + 3)=effffba4 a[4]=4 *(a + 4)=4 &a[4]=effffba8 (a + 4)=effffba8 Programmeringsteknik 148

Pekare vs. vektorer Vi kan alltså se det som att det ser ut så här i minnet. Observera C tillåter oss att referera och ändra hur vi vill i minnet. Om vi försöker ändra minne som programmet inte äger avslutar vanligtvis operativsystemet programmet. Däremot kan vi ändra i det minne som programmet äger. Om vi antar att i har adressen effffb94 kan vi alltså ändra värdet på i genom att skriva *(a - 1) = 3;. Programmeringsteknik 149

Pekare vs. vektorer Vi kan alltså använda pekare för att referera positioner i vektorer. Exempel: #define N 5 int a[n] = {0, 1, 2, 3, 4; int *p; int sum = 0; p = &a[1]; /* *p == 1 */ p = (a + 2) /* *p == 2 */ *p = 7; /* a[2] == 7 */ for (p=a; p<&a[n]; p++) { sum += *p; Värdet på sum är efter detta 15. Programmeringsteknik 150

Vektorer som argument Man kan även ge vektorer som argument till funktioner. När vektorer skickas som argument kopieras vektorns adress med Call-by-value, medan vektorelementen inte kopieras. Exempel: void scale(double v[], int n, double scale) { int i; for (i=0; i<n; i++) { v[i] *= scale; Observera att följande deklaration är ekvivalent. void scale(double *v, int n, double scale) {... Programmeringsteknik 151

Bubble sort void swap(int *a, int *b) { int tmp; tmp = *a; *a = *b; *b = tmp; void bubble(int v[], int n) { int i, j; for (i=0; i<n-1; i++) for (j=0; j<n-i-1; j++) if (v[j] > v[j+1]) swap(&v[j], &v[j+1]); Programmeringsteknik 152

Dynamisk minnesallokering Allokera minne för de variabler man behöver och frigör minne när man är klar. För att allokera minne finns i C, de inbyggda funktionerna malloc och calloc. #include <stdlib.h> void *malloc(size_t size); void *calloc(size_t nelem, size_t size); Returnerar: En pekare till allokerat minne om OK, annars NULL Typen size_t är i ANSI C definierad till unsigned int. Vanligtvis är typedef använd i stdlib.h. Programmeringsteknik 153

Dynamisk minnesallokering malloc allokerar size bytes med minne. För att allokera minne som räcker för en viss mängd data och datatyp invänds oftast sizeof. int *v = (int*)malloc(10*sizeof(int)); Här allokeras minne för en heltalsvektor med längden 10. Observera att vi också gör en typecast från void* till int*. Detta är inte nödvändigt, men är bra programmeringsstil. v[i] kan användas p.s.s. som om man gjort deklarationen v[10]. Programmeringsteknik 154

Dynamisk minnesallokering calloc allokerar nelem element av storleken size. calloc initierar det allokerade minnets alla bitar till 0; Motsvarande exempel för calloc blir: int *v = (int*)calloc(10, sizeof(int)); Programmeringsteknik 155

Dynamisk minnesallokering Minne som är dynamiskt allokerat lämnas inte automatiskt tillbaka till systemet. #include <stdlib.h> void free(void* ptr); Funktionen free används för att explicit lämna tillbaka minne. int *p = (int*)malloc(10*sizeof(int));... free(p); Allokerat minne är inte knutet till en specifik pekarvariabel. Om man förlorar referensen till allokerat minne kan man inte sedan referera det eller frigöra det. Programmeringsteknik 156

Dynamisk minnesallokering int* new_int_array(int n) { int *v; v = (int*)malloc(n*sizeof(int)); return v; int main(void) { void *p; p = new_int_array(10); p = new_int_array(10); /* memory lost!!! */ free(p); Programmeringsteknik 157

Strängar Strängar är endimensionella vektorer av typen char. En sträng avslutas med ett \0 tecken, dvs ett tecken med alla bitar satta till 0. En strängs längd kan ses på två sätt: En fix maximal längd som avgörs av vektorns allokerade längd. En variabel längd som bestäms av första \0 tecknet. \0 tecknet måste rymmas inom det allokerade utrymmet. Programmeringsteknik 158

Strängar char s[] = "abc"; char s[] ={ a, b, c, \0 char *p = "abc"; Programmeringsteknik 159

strcat & strncat #include <string.h> char *strcat(char *s1, const char *s2); char *strncat(char *s1,const char *s2, size t n); Returnerar: Pekaren s1. Konkatenerar (slår ihop) två strängar och lägger resultatet i s1. s1 måste vara stor nog för att rymma resultatet. strncat lägger till som mest n tecken. Programmeringsteknik 160

strcmp & strncmp #include <string.h> int strcmp(char *s1, const char *s2); int strncmp(char *s1, const char *s2, size_t n); Returnerar: Ett heltal < 0, lika med 0 eller > 0, beroende på om s1 är lexikografiskt mindre, lika eller större än s2. Jämför två strängar. strncmp jämför som mest n tecken. Programmeringsteknik 161

Strängfunktioner #include <string.h> char *strcpy(char *s1, const char *s2); char *strncpy(char *s1,const char *s2, size_t n); Returnerar: Pekaren s1. Innehållet i s2 kopieras till s1 tills \0 flyttas. s1 måste ha plats för resultatet. strncpy kopierar som mest n tecken. #include <string.h> size_t strlen(const char *s); Returnerar: Antalet tecken före \0. Undersöker längden av eller antalet tecken före\0 hos en sträng. Programmeringsteknik 162

Strängexempel #include <stdlib.h> #define MAX_STR_LEN 20 int main(void) { char s[] = "I love pointers"; char *p; p = (char*)malloc(max_str_len*sizeof(char)); strncpy(p, s, MAX_STR_LEN); free(p); Bild just innan free anropas. Programmeringsteknik 163

Argument till main() Två argument, vanligtvis kallade argc och argv kan användas med main() för kommunikation med operativsystemet. argc anger antalet argument på kommandoraden. argv är en vektor med pekare till strängar med respektive argument. Kommandot, eller programnamnet, är alltid första argumentet. void main(int argc, char *argv[]) {... Programmeringsteknik 164

Echo exempel #include <stdio.h> int main(int argc, char *argv[]) { int i; for (i=1; i<argc; i++) { printf("%s", argv[i]); if (i < argc-1) printf(" "); else printf("\n"); return 0; Programmeringsteknik 165

Echo exempel Om det tidigare exemplet döpts till my_echo och kompilerats på C: kan ett exempel vid kommandopromten bli: C:> my_echo I love C I love C C:> I minnet kommer det att se ut så här: Programmeringsteknik 166

Sammansatta datatyper Vektorer finns för homogent data. Vad gör man med relaterat data av olika datatyper? char *name1 = "Adam Gudmundsson"; int age1 = 23; double weight1 = 74.7; char *name2 = "Eva Gudmundsdotter"; int age2 = 27; double weight2 = 56.2; Programmeringsteknik 167

Strukturer Strukturer definieras med nyckelordet struct. struct post { /* definition */ char *name; int age; double weight; ; struct post p1, p2; /* deklaration */ Definitionen skapar en mall, med vilken man sedan kan deklarera variabler. Strukturer kan användas som andra datatyper i bl.a. vektorer. Programmeringsteknik 168

Strukturer För att göra accesser till medlemmar av en struktur används punktoperatorn. ( genetiv s) struct post p1, persons[2]; p1.name = "Adam Gudmundsson"; p1.age = 23; p1.weight = 74.7; persons[0] = p1; /* hela posten kopieras */ persons[1].name = "Eva Gudmundsdotter"; persons[1].age = 27; persons[1].weight = 56.2; Programmeringsteknik 169

Strukturer Utelämnar man namntaggen till en struktur, kan strukturen inte användas till ytterligare deklarationer. struct { int r; int g; int b; red, blue, green; Detta till skillnad mot om den tas med struct colour { int r; int g; int b; ; struct colour red; struct colour green; struct colour blue; Programmeringsteknik 170

Strukturer Vanligtvis använder man typedef tillsammans med strukturer. När man gör typdeklarationer är namntaggen vanligtvis onödig. typedef struct { double re; double im; complex; /* ny datatyp */ complex a, b, c[n]; Typdeklarationer ökar flexibiliteten och portabiliteten hos kod. Programmeringsteknik 171

Strukturer och dynamiskt minne Vid hantering av pekare till strukturer kommer nyttan av sizeof till sin fulla rätt. sizeof returnerar, för strukturer, summan av storlekarna hos dess medlemstyper. Om vi har strukturen complex. typedef struct { double re; double im; complex; ger sizeof(complex) summan av storleken på två double, d.v.s. vanligtvis 16. Detta är mycket praktiskt vid allokering av nytt minne. complex *a = (complex*)malloc(sizeof(complex)); Programmeringsteknik 172

Strukturer och dynamiskt minne Om vi har en struktur som en pekare kan syntaxen fort bli komplex. complex *a = (complex*)malloc(sizeof(complex)); complex *v[n]; (*a).im = 3.0; (*a).re = 0.2; v[0] = (complex*)malloc(sizeof(complex)); (*(v[0])).im = 5.1; (*(v[0])).re = 2.8; I C finns operatorn -> för att göra accesser till medlemmar i en struktur via en pekare. a->im = 3.0; a->re = 0.2; v[0]->im = 5.1; v[0]->re = 2.8; Programmeringsteknik 173

Strukturer och funktioner Precis som andra datatyper kan strukturer användas med funktioner. typedef struct { int x; int y; coordinate; Med Call-by-value : coordinate move(coordinate p, int dx, int dy) { p.x += dx; p.y += dy; return p; och som pekare: void move(coordinate *p, int dx, int dy) { p->x += dx; p->y += dy; Programmeringsteknik 174

Initiering av strukturer Även strukturer kan initieras vid deklarationen. complex a = {1.0, 2.45; complex v[2] = {{1.4, 0.23, {-1.4, 5.1; person p = {"Adam Gudmundsson", 27, 74.7; Man kan även initiera en hel struktur med värde noll (alla bitar satta till noll) på vanligt sätt. complex c[4] = {0; Programmeringsteknik 175

Unioner Unioner är en datatyp som definierar set med alternativa typer. Definitionen sker på liknande sätt som hos strukturer och ger en mall. union int_or_float { int i; float f; ; Mallen kan sedan användas för att deklarera variabler. union int_or_float a; union int_or_float v[n]; union int_or_float *p; Programmeringsteknik 176

Unioner Det ligger på programmerarens ansvar att tolka det lagrade värdet rätt. Följande exempel går genom kompilatorn och kan exekveras utan fel, men kan ge mycket märkliga effekter. float f; union int_or_float a; a.i = 3; f = a.f; /* f == 4.203895e-45 och ej 3.0!!! */ Storleken på en union blir storleken av den största ingående datatypen. typedef union { int v[6]; double lf; union1; sizeof(union1) /*== 6*sizeof(int) == 6*4 == 24 */ Programmeringsteknik 177

Exempel på sammansatta typer typedef struct { enum {t_integer, t_float type; union { int i; float f; value; compound;... compound c; c.type = t_integer; c.value.i = 4; switch (c.type) { case t_integer: print("c: %d\n", c.value.i); break; case t_float: print("c: %f\n", c.value.f); break; Programmeringsteknik 178

Utskrifter till skärm Utskrifter sker med printf funktionen. #include <stdio.h> int printf(const char* format,...); Returnerar: Antalet utskrivna tecken om OK, annars negativt värde. Första argumentet, format, anger vad som skall skrivas ut och hur det skall skrivas ut. I format-strängen kan konverteringsspecifikationer anges som beskriver hur följande argument skall tolkas och konverteras. int a = 3; printf("%s\n","hello world!"); printf("a har värdet %d\n",a); Programmeringsteknik 179

Flaggor till printf [] flaggan behöver inte anges. eller x bredd på fältet y antalet decimaler som skall skrivas ut z antalet siffror i exponenten som skall skrivas ut. - vänsterjusterat space mellanslag om tecken saknas + skriver ut + eller - före nummer 0 fyller ut med 0:or. # alternativ formatering. Programmeringsteknik 180

Flaggor till printf %[-][x]c chars %[-][x]s strings %[ +][-][0][x]d decimal %[ +][-][0][x]u unsigned decimal %[ +][-][0][x]o octal %[ +][-][0][x]x hexadecimal (with a,b,...) %[ +][-][0][x]X hexadecimal (with A,B,...) %[ +][-][0][x][.y]f float %[ +][-][0][x][.y]lf double %[ +][-][#][0][x][.y][+z]e scientific notation (with e) %[ +][-][#][0][x][.y][+z]E scientific notation (with E) %[ +][-][#][0][x][.y][+z]g same as f or e, depending on the value. %[ +][-][#][0][x][.y][+z]G same as f or E, depending on the value. Programmeringsteknik 181

Exempel på printf #include <stdio.h> int main(void) { int i1 = -3; int i2 = 5; char c1 = c ; double f1 = -2.0; double f2 = 3.3; printf("%-10s%10s\n", "Variabel", "Värde"); printf("--------------------\n"); printf("%-10s%+10d\n", "i1", i1); printf("%-10s% 10d\n", "i2", i2); printf("%-10s%10c\n", "c1", c1); printf("%-10s%+10.2f\n", "f1", f1); printf("%-10s%+10.2+2e\n","f2", f2); return 0; Programmeringsteknik 182

Exempel på printf Ger utskriften: Variabel Värde -------------------- i1-3 i2 5 c1 c f1-2.00 f2 +3.30e+00 Programmeringsteknik 183

Inläsning från tangentbord Inläsning från tangentbordet sker vanligtvis med scanf. #include <stdio.h> int scanf(const char* format,...); Returnerar: Antalet lyckosamt matchade tecken. Vid fel EOF. Första argumentet, format, anger hur det som läses in skall formateras. Efterföljande argument anger adresser (pekare) till minnesutrymme för det inlästa datat. int i; char c; double d; scanf("%d%c%lf", &i, &c, &d); Programmeringsteknik 184

Exempel på scanf int i; char c; char s[15]; scanf("%d,%*s %% %c %5s %s", &i, &c, s, &s[5]); Med insträngen 45, ignore_this % C read_in_this** lagras 45 i i, C i c och read lagras i s[0] till s[4] och \0 i s[5]. Därefter lagras in this** i s[5] till s[13] och \0 i s[14]. Programmeringsteknik 185

Fler strängfunktioner #include <stdio.h> int sprintf(char *s, const char* format,...); Returnerar: Antalet utskrivna tecken om OK, annars negativt värde. sprintf fungerar på samma sätt som printf med den skillnaden att resultatet skrivs till en sträng, s, istället för till skärmen. #include <stdio.h> int sscanf(char* s, const char* format,...); Returnerar: Antalet lyckosamma matchningar. Vid fel EOF. sprintf läser text från en sträng och inte från tangentbordet. Programmeringsteknik 186

Filhantering Filer hanteras med en speciell struktur, FILE, eller snarare pekare till en sådan struktur FILE * Denna definieras i stdio.h, men hur den exakt ser ut är oviktigt. Även utskrifter till skärm och inläsning från tangentbort sköts med filpekare. Dessa benämns stdout och stdin. Dessutom finns en filpekare för utskrifter av felmeddelanden, stderr. Programmeringsteknik 187

Öppna och stänga filer För att kunna läsa eller skriva till en fil måste den först öppnas. #include <stdio.h> FILE *fopen(const char* filename, const char *mode); Returnerar: Filpekare vid OK, annars NULL. Vi öppnar filer genom att ange bl. a. dess namn. #include <stdio.h> int main(void) { FILE* ifp; FILE* ofp; /* open for reading */ ifp = fopen("any_file", "r"); /* open for writing */ ofp = fopen("another_file", "w");... Programmeringsteknik 188

Öppna och stänga filer Vid öppnandet anger man också vad man vill kunna göra med filen. Detta för att undvika misstag. Dessa kan vara r Öppnar textfil för läsning. w Öppnar textfil för skrivning. a Öppnar textfil för att lägga till. rb Öppnar binär fil för läsning. wb Öppnar binär fil för skrivning. ab Öppnar binär fil för att lägga till. r+ Öppnar fil för läsning och skrivning. w+ Öppnar fil för skrivning och läsning.... o.s.v. Programmeringsteknik 189

Öppna och stänga filer När man är klar med en fil bör den stängas. #include <stdio.h> int fclose(file *stream); Returnerar: 0 vid OK, annars EOF. #include <stdio.h> int main(void) { FILE* fp; /* open for reading */ fp = fopen("any_file", "r"); fclose(fp); Programmeringsteknik 190

Läsa och skriva på filer Motsvarigheten till printf och scanf för filer heter fprintf och fscanf. #include <stdio.h> int fprintf(file *stream,const char* format,...); Returnerar: Antalet utskrivna tecken om OK, annars negativt värde. fprintf fungerar på samma sätt som printf med den skillnaden att resultatet skrivs till en filpekare, stream, i stället för till skärmen. #include <stdio.h> int fscanf(file* stream,const char* format,...); Returnerar: Antalet lyckosamma matchningar. Vid fel EOF. fprintf läser text från en filpekare och inte från tangentbordet. Programmeringsteknik 191

Exempel med filer FILE* fp; int a = 5; fp = fopen("anyfile", "w"); fprintf(fp, "Skriver a: %d\n", a); fclose(fp); fp = fopen("anyfile", "r"); fscanf(fp, "%*s%*s %d\n", &a); fclose(fp); Programmeringsteknik 192

Skriva eller läsa enskilda tecken Motsvarigheten till getchar och putchar heter för filer getc och putc. #include <stdio.h> int putc(int c, FILE *stream); Returnerar: värdet av c. EOF vid filslut eller fel. #include <stdio.h> int getc(file *stream); Returnerar: Nästa tecken från strömmen. EOF vid filslut eller fel. Dessa anrop sker genom makron. Det finns också litet långsammare funktionsvarianter av dessa som heter fputc och fgetc. Programmeringsteknik 193

Exempel Observera att dessa två satser är ekvivalenta och att man inte kan öppna eller stänga stdout. fprintf(stdout, "Detta skrivs till skärm\n"): printf("detta skrivs till skärm\n"): Liksom att dessa tre satser är ekvivalenta. putc( a, stdout); fputc( a, stdout); putchar( a ); Programmeringsteknik 194