Funktioner och programorganisation

Föreläsning 6,
F.Bergholm
• Alla professionella programmerare använder debug. (Utom det
lilla fåtal som tycker om att göra massvis med kontrollutskrifter).
Detta gäller stora program, halvstora program , icke-triviala
algoritmer. Samt svåranalyserade fel i små program.
• I små enkla program duger ofta kontrollutskrifter.
• Vanligt debugprogram:
gdb
• (BRYTPUNKT) Stanna programmet på viss rad och titta
på variablerna.
• (STEGA RAD FÖR RAD) Kör en rad i taget och titta på
vad som händer med variablerna
Vanliga kommandon i en debugger är:
r
c
s
b 9
p x
(=run)
(=continue)
(=gå en rad till)
(=stanna på rad 9 (t.ex))
(=skriv ut variabeln x)
• (Rad för rad) En debugger (ett felsökningsprogram) går vanligtvis
rad för rad med s-kommandot (s=step) utan att gå in i funktioner. Om
man vill gå in i funktioner finns n-kommandot .
• (Brytpunkt i funktion) Istället för att ha en brytpunkt på en rad kan
man ange vilken funktion man vill stanna i.
Typiska varianter på de vanligaste
kommandona (b,p,r,c,s), är i gdb:
info local (=lista alla lokala variabler)
b
n
b
b
17 if n == 10
(=gå in i funktion,step inside)
main (=stanna i main)
foo (=stanna i funktion foo)
För att starta debug med gdb måste man kompilera:
gcc -g program.c -o program
Därefter kör man exe-filen med gdb:
gdb
program.exe
(Det beror på att felsökningsprogram behöver inte bara
maskinkod utan ytterligare information, en specialkompilering
(Option: -g) krävs.)
(gdb)
b 9
(gdb)
r
(gdb)
info local
a= 3, area=7
antal=16
(gdb)
s
(gdb)
s
(gdb)
p
antal
antal=17
(gdb)
c
Program exited with 0
(gdb)
quit
(gdb)
l
1 #include <stdio.h>
2 int main() {
3 printf(”Hej\n ”);
4 return 0;
5}
(gdb) b 3
(gdb) r
osv….
Man listar med kommandot ”l” (litet L), eller ”l 10”, som
betyder lista de 10 kommande raderna. Rött är gdb:s utskrift.
Grundide:
Lägg in alla heltal i en lång
vektor genom att markera med 1 vilka tal
som ska sorteras. (Vektorarrayen är
initierad med nollor.)
int
v[100]={0};
Sortera
talen:
5,3,10,9
V=
0 0 1 0 1 0 0 0 1 1 0…
En for-slinga behövs för att lägga in
heltalen (=ettorna) i arrayen v.
Ytterligare en for-slinga behövs för att ta i
tur och ordning de tal som inte är noll i
arrayen. Gör man det, blir talen
automatiskt sorterade (skiss):
if (v[i] != 0)
res[j++]= i;
Ett idiom är ett invant mönster (som man använder vid
C-programmering) av säkerhetsskäl.
Exempel:
Stega alltid från noll till
i< längden av arrayen, i en for-slinga.
Då kommer man inte UTANFÖR arrayen. Om (King, s.163 )man
kommer utanför en array kan vad-som-helst hända.)
int
for
v[125];
(i=0, i< 125; ++i)
SKRIV INTE
for
(i=0; i <=124; ++i)
for
(i= 1; i <=125; ++i)
• Läs F6debug.pdf. Läs F6debugBeskrivning.pdf.
• Läs F5_6checklista.pdf noga., och testa att med flit göra de fel
som nämns. Testa speciellt ”blankfällan” dvs att i scanf skriva
”%d ” med ett blanktecken efter d:et, dvs ”%d ”.
• * Programmera själva pigeon hole-uppgift (finns efter denna
sida)
• * Gör utdelad övning på idiom (finns efter denna sida)
• *Gör en funktion platsbyt(&a,&b,&c) som byter plats på värdena så att a
får b:s värde, b får c:s värde och c får a:s värde,där vi antar att
variablerna är deklarerade double a,b,c i main().
• Repetera Förel. 1-5, och gör övningar du missat. Testa debug!
Det underlättar i labbarna
• Gör debug på Isdans-poängprogrammet. (se nästa sida)
#include <stdio.h>
int poang[4][8]= {{4,5,4,4,5,4,4,3},
{4,4,4,4,4,4,4,4},
{4,5,5,5,5,5,5,5},
{5,4,3,4,3,5,3,2}};
double beraknaPoang(int par[], int antal);
int main() {
int i=0; int antal; //antal domare
int par[]; double res=0;
for (i=0; i<4; ++i) {
par= poang[i];
res= beraknaPoang(par,antal);
printf(”slutpoang= %f \n”,res);
}
return 0;
} /*end main*/
/*
***************************
Funktionen beraknapoang()
***************************/
double beraknaPoang(int par[], int antal)
double max,min,summa=0; int j=0;
for (j=1;j<antal; ++j) {
summa= summa+ par[j];
if (par[j]>max) max= par[j];
if (par[j]<min) min= par[j];
}
return (summa-max-min)/(antal-2);
}
Uppg.1 Gör en for-loop som printar ut innehållet i
vektorn
double varden[5]={1,1.5,1.75,1.875,1.9375};
Uppg.2 Gör 2 dubbelloopar (for) för matrisen
(matrisarrayen) int schack[8][8],
Fyll den med varden,
bonde=1,torn=2,springare=3,dam=4,kung=5.
tom=0, och skriv ut matrisen.
Uppg.3 Gör en for-loop som kastar tärning med rand().
Uppg.4 Gör en while-slinga som läser förbi nollor i en
pigeon-hole vektor. (Idiomet är att ha en tom sats i
while-slingan.)
Uppg.5 Använd ++-operatorn inuti en indicerad variabel
i en slinga. Du ska först hämta värdet, sedan
inkrementera index (dvs öka med 1).
UPPG: Slumpa tal mellan 1 och 100, men släng bort tal
som sammanfaller, och sortera dem med pigeon holemetoden. Man ska slumpa 50 gånger.
TIPS: Använd vektorn int v[100] för att lagra nollorna
och ettorna i. Och det är smart att lagra nollor och
”antal förekomster” istället för ettor.
TIPS: När man slumpar med rand(),som tal%100, får man
tal mellan 0 och 99. Man förskjuter detta till 1
och 100, på enklaste sätt.
(Detta är också ett idiom.)