480 likes | 634 Views
Minnen, variabler, att lagra i primärminnet forts. Den här bilden känner ni igen sedan tidigare. Vi skall fortsätta att prata variabeltyper men först lite repetition. Fördefinierade minnes- variabeltyper. int main() { char tecken; int heltal; float flyttal; double dubbeltFlyttal; ” ”.
E N D
Minnen, variabler,att lagra i primärminnetforts. Den här bilden känner ni igen sedan tidigare. Vi skall fortsätta att prata variabeltyper men först lite repetition
Fördefinierade minnes-variabeltyper • int main() { • char tecken; • int heltal; • float flyttal; • double dubbeltFlyttal; • ” • ”
Egendefinierade minnen • enum • array • strukturer - poster en liten återblick ... ..... sedan skall vi gå in pådet här
Array ( vektor, matris )ett exempel som illustrerar behovet Antag att man vill mäta temperaturen flera gånger och spara värdena för statistisk behandling .Hur gör man ett program som läser in mätvärdena? Ni minns väl det här?
Varför array ? • #include <stdio.h> • int main(void) • { • int temp1, temp2, temp3, temp4, temp5; • int temp6, temp7, temp8, temp9, temp10; • printf("Ge temperatur --> "); scanf("%d",&temp1); • printf("Ge temperatur --> "); scanf("%d",&temp2); • printf("Ge temperatur --> "); scanf("%d",&temp3); • printf("Ge temperatur --> "); scanf("%d",&temp4); • printf("Ge temperatur --> "); scanf("%d",&temp5); • printf("Ge temperatur --> "); scanf("%d",&temp6); • printf("Ge temperatur --> "); scanf("%d",&temp7); • printf("Ge temperatur --> "); scanf("%d",&temp8); • printf("Ge temperatur --> "); scanf("%d",&temp9); • printf("Ge temperatur --> "); scanf("%d",&temp10); • printf("\ntemp = %d", temp1); • return 0; • } Klumpigt !
Varför array ? #include <stdio.h> int main(void) { int temp[10]; int i; for (i=0 ; i<10 ; i++){ printf("Ge temperatur %d --> ",i); scanf("%d",&temp[i]); } for (i=0 ; i<10 ; i++) printf("\ntemp %d = %d",i, temp[i]); return 0; } detta skapar 10 st minnen i primärminnet ( på stacken i detta fall) som vardera kan lagra en int.En array ( vektor ) om 10 element har sett dagens ljus Bra, hyfsat!
int int temp[0] temp[1] temp temp[6] temp[9] Vad är en array ? • for (i=0 ; i<10 ; i++) • printf("\ntemp %d = %d",i, temp[i]); • stega på index Vitsen är att man kan samla minnen av samma typ i en array där man når dem enkelt via ett index. Nackdelen är att alla elementen måste vara av samma typ.
Strukturer - "struct", post • I en array så är alla "delminnen" av samma typ • antag att man vill samla flera olika minnen under ett "tak", ett variabelnamn • som t ex att man önskar lagra fakta om böcker • titel • författare • antal sidor • pris • vikt
Strukturer - "struct", post • I en array så är alla "delminnen" av samma typ • antag att man vill samla flera olika minnen under ett "tak", ett variabelnamn • som t ex att man önskar lagra fakta om böcker • titel • författare • antal sidor • pris • vikt char titel ”en sträng”
Strukturer - "struct", post • I en array så är alla "delminnen" av samma typ • antag att man vill samla flera olika minnen under ett "tak", ett variabelnamn • som t ex att man önskar lagra fakta om böcker • titel • författare • antal sidor • pris • vikt char titel ”en sträng” char forfattare ”en sträng”
Strukturer - "struct", post • I en array så är alla "delminnen" av samma typ • antag att man vill samla flera olika minnen under ett "tak", ett variabelnamn • som t ex att man önskar lagra fakta om böcker • titel • författare • antal sidor • pris • vikt char titel ”en sträng” char forfattare ”en sträng” • antal_sidor int • pris int
Strukturer - "struct", post • I en array så är alla "delminnen" av samma typ • antag att man vill samla flera olika minnen under ett "tak", ett variabelnamn • som t ex att man önskar lagra fakta om böcker • titel • författare • antal sidor • pris • vikt char titel ”en sträng” char forfattare ”en sträng” • antal_sidor int • pris int • vikt float
Strukturer - "struct", post • antag att man vill samla flera olika minnen under ett "tak", ett variabelnamn struct,så här gör man char titel ”en sträng” char forfattare ”en sträng” • antal_sidor int • pris int • vikt float
Strukturer - "struct", post • int main( void ) { • struct bok { • char titel[50], forfattare[50]; • int antal_sidor, pris; • float vikt; • } b1, b2; • b1.antal_sidor = 276; • antag att man vill samla flera olika minnen under ett "tak", ett variabel-namn char titel ”en sträng” char forfattare ”en sträng” • antal_sidor int • pris int • vikt float
Strukturer - "struct", post • int main( void ) { • struct bok { • char titel[50], forfattare[50]; • int antal_sidor, pris; • float vikt; • } b1, b2; • b1.antal_sidor = 276; • varje ”del-minne” i en struktur nås m h a punktoperatorn, ej med index char titel ”en sträng” char forfattare ”en sträng” • antal_sidor int • pris int • vikt float
Operatorprioritet • högst prioritet har de unära postfixoperatorerna [] () . -> ++ -- • sedan kommer de unära prefixoperatorerna ++ -- & * + - ~ ! (typnamn) • därefter de aritmetiska ( rikning V till H ) * / % + - • skiftoperatorer ( rikning V till H ) << >> • jämförelseoperatorerna ( rikning V till H ) < > <= >= == != • bit-operatorerna ( rikning V till H ) & ^ | • logiska operatorer ( rikning V till H ) && || • villkorsoperatorn ( rikning H till V ) ? uttryck : • tilldelningsoperatorer ( rikning H till V ) = *= /= %= += -= <<= >>= &= ~= |= • kommaoperatorn ( riktning V till höger ) ,
Strukturer - "struct", post #include <stdio.h> int main( void ) { struct bok { char titel[50], forfattare[50]; int antal_sidor, pris; float vikt; } b1, b2; printf("Titel? -> "); scanf("%s", b1.titel); printf("Författare? (efternamn)-> "); scanf("%s", b1.forfattare); printf("Sidor, pris och vikt? -> "); scanf("%d%d%f", &b1.antal_sidor,&b1.pris, &b1.vikt); b2 = b1 ; printf("\nTitel:\t\t%s\n", b2.titel); printf("Författare:\t%s\n", b2.forfattare); printf("Sidor:\t\t%d\n", b2.antal_sidor ); printf("Pris:\t\t%d\n", b2.pris ); printf("Vikt:\t\t%0.2f\n", b2.vikt ); return 0; } Ett helt program • vid tilldelning kopieras hela strukturen, ingen adresskopiering som vid arrayer!
Strukturer - "struct", post Nu byter vi till en enklare struktur att jobba med, komplexa tal! a + bi
Komplexa tal #include <stdio.h> int main ( void ) { struct Komplex { float a; /* realdel */ float b; /* Imaginärdel */ } z; printf("Ge real och imaginärdel --> "); scanf("%f%f",&z.a, &z.b); printf("%0.2f + %0.2fi", z.a, z.b); return 0 ; } • Ett sätt att definiera en struktur (samma som tidigare)
Komplexa tal • Ett annat sätt att definiera en struktur • typedef struct { • float re; /* realdel */ • float im; /* Imaginärdel */ • } Komplex ; int main ( void ){ Komplex z ;
Arbeta med strukturer • tilldelning ( = ) på strukturer ? • värdeöverföring av strukturer vid funktionsanrop ?
Arbeta med strukturer • tilldelning ( = ) på strukturer ? • värdeöverföring av strukturer vid funktionsanrop ? • . operatorn int main ( void ) { Komplex z ; z = LaesKomplexTal(); SkrivKomplexTal( z ); return 0 ; }
Arbeta med strukturer int main ( void ) { Komplex z ; z = LaesKomplexTal(); SkrivKomplexTal( z ); return 0 ; } • tilldelning (=) på strukturer ? • . • Komplex LaesKomplexTal( void ) { • Komplex z; • printf( "Ge real och imaginärdel --> "); • scanf("%f%f",&z.re, &z.im); • return z; • } Som sagts tidigare så kopieras hela strukturen vid tilldelning
Arbeta med strukturer int main ( void ) { Komplex z ; z = LaesKomplexTal(); SkrivKomplexTal( z ); return 0 ; } • värdeöverföring av strukturer vid funktionsanrop ? • . Vid funktionsanrop på detta sätt så värdeöverförs (kopieras) hela strukturen,jämför med arrayer. void SkrivKomplexTal( Komplex z ) { printf("%0.2f + %0.2fi", z.re, z.im); return; }
Komplettera till ett färdigt program! • vad gör funktionerna? • hur arbetar funktionerna? • inte bra att värdeöverföra strukturer om de är stora. Ändra till referensöver-föring! • int main ( void ) • { • Komplex z1, z2, z3 ; • z1 = LaesKomplexTal(); • z2 = LaesKomplexTal(); • z3 = AdderaKomplex(z1, z2); • SkrivKomplexTal( z3 ); • return 0 ; • }
Komplettera till ett färdigt program! • vad gör funktionerna? • hur arbetar funktionerna? • inte bra att värdeöverföra strukturer om de är stora. Ändra till referensöver-föring! • int main ( void ) • { • Komplex z1, z2, z3 ; • z1 = LaesKomplexTal(); • z2 = LaesKomplexTal(); • z3 = AdderaKomplex(z1, z2); • SkrivKomplexTal( z3 ); • return 0 ; • }
Komplettera till ett färdigt program! • vad gör funktionerna? • hur arbetar funktionerna? • inte bra att värdeöverföra strukturer om de är stora. Ändra till referensöver-föring! • int main ( void ) • { • Komplex z1, z2, z3 ; • z1 = LaesKomplexTal(); • z2 = LaesKomplexTal(); • z3 = AdderaKomplex(z1, z2); • SkrivKomplexTal( z3 ); • return 0 ; • }
/* komplex3.c */ typedefstruct { float re; /* realdel */ float im; /* Imaginärdel */ } Komplex ; z1 = LaesKomplexTal(); z2 = LaesKomplexTal(); z3 = AdderaKomplex(z1, z2);SkrivKomplexTal( z3 ); Komplex AdderaKomplex(Komplex z1, Komplex z2){/* ?? skriv själv ?? */}
Dynamisk allokering • hur fungerar detta program och speciellt funktionen LaesKomplexTal() ? I detta fall jobbar man bara med pekare ( z1, z2, z3 ) till strukturer och då är det onödigt att skriva z1Pek osv. OBS! Att skapa en pekare till en struktur skapar ingen struktur i sig. int main ( void ) { Komplex *z1, *z2, *z3 ; z1 = LaesKomplexTal(); z2 = LaesKomplexTal(); z3 = AdderaKomplex(z1, z2); SkrivKomplexTal( z3 ); free(z1);free(z2);free(z3); return 0 ; }
Dynamisk allokering Hur fungerar funktionenLaesKomplexTal()? Lägg märke till piloperatorn! int main ( void ) { Komplex *z1, *z2, *z3 ; z1 = LaesKomplexTal(); • Komplex* LaesKomplexTal( void ) • { • Komplex *z; • z = malloc(sizeof( Komplex )); • printf( "Ge real och imaginärdel --> "); • scanf("%f%f", &z->re, &(*z).im); • return z ; • }
Heap Heap Dynamisk allokering - "heapen" Bytes Maskinkod programmet • allokerat minne på heapen försvinner inte när funktionen som skapat det "dör" , jämför z resp den komplexa strukturen som skapats på heapen! Komplexstruktur Komplexstruktur LaesKomplexTal() ? ? Stack z Stack z1 z1 z1 main() main() Säkrast är att initiera pekare till NULL (z1) tidsaxel
Arbeta med strukturer • i detta fall har vi inget variabelnamn på det allokerade minnet utan endast en pekare (adress) dit. För att nå de olika delminnena används då ”piloperatorn” • -> operator: z->re , då z är en pekare • Komplex* LaesKomplexTal( void ) • { • Komplex *z; • z = malloc(sizeof( Komplex )); • printf( "Ge real och imaginärdel --> "); • scanf("%f%f", &z->re, &(*z).im); • return z ; • } För att scanf() kräver en adress
Operatorprioritet • högst prioritet har de unära postfixoperatorerna [] () .-> ++ -- • sedan kommer de unära prefixoperatorerna ++ -- & * + - ~ ! (typnamn) • därefter de aritmetiska ( rikning V till H ) * / % + - • skiftoperatorer ( rikning V till H ) << >> • jämförelseoperatorerna ( rikning V till H ) < > <= >= == != • bit-operatorerna ( rikning V till H ) & ^ | • logiska operatorer ( rikning V till H ) && || • villkorsoperatorn ( rikning H till V ) ? uttryck : • tilldelningsoperatorer ( rikning H till V ) = *= /= %= += -= <<= >>= &= ~= |= • kommaoperatorn ( riktning V till höger ) , Då var alla operatorerna ”gröna”!
Arrayer av strukturer går bra! typedef struct { float re; /* realdel */ float im; /* Imaginärdel */ } Komplex ; int main ( void ) { Komplex zVektor[10] ; int i ; zVektor Komplex Komplex Komplex Komplex Komplex Komplex Komplex Komplex Komplex Komplex zVektor[2] zVektor[2].re zVektor[2].im
Sortera element i en array • funktion för detta finns redan Lite repetition!
Sortera element i en array • funktion för detta finns redan
Sortera element i en array • funktion för detta finns redan qsort() i stdlib.h
Sortera element i en array • funktion för detta finns redan och prototypen ser ut på följande sätt • void *base är en pekare till inget men som kan konverteras att peka på någon specifik typ • void qsort(void *base, size_t nelem, size_t width, • int (*fcmp)(const void *, const void *));
Sortera element i en array • funktion för detta finns redan och prototypen ser ut på följande sätt • size_t är ett makro som i ANSI-standard anger typen på returvärdet för funktionen sizeof() • void qsort(void *base, size_t nelem, size_t width, • int (*fcmp)(const void *, const void *));
Sortera element i en array • funktion för detta finns redan och prototypen ser ut på följande sätt • pekare till en funktion (funktionspekare) vars argument är två void-pekare och som returnerar en int • void qsort(void *base, size_t nelem, size_t width, • int (*fcmp)(const void *, const void *));
Sortering implementerat int main ( void ) { Komplex z[5] ; int i ; for ( i=0; i<=4 ; i++) z[i] = LaesKomplexTal(); qsort( (void*) z , 5 , sizeof( Komplex ) , fcompare ); for ( i=0; i<=4 ; i++) SkrivKomplexTal( z[i] ); return 0 ; }
Funktionen fcompare()”hur det skall sorteras” • sorterar på de komplexa talens belopp • int fcompare( const void* z, const void* w){ • if • ( sqrt(pow(((Komplex*)z)->re,2)+pow(((Komplex*)z)->im,2)) < • sqrt(pow(((Komplex*)w)->re,2)+pow(((Komplex*)w)->im,2)) ) • return -1 ; • else if • ( sqrt(pow(((Komplex*)z)->re,2)+pow(((Komplex*)z)->im,2)) > • sqrt(pow(((Komplex*)w)->re,2)+pow(((Komplex*)w)->im,2)) ) • return 1 ; • else return 0 ; • }
Vad tror Du att programmeraren glömt här? #include <math.h>
Vad tror Du att programmeraren glömt här? Använd kompilatorflaggorna: -std=c99 –Wall Läs alla varningar, försök förstå och åtgärda. #include <math.h>