Bitvisa operationer Alla variabler oavsett typ representeras internt i datorn som binära tal med ettor och nollor. Om vi antar att en int representeras med 2 byte (dock vanligare med 4 byte) på systemet. blir den binära representationen: 00000000 00000001 1 2 0 =1 00000000 00000111 1 2 2 +1 2 1 +1 2 0 =7 00000000 00001000 1 2 3 +0 2 2 +0 2 1 +0 2 0 =8 00000000 00001001 1 2 3 +0 2 2 +0 2 1 +1 2 0 =9 Programmeringsteknik 195
Bitvisa operationer I C kan man operera direkt på de enskilda bitarna med de så kallade bitoperatorerna. Logiska operatorer unary complement and & exclusive or ˆ inclusive or Shiftoperatorer left shift << right shift >> Bitvisa operatorer kan enbart utföras på heltalstyper (int, unsigned int, long, char,... ). Programmeringsteknik 196
Binärt komplement Med komplementet menas att alla bitar byter värde, dvs alla ettor blir nollor och alla nollor blir ettor. Den binära representationen av heltalet int a = 550055; (2 0 + 2 1 + 2 2 + 2 5 + 2 7 + 2 10 + 2 13 + 2 14 + 2 19 ) är 0000000 00001000 01100100 10100111 Uttrycket a blir således 1111111 11110111 10011011 01011000 Programmeringsteknik 197
Negativa tal Negativa tal representeras ofta enligt vad som på engelska kallas two s complement representation. Det innebär att ett negativt tal -n representeras som det binära komplementet till n-1 0 00000000 00000000 00000000 00000000-1 11111111 11111111 11111111 11111111 6 00000000 00000000 00000000 00000110-7 11111111 11111111 11111111 11111001 Programmeringsteknik 198
Logiska bitvisa binära operationer Tabellen visar and (&), exclusive or (ˆ) och inclusive or ( ) på 1-bits fält. a b a & b a ˆ b a b 00 0 0 0 10 0 1 1 01 0 1 1 11 1 0 1 Programmeringsteknik 199
Logiska bitvisa binära operationer Uttryck Representation Värde A 00000000 00000000 10000010 00110101 33333 B 11111111 11111110 11010000 00101111-77777 a & b 00000000 00000000 10000000 00100101 32805 a ˆ b 11111111 11111110 01010010 00011010-110054 a b 11111111 11111110 11010010 00111111-77249 (a b) 00000000 00000001 00101101 11000000 77248 ( a & b) 00000000 00000001 00101101 11000000 77248 Programmeringsteknik 200
Shiftoperatorer De två operatorerna till shiftoperatorerna måste vara av heltalstyp. Uttrycket expr1 << expr2 innebär att bitrepresentationen i expr1 shiftas expr2 steg till vänster. int d=1076; 1076 00000000 00000000 00000100 00110100 d << 1; 2152 00000000 00000000 00001000 01101000 d << 3; 8608 00000000 00000000 00100001 10100000 d << 29; -2147483648 10000000 00000000 00000000 00000000 d << 32; 0 00000000 00000000 00000000 00000000 Vid vänstershift fylls 0:or på från vänster Programmeringsteknik 201
Fler bitoperatorer På samma sätt som +=, *= operatorerna finns även dessa operatorer: operator exempel ekvivalent >>= a >>= b a = a >> b <<= a <<= b a = a << b ˆ= aˆ= b a = a ˆ b &= a &= b a = a & b = a = b a = a b Programmeringsteknik 202
Exempel void bit_print(unsigned in) { unsigned mask=1<<8*sizeof(in)-1; while(mask) { printf("%d",mask&in?1:0); mask=mask>>1; } } Programmeringsteknik 203
Uppräkningstyper En uppräkningsbar typ specificerar en mängd heltalskonstanter med symboliska namn. Variabler av den uppräkningsbara typen kan endast anta värden av dessa symboliska namn. enum state {off, on}; enum state lightbulb = on; if (lightbulb == on) printf("the light is on"); Programmeringsteknik 204
Uppräkningstyper Varje symbol i typen antar ett heltal 1 större än föregående och börjar med 0. Specifika heltalsvärden kan anges vid deklarationen. enum boolean {false, true}; /* false = 0, true = 1 */ enum result {unknown=0, win=1, lost, tie=4}; /* unknown=0, win=1, lost=2, tie=4 */ OBS! Det går inte att läsa in värden till en variabel typ av enum Programmeringsteknik 205
Uppräkningstyper Uppräkningstyper används ofta tillsammans med typedef för att skapa en ny datatyp som enkelt kan användas som funktionsparametrar m.m. typedef enum {unknown=0, metanol=1, etanol=2, butanol=4, hexanol=6} alcohole; int hydrogen_atoms(alcohole molecule);... Programmeringsteknik 206
Uppräkningstyper Eftersom uppräkningstyper är av konstant heltalstyp kan de med fördel användas i switchsatser. char *molecule_to_string(alcohole molecule){ switch(molecule) { case metanol: return "CH3OH"; case etanol: return "C2H5OH"; case butanol: return "C4H9OH"; case hexanol: return "C6H13OH"; default: return NULL; } } Programmeringsteknik 207
Preprocessorn Preprocessorn evaluerar speciella direktiv i koden innan koden kompileras. Preprocessorn kan användas för att effektivisera hackande av kod. Rader med preprocessordirektiv börjar med en #. Preprocessorn utför inkludering av filer, villkorlig kompilering och expansion av makron. Rader med preprocessordirektiv kan förekomma var som helst i koden. Programmeringsteknik 208
Filinkludering Inkludering av filer utförs med #include. Standardfiler Standardfiler anges inom < och > varefter preprocessorn söker på ett antal fördefinierade ställen. #include <stdio.h> #include <tcp.h> Användarfiler Användarfiler anges inom " varefter preprocessorn letar i den aktuella katalogen. #include "list.h" #include "matrix.h" Programmeringsteknik 209
Filinkludering Raden med preprocessordirektivet byts ut mot en kopia av filen vilket kan vara av intresse om det finns beroenden mellan filer som inkluderas. Filinkluderingar kan vara nästlade, d.v.s filer som inkluderas kan själv inkludera filer. Programmeringsteknik 210
Makron och konstanter Makron kan användas till att definiera konstanter och öka tydligheten och portabiliteten av kod. Ett makro definieras med #define. #define identifier token string Preprocessorn byter ut alla förekomster av identifier mot token_string i koden. #define MAX_STR_LEN 50 #define EPS 2.2204e-16 #define EQ == Det finns inga begränsningar i vad som kan definieras som makron. Programmeringsteknik 211
Makron med argument #define identifier(identifier,, identifier) token_string Efter en deklaration #define max(x,y) ((x)>(y)? (x) : (y)) blir uttrycket c = max(a+1,b-1); expanderat av preprocessorn till c = ((a+1)>(b-1)? (a+1) : (b-1)); Programmeringsteknik 212
Vanliga fel Utan parenteser #define SQ(x) x*x... c = SQ(5 + 1); blir expanderat av preprocessorn till c = 5 + 1 * 5 + 1 ; /* == 11 och ej 36 */ Semikolon och lika med #define add = + #define A 3;... c = b add A-5; blir expanderat av preprocessorn till c = b = + 3; -5; Programmeringsteknik 213
Fler vanliga fel Funktionsargument Vad blir nämligen egentligen detta? #define MAX(x,y) ((x) > (y)? (x) : (y)) int give_next() { static int d = 2; return d++; }.. MAX(3, give_next()) Programmeringsteknik 214
Vilkorlig kompilering #if constant_integer_expression #ifdef identifier #ifndef identifier #elif #else #endif Portabel kod Debugg utskrifter Programmeringsteknik 215
Vilkorlig kompilering Debuggutskrifter: #define DEBUG 1 #if DEBUG printf("debug: a = %d\n", a); #endif eller #define DEBUG #ifdef DEBUG printf("debug: a = %d\n", a); #endif Programmeringsteknik 216
Modulär programmering Bryta upp kod i moduler Hålla samman relaterade funktioner Lättare felsökning Lättare att bygga ut. Programmeringsteknik 217
Modulär programmering Headerfiler: Filinkluderingar Typdeklarationer Definitioner, makron Funktionsprototyper Källkodsfil: Funktioner Programmeringsteknik 218
Modulär programmering temp.h #ifndef TEMP_H #define TEMP_H #include <stdlib.h> #define CK_ADJUST 273.15 #define CF_SCALE 1.8 #define CF_ADJUST 32 typedef double celsius; typedef double kelvin; typedef double farenheit; kelvin celsius_to_kelvin (celsius); farenheit celsius_to_farenheit (celsius); celsius farenheit_to_celsius (farenheit); kelvin farenheit_to_kelvin (farenheit); celsius kelvin_to_celsius (kelvin); farenheit kelvin_to_farenheit (kelvin); #endif Programmeringsteknik 219
Modulär programmering temp.c #include temp.h kelvin celsius_to_kelvin(celsius c) { return (kelvin)(c - CK_ADJUST); } farenheit celsius_to_farenheit(celsius c) { return (farenheit)((c * CF_SCALE) + CF_ADJUST); } celsius farenheit_to_celsius(farenheit f) { return (celsius)((f - CF_ADJUST)/CF_SCALE); }... Programmeringsteknik 220
Makron i ctype.h #include stdio.h int getchar(); int putchar(int c); Returnerar: c vid OK, annars EOF getchar läser ett tecken från tangentbordet. putchar skriver ett tecken till skärmen. Programmeringsteknik 221
Makron i ctype.h Makron för teckenhantering. #include <ctype.h> int isalpha(int c); 0 om c är en bokstav int isupper(int c); 0 om c är en stor bokstav int islower(int c); 0 om c är en liten bokstav int isdigit(int c); 0 om c är en siffra int isspace(int c); 0 om c är ett vitt tecken int toupper(int c); motsvarande stora bokstav eller c int tolower(int c); motsvarande lilla bokstav eller c Programmeringsteknik 222
Självrefererande strukturer Det går bra för strukturer att referera till sig själv. struct link { int data; struct link *next; } a; Pekarvariabeln next kallas länk. Liknande strukturer används ofta till länkade strukturer. Programmeringsteknik 223
Självrefererande strukturer Flera sådana strukturer kan länkas samman. struct link a, b, c; a.data = 1; b.data = 2; c.data = 3; a.next = b.next = c.next = NULL; a.next = &b; b.next = &c; a.next->data; /* == 2 */ a.next->next->data; /* == 3 */ Programmeringsteknik 224
Enkellänkade listor Självrefererande strukturer används i länkade listor. Länkade listor kan lagra data av variabel storlek, d.v.s. jämfört med en vektor behöver man inte veta hur många element som maximalt skall finnas och onödigt mycke minne behöver inte allokeras. Programmeringsteknik 225
Enkellänkade listor Viktiga funktioner som bör kunna göras på en lista: skapa en lista, räkna elementen, kolla på ett element, slå samman två listor, sätta in ett element på valfri plats, ta bort ett element. Programmeringsteknik 226
Enkellänkade listor För att skapa en lista som enkelt kan användas skapar vi en ny datatyp som vi placerar i en fil kallad list.h. #ifndef _LIST_H #define _LIST_H #include <stdio.h> #include <stdlib.h> #include <assert.h> typedef int DATA; typedef struct link { DATA data; struct link *next; } element; typedef struct { element *head; } list; #endif Programmeringsteknik 227
Enkellänkade listor En något så när komplett lista av funktionsprototyper kan vara: list *create_empty_list (); list *vector_to_list (DATA *, int); int count (list *l); int is_empty (list *l); void print_list (list*); element *first (list *); element *last (list *); element *next (element *); element *prev (element *); element *insert_first (list *, DATA); element *insert_after (element *, DATA); DATA delete_first (list*); DATA delete_after (element *); DATA peek (element *); Programmeringsteknik 228
Enkellänkade listor Listan kan vi nu använda enligt: list *l = create_empty_list(); insert_first(l, 1); insert_after(first(), 2); insert_first(l, 3); delete_after(next(first(l)); insert_after(next(first(l), 4); print_list(l); printf("\nlist length: %d\n", count(l)); och resultatet borde då bli: 3 --> 1 --> 4 list length: 3 Programmeringsteknik 229
Stackar I en stack tas alltid det element som senast lades till bort först. Man kan likna en stack med en stapel tallrikar där man bara tar bort översta tallriken eller lägger till en tallrik i taget överst. En stack har ett fåtal grundläggande funktioner top ger datat i översta elementet pop tar bort översta elementet push lägger till ett elementet på toppen stack_count räknar antalet element i stacken Exempel på några ytterligare funktioner kan vara print_stack skriver ut stacken stack_is_empty kollar om stacken är tom Programmeringsteknik 230
Köer I en kö läggs alltid ett nytt element till i slutet och det är alltid det första som tas bort. En kö har också ett fåtal grundläggande funktioner front ger datat i första elementet dequeue tar bort första elementet enqueue lägger till ett element på slutet queue_count räknar antalet element i kön Exempel på några ytterligare funktioner kan vara print_queue skriver ut kön queue_is_empty kollar om kön är tom Programmeringsteknik 231
Träd Ett träd består av ett antal noder förbundna med varandra så att det inte bildas någon loop. Varje träd har en unik nod som kallas rot. Roten saknar föräldrar. En nod som saknar barn kallas för löv. Ett träd består av en samling delträd. Programmeringsteknik 232
Binära träd Binära träd är en viktig undergrupp till träd. I ett binärt träd har en nod maximalt två barn. Ett viktigt begrepp när man behandlar olika datatyper är hur snabbt man kan finna (söka efter) ett visst element. Normalt kan ett specifikt element finnas på logaritmisk tid i ett träd, medan det normalt krävs linjär tid att finna ett element i en lista. D.v.s. finns det n element är tids åtgången i ett träd maximalt a log 2 (n) och i en lista a n, där a är en konstant. Programmeringsteknik 233
Java och C++ Programmeringsspråken C++ och java bygger båda på C. Förutom de grundläggande konstruktionerna i C så har man också lagt till begreppet objekt-orienterad programmering. Båda språken har också försökt förbättra endel C konstruktioner som ej har ansetts så bra. Programmeringsteknik 234
Objektorientering Ett objekt är något som har: tillstånd - egenskaper (ungefär variabler) beteenden - vad det kan göra, eller utsättas för (ungefär funktioner). Klasser Mallar för hur man skapar objekt. Inte helt olika struct i C, men definierar också de funktioner som kan använda sig av datat. Arv Hjälper till med återanvändning av kod Man utökar en redan befintlig klass eller förändrar beteenden hos den. Programmeringsteknik 235
Syfte med objektorientering Att bidra till inkapsling; dvs endast de funktioner som behöver använda visst data skall ha tillgång till detta (jämför tex lokala/globala variabler i C) Samla data på ett sätt som liknar hur vi tänker på dem i verkligheten (utanför datorn) Öka kodåteranvändningen. Göra så att man slipper återupfinna hjulet flera ggr. Programmeringsteknik 236
C++ Skapades i början av 80-talet av Bjarne Stroustrup (AT&T Bell Labs) 1985 släpptes C++ kommersiellt och fick snabbt spridning inom UNIX-värden C++ har: hårdare typkontroll än C möjlighet till multipelt arv mindre behov av preprocessorn, eftersom man har möjlighet att skriva funktioner som fungerar som makron, samt möjlighet att definiera konstanter utan att använda sig av #define. Har möjlighet att skicka parametrar via call-byreference utan att använda sig av adressoperatorn & Programmeringsteknik 237
Målen med C++ Bakåtkompabilitet med ANSI C i så hög grad som möjligt Inkludera nya programmeringsparadigmer som objektorientering utan att för den skull offra prestanda. Programmeringsteknik 238
Exempel # include <iostream.h> const double ranta =13.5; int rante_ber(int summa) { int resultat; resultat =summa *(ranta/100); return resultat; } int main() { cout << Ange belopp ; cin >>belopp; } cout << Räntan på beloppet blir: << rante_ber(belopp) <<endl; Programmeringsteknik 239
#include <string.h> #include <iostream.h> const int max_len =255; class string { public: //Universal access void assign(const char* st) { strcpy(s,st); len=strlen(st); } int length() {return len;} void print() { cout << s << \nlength << len << \n ; } private: char s[max_len]; int len; }; Programmeringsteknik 240
Java Utformades av James Gossling (SUN) och släpptes 1995 Konstruerat för att vara plattformsoberoende. Dvs ett program skrivet i java skall gå att köra på olika datorplattformar utan att man behöver göra några förändringar. Java har: en speciell konstruktion Applets; som gör att man kan lägga in sina program på webbsidor och köra dem via sin browser. inga pekare och man behöver inte avallokera minne eftersom systemet hanterar detta automatiskt All kod skrivs i klasser endast enkelt arv ett stort klassbibliotek som man kan utnyttja Programmeringsteknik 241
Exempel import java.io.*; import cs1.*; public class MedelTemp { public static void main (String [ ] args) throws IOException { float summatemp = 0; int antaltemp = 0; System.out.print("Ge temperaturer, avsluta med -99 : "); float temp = Keyboard.readFloat(); while ( temp!= -99) { summatemp = summatemp + temp; antaltemp = antaltemp + 1; temp = Keyboard.readFloat(); }//while System.out.println("Medeltemperatur = " + summatemp/antaltemp); }//main }// MedelTemp Programmeringsteknik 242
public class SparKonto { double saldo; public SparKonto(double startsaldo) { saldo = startsaldo; }// constructor SparKonto public void ins(double belopp) { saldo = saldo + belopp; System.out.println(belopp + " insatt."); }// method ins public void uttag(double belopp) { if (saldo >= belopp) { saldo = saldo - belopp; System.out.println(belopp + " uttaget."); } else System.out.println("Så mycket kan man inte ta ut."); }// method uttag public double getsaldo() { return saldo; }// method getsaldo } // class SparKonto Programmeringsteknik 243