Flerdimensionella vektorer Två-dimensionella 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][2][5];/*en tredimensionell vektor*/ • 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: • Initiering sker på liknande sätt som med endimensionella vektorer. int a[2][2] = {{1, 2}, {4, 0}}; • I minnet lagras dock flerdimensionella vektorer kontinuerligt. 148 Två-dimensionella vektorer 149 Bubble sort #include <math.h> #include <stdio.h> #define N 5 #define M 3 int main(void) { double A[M][N]; int i, j; for (i=0; i<M; i++) { for (j=0; j<N; j++) { A[i][j] = i*N+j; printf("%4.0f", A[i][j]); } printf("\n"); /*Ny rad för varje rad i A */ } } void swap(int *a, int *b) { int tmp; tmp = *a; *a = *b; *b = tmp; } void bubble(int v[], int n) { int i=0, j, swaped=1; while(swaped) { swaped=0; for (j=0; j<n-i-1; j++) if (v[j] > v[j+1]) { swap(&v[j], &v[j+1]); swaped=1; } i++; } } 150 Utskrifter till skärm 151 Flaggor till printf • 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); 152 [] 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. 153 1 Flaggor till printf %[-][x]c %[-][x]s %[ |+][-][0][x]d %[ |+][-][0][x]u %[ |+][-][0][x]o %[ |+][-][0][x]x %[ |+][-][0][x]X %[ |+][-][0][x][.y]f %[ |+][-][0][x][.y]lf %[ |+][-][#][0][x][.y][+z]e %[ |+][-][#][0][x][.y][+z]E %[ |+][-][#][0][x][.y][+z]g %[ |+][-][#][0][x][.y][+z]G Exempel på printf chars strings decimal unsigned decimal octal hexadecimal (with a,b,...) hexadecimal (with A,B,...) float double scientific notation (with e) scientific notation (with E) same as f or e, depending on the value. same as f or E, depending on the value. #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; } 154 Exempel på printf 155 Inläsning från tangentbord • Inläsning från tangentbordet sker vanligtvis med scanf. • Ger utskriften: Variabel Värde -------------------i1 -3 i2 5 c1 c f1 -2.00 f2 +3.30e+00 #include <stdio.h> int scanf(const char* format, ...); • Returnerar: Antalet lyckosamma matchningar. 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); 156 Exempel på scanf 157 Fler strängfunktioner int i; char c; char s[15]; scanf("%d,%*s %% %c %5s %s", &i, &c, s, &s[5]); #include <stdio.h> int sprintf(char *s, const char* format, ...); • 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]. 158 • 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. • scanf läser text från en sträng och inte från tangentbordet. 159 2 Dynamisk minnesallokering 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. • 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. #include <stdlib.h> void *malloc(size_t size); void *calloc(size_t nelem, size_t size); • 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]. int *v = (int*)malloc(10*sizeof(int)); • 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. 160 161 Dynamisk minnesallokering Dynamisk minnesallokering • calloc allokerar nelem element av storleken size. • calloc initierar det allokerade minnets alla bitar till 0; • Motsvarande exempel för calloc blir: • 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 *v = (int*)calloc(10, sizeof(int)); 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. 162 163 Dynamisk minnesallokering Strängexempel int* new_int_array(int n) { int *v; v = (int*)malloc(n*sizeof(int)); return v; } #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); } int main(void) { int *p; p = new_int_array(10); p = new_int_array(10); /* memory lost!!! */ free(p); } • Bild just innan free anropas. s p 164 I l o v e p o i n t e r s \0 I l o v e p o i n t e r s \0 ? ? ? ? 165 3 Argument till main() Echo exempel • 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 innehållande respektive argument. • Kommandot, eller programnamnet, är alltid första argumentet. int main(int argc, char *argv[]) { ... } 166 #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; } 167 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: 168 4