En sammansatt sats eller block är en sekvens av satser, sammanslagna till en enhet med hjälp av ett matchande par av klamrar, { }.



Relevanta dokument
3.3 for-satsen. Programmering, grundkurs, 8.0 hp, Elektro, KTH, hösten Föreläsning 3

Moment Viktiga exempel Övningsuppgifter

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

Programmering i C++ En manual för kursen Datavetenskaplig introduktionskurs 5p

Programmering i C, 7,5 hp

Loopar och datatyper. Föreläsning 3

2.1 Variabler. 2.2 Regler för namngivning i C. Programmering, grundkurs, 8.0 hp, Elektro, KTH, hösten Föreläsning 2

Operatorer Tilldelning Kodblock { } if satsen Logiska uttryck Att programmera

Fråga 11. Vad skrivs ut? Fråga 12. Vad skrivs ut? Fråga 13. Vad skrivs ut? x=x+y; y=x-y; x=x-y;

Följande, ur problemsynpunkt enkla uppgifter, är till för att nöta in dagens teori.

Alla datorprogram har en sak gemensam; alla processerar indata för att producera något slags resultat, utdata.

Användarhandledning Version 1.2

Uppgifter att lösa 1,1,2,3,5,8,13,21...

Funktioner. Räta linjen

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

Programmeringsteknik med C och Matlab

a = a a a a a a ± ± ± ±500

Loopar och datatyper. Föreläsning 3

Den räta linjens ekvation

Fråga 13. Skriv en loop som fyller arrayen int v[100] med talen

Sidor i boken f(x) = a x 2 +b x+c

Gamla tentemensuppgifter

Mathematica. Utdata är Mathematicas svar på dina kommandon. Här ser vi svaret på kommandot från. , x

Tentamen i. för D1 m fl, även distanskursen. lördag 26 februari 2011

Klassdeklaration. Metoddeklaration. Parameteröverföring

Den räta linjens ekvation

Inledande matematik för I1. MVE011 läsperiod Matlab vecka 2 övningsuppgifter

Lösningar och kommentarer till uppgifter i 1.1

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

Föreläsning 2 Programmeringsteknik och C DD1316. Mikael Djurfeldt

JavaScript del 3 If, Operatorer och Confirm

Inledande programmering med C# (1DV402) Summera med while"-satsen

UPPGIFT 1 V75 FIGUR 1.

Objektorienterad programmering Föreläsning 2

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

Uttryck och villkor. Föreläsning 2

STYRANDE SATSER. 1) Skriv ett program som räknar ut hur många år du har till pensionen. Vi räknar här med att man pensioneras det år man fyller 65 år.

Del I: Digitala verktyg är inte tillåtna. Endast svar krävs. Skriv dina svar direkt i provhäftet.

Uttryck och villkor. Föreläsning 2

Problemlösning Lösningar

6 Derivata och grafer

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

Föreläsning 1 & 2 INTRODUKTION

Kompletterande lösningsförslag och ledningar, Matematik 3000 kurs A, kapitel 4. b) = 3 1 = 2

System.out.println("Jaså du har "+ antalhusdjur+ " husdjur"); if ( antalhusdjur > 5 ) System.out.println("Oj det var många);

TDIU01 - Programmering i C++, grundkurs

Programmering, grundkurs, 8.0 hp, Elektro, KTH, hösten 2010

Uttryck, satser och strömhantering

C++ Slumptalsfunktioner + switch-satsen

Föreläsning 3.1: Datastrukturer, en översikt

i LabVIEW. Några programmeringstekniska grundbegrepp

Föreläsning 4. Val, boolska värden, läsbarhet, osv

Alla filer som bearbetar PHP script ska avslutas med ändelsen.php, exempelvis ska en indexsida till en hemsida heta index.php

Introduktion till algoritmer - Lektion 1 Matematikgymnasiet, Läsåret Lektion 1

For-sats/slinga. Notis

Introduktion till programmering SMD180. Föreläsning 4: Villkor och rekursion

Datorteknik 2 (AVR 2)

Prov 1 2. Ellips 12 Numeriska och algebraiska metoder lösningar till övningsproven uppdaterad a) i) Nollställen för polynomet 2x 2 3x 1:

Introduktion till programmering D0009E. Föreläsning 5: Fruktbara funktioner

Grunderna i stegkodsprogrammering

Övningsuppgifter till föreläsning 2 Variabler och uttryck

Vi ska titta närmare på några potensfunktioner och skaffa oss en idé om hur deras kurvor ser ut. Vi har tidigare sett grafen till f(x) = 1 x.

En villkorssats är den konstruktion som finns i C++ för att göra en selektion av två alternativa sekvenser. Formen för if satsen är

1. Inledning, som visar att man inte skall tro på allt man ser. Betrakta denna följd av tal, där varje tal är dubbelt så stort som närmast föregående

Boken?!?! Vad är ett program? Kompilerande-Interpreterande Programmeringsmiljö Hello World! Att programmera och ett enkelt program Variabler printf

Multipel tilldelning. Introduktion till programmering D0009E. Föreläsning 6: Iteration. while-satsen. Kom ihåg. Snurror kontra rekursion

Logik och kontrollstrukturer

Pseudokod. Arbetets gång

Planering av ett större program, del 2 - for och listor. Linda Mannila

Belopp Belopp > procent

Språket Python - Del 1 Grundkurs i programmering med Python

Föreläsning 2 Programmeringsteknik DD1310. Programmering. Programspråk

MMA132: Laboration 2 Matriser i MATLAB

Kompletterande lösningsförslag och ledningar, Matematik 3000 kurs B, kapitel 2

y y 1 = k(x x 1 ) f(x) = 3 x

4 Fler deriveringsregler

HI1024, Programmering, grundkurs, 8hp KTH STH TENTAMEN. HI1024:TEN2 - Praktisk tentamen Tid: Fredagen den 21 oktober 2011,

Moment Viktiga exempel Övningsuppgifter I

Programmering, grundkurs, 8.0 hp HI1024, TEN1. Fredagen den 2 mars 2012

Några inbyggda funktioner (med resultat!) Introduktion till programmering D0009E. Föreläsning 4: Villkor och rekursion. Modulus-operatorn.

Programmering Grundkurs (HI1900) Teoridel

Föreläsning 2 Programmeringsteknik och C DD1316

Programmering i C. Christer Sandberg, Gunilla Eken, Stefan Bygde Olof Andersson Linus Källberg Caroline Uppsäll Johan Hägg

Programmering A. Johan Eliasson

Sidor i boken V.L = 8 H.L. 2+6 = 8 V.L. = H.L.

Programmeringsuppgifter 1

Repetera snabbt vad du lärde dig förra veckan. Du är nu redo att kasta dig in i nästa fas, teorin om villkor.

Laboration 1. "kompilera"-ikonen "exekvera"-ikonen

Laboration 1 Introduktion till Visual Basic 6.0

1 Iteration. 1.1 for-satsen

Repetitionsprov på algebra, p-q-formeln samt andragradsfunktioner

Introduktion till Matlab

3 Deriveringsregler. Vi ska nu bestämma derivatan för dessa fyra funktioner med hjälp av derivatans definition

Lutande torn och kluriga konster!

Data, typ, selektion, iteration

Malmö högskola 2007/2008 Teknik och samhälle

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

Föreläsning 10 Datalogi 1 DA2001. Utskrift på skärmen. Syntax. print( Hej ) Hur är det? Hej. print( Hej,end= ) print( Hur är det? ) HejHur är det?

SMD 134 Objektorienterad programmering

Objektorienterad programmering i Java

Transkript:

Innehåll Förord 1 Kapitel 3 3 3.1 Sammansatt sats........................ 3 3.2 Mer om if-satsen....................... 3 3.3 for-satsen........................... 7 3.4 Maximum och minimum.................... 13 3.5 Att programmera........................ 15 3.6 Programutveckling....................... 16 3.7 Övningsuppgifter........................ 18 3.8 Lösningsförslag......................... 23 3.9 Eftersnack............................ 35

Kapitel 3 3.1 Sammansatt sats En sammansatt sats eller block är en sekvens av satser, sammanslagna till en enhet med hjälp av ett matchande par av klamrar, { }. Syntaktiskt är en sammansatt sats ekvivalent med en ensam sats, något du ska komma ihåg då du studerar senare definitioner av satser i C. Exempel 1. Ett exempel på en sammansatt sats 1 { 2 a=a+10; 3 b=2 a+20; 4 printf("%d %d\n",a,b); 5 } 3.2 Mer om if-satsen Vi har hittills lärt oss hantera den if-sats, som endast har en gren (se figur 3.1).

Kapitel 3 Figur 3.1: Ett flödesschema över den enkla varianten av if-satsen den som saknar else-gren Ofta uppstår dock situationen: Om villkoret är sant ska det här göras annars ska det där göras. Figur 3.2 ger en bild över if-else-satsen. Figur 3.2: Ett flödesschema över if-else-satsen. Om villkoret är sant utförs satsblocket till vänster annars det till höger Exempel 2. En if-else-sats i sin enklaste form 1 if (a>10) 2 a=a 2; 3 else 4 a=a+2; Om variabeln a har ett värde som överskrider 10 så subtraheras 2 från a. I annat fall ökas a med 2. 4

3.2 Mer om if-satsen if-satsen kan kapslas på olika sätt: Exempel 3. En if-else-sats kapslad i en annan. 1 if (a==3) 2 if(b==1) 3 c=1; 4 else 5 c=2; 6 else 7 c=3; Om a är lika med 3, så vet man inte omedelbart vad som ska ske. Det hela beror på b, och om b är lika med 1 så får c värdet 1. c får värdet 2 om a=3 och dessutom b inte är 1. Slutligen får c värdet 3 i de fall då a är något annat än 3. Figur 3.3: I exempel 4, vill man tilldela både variablerna a och b nya värden om c har värdet 0. Eftersom det efter villkoret i if-satsen endast får finnas en enda sats, löser man detta problem, genom att av de två satserna skapa en sammansatt sats. I kod ser det ut så här: 5

Kapitel 3 Exempel 4. En enkel if-sats som styr en sammansatt sats 1 if (c==0) { 2 a=3; 3 b=4; 4 } Med hjälp av ett par klamrar, kan man ju bunta ihop hur många satser som helst till en enda. Hur kommer if-satsen i figur 3.2 då att se ut? Figur 3.4: Sammansatta satser är mycket vanliga, snarare regel än undantag. Likväl händer det då och då, att även vana programmerar glömmer de viktiga klamrarna,{ }. Definition: if-else-satsen har i C följande utseende: 1 if (villkor) 2 ssats 3 [else 4 fsats] Delen av satsen som står innanför hakparenteser är ej nödvändig ssats och fsats är enkla eller sammansatta satser. if-sats kallar vi den enklare varianten. Om värdet hos villkor är sant ( 0) exekveras ssats. Är värdet däremot falskt (0), hoppas satsen över. 6

3.3 for-satsen För den andra konstruktionen, för if-else-satsen, då både ssats och fsats finns med gäller förstås, att då villkor är sant exekveras ssats och då villkor är falskt så exekveras fsats Till skillnad från, bland annat Pascal, saknar C en boolsk datatyp. Vid beräkning av villkor, till exempel x<y, blir resultatet 1 om villkoret är sant och 0 om villkoret är falskt. 3.3 for-satsen En viktig sats är for-satsen, som är en av tre möjligheter att åstadkomma en loop eller snurra i C. Utan möjligheten att låta samma satser utföras flera gånger skulle programmering vara ett tungt jobb (en del anser att det är det ändå). Exempel 5. Ett första exempel: 1 for(k=1;k<=10;k=k+1) 2 printf("d%",k); Variabeln k kallas loopvariabel. Det är den som håller reda på hur många varv snurran har snurrat. I detta exempel startar k med värdet 1 och så länge k är mindre än eller lika med 10 så kommer underlydande satser att utföras. I detta fall har vi bara en sådan sats en printf-sats. När den satsen har utförts exekveras tredje raketsteget i for-satsen k=k+1, som innebär att k ökas med 1, till 2. Därefter kontrolleras om avbrottsvillkoret, k<=10, fortfarande är uppfyllt. Om så är fallet utförs printf-satsen igen. Programmet tuffar vidare och datorn skriver efter hand ut: 1 2 3 4 5 6 7 8 9 10 När talet 10 skrivits ut går programmet som vanligt upp och ökar k med 1 denna gång till 11 och nu, när avbrottsvillkoret testas, visar det sig att det inte längre är sant vilket betyder att for-satsen avbryts och exekveringen fortsätter med de satser som kommer längre ner i programmet. 7

Kapitel 3 Figur 3.5: Ett flödesschema över for-satsen. Siffrorna förklaras av definitionen nedan Definition: for-satsen i C har följande utseende: 1 for ([init];[test];[increment]) 2 [statement] (Delarna av satsen som står innanför hakparenteser är ej nödvändiga) 1 Loopvariabeln initieras, init exekveras. Normalt finns här ett uttryck liknande i=1, men C s syntax tillåter att det här kan finnas ett godtyckligt komplext uttryck. 2 Uttrycket test beräknas. Normalt finns här ett uttryck liknade i<=10. Om resultatet är falskt avbryts loopen. 3 Loopsatsen statement exekveras. 4 for-satsens tredje del, increment, exekveras. Normalt stegas loopvariabeln upp eller ned, som till exempel genom i++. Kontrollen lämnas över till 2. Exempel 6. Ett exempel där loopvariabeln minskas för varje varv 1 for(k=10; k>=0; k=k 1) 2 printf("%d ",k); 8

3.3 for-satsen Vad händer här? Jo k får denna gång startvärdet 10 som skrivs ut. Därefter minskas k till 9. Eftersom villkoret är sant kommer också talet 9 att skrivas ut, liksom 8,7,6,5,4,3,2,1. Vilket kommer då att bli det sista talet som skrivs ut? Efter att 1 har skrivits ut minskas k till 0. Eftersom villkoret fortfarande är sant kommer också talet 0 att skrivas ut. Men sedan är det stopp. Exempel 7. Det är inte indenteringen som avgör vilka satser som hör till loopen! 1 for(p=0; p<3; p=p+0.5) 2 printf("%.2f ",p); 3 printf("hej"); I det här exemplet kan inte p vara deklarerad int eftersom p ska ökas med 0.5 i varje varv. Vilka tal kommer att skrivas ut och hur många gånger kommer HEJ att skrivas ut? Talen på skärmen kommer att bli 0.0, 0.5, 1.0, 1.5, 2.0, 2.5 Talet 3.0 kommer inte att skrivas ut eftersom 3.0 < 3.0 inte är sant! Observera att vi denna gång skrev p<3 och inte p<=3. Ordet HEJ kommer att skrivas ut precis en gång, efter att talen har skrivits ut. Att skriva koden med ett indrag för vissa satser, kallas att indentera. I början kan denna teknik te sig obegriplig eller i varje fall onödig, men efter hand, när programmen blir mer komplicerade visar det sig att indentering är till utmärkt eller rentav nödvändig hjälp. Dock ska man inte, som i exempel 7, låta lura sig av indenteringen och tro att de två sista satserna utgör ett block. Till detta krävs förstås ett par klamrar. Exempel 8. En for-sats som styr en sammansatt sats. 1 sum=0; 2 for(m=1; m<=13; m=m+2){ 3 sum=sum+m; 4 printf("%d ",m); 5 } 9

Kapitel 3 Skriver man så här kommer båda satserna att exekveras i varje varv. Genom klamrarna utgör de två satserna ett block, som i sin helhet styrs av for-satsen. Vilket värde får förresten sum? Loopvariabeln m kommer att anta värdena 1, 3, 5, 7, 9, 11, 13, som alla kommer att skrivas ut. Variabeln sum, som nollställs före loopen, ökas sedan med loopvariabelns värde för varje varv och får till sist värdet 49. Ett viktigt begrepp, som kommer flitigt till användning redan i kapitlets uppgifter, är dubbelloop och trippelloop. Exempel 9. En dubbelloop 1 for(k=1; k<=3; k++) 2 for(l=1; l<=2; l++) 3 printf("%d %d - ",k,l); Först observerar vi uttrycken k++ och l++, som är så typiska för C och som i detta sammanhang är liktydiga med k=k+1 och l=l+1. Över till exekveringen. Under den första loopen med variabeln k finns en sats en for-loop och under den finns en sats printf-sats. Denna konstruktion är vanlig. Observera att det inte ska (behöver) finnas några klamrar här. Trots att koden består tre satser är det inte fråga om någon sammansatt sats. Den yttersta for-loopen styr en sats, den inre for-loopen, som i sin tur styr printf-satsen. Vad händer då när satserna exekveras? Det kan vara lättare att förstå funktionen om man får reda på att utskriften blir: 1 1-1 2-2 1-2 2-3 1-3 2 - printf-satsen utförs alltså sex gånger. Den yttre loopen tre gånger och för varje gång den inre två gånger 2 3 = 6. Det kan ta en liten stund att smälta detta. Ta dig därför en funderare på följande två exempel innan du går vidare. Vilket värde får sum efter följande satser? 10

3.3 for-satsen Exempel 10. Vilket värde har sum efter denna rutin? 1 sum=0; 2 for(k=1; k<=4; k++) 3 for(l=1; l<=5; l++) 4 sum=sum+1; Variabeln sum ökas med 1 varje gång loopsatsen exekveras (vi kunde lika väl ha skrivit sum++), men hur många gånger utförs den? Den yttre loopen snurrar fyra varv och för varje sådant varv snurrar den inre fem, vilket skulle betyda att sum kommer att ökas 20 gånger och till sist få värdet 20. Vi skulle kunna kalla sum för en varvräknare. Exempel 11. Vilket värde får sum här då? Observera skillnaden mellan de inre for-satserna i detta och förra exemplet. 1 sum=0; 2 for(k=1; k<=4; k++) 3 for(l=k; l<=5; l++) 4 sum++; Den yttre loopen snurrar ju fyra varv, men den inre exekveras olika många gånger, eftersom loopvariabeln l får olika startvärden varje gång. Första gången när l startar på 1 (k har värdet 1) utförs loopen 5 gånger, men nästa gång får l startvärdet 2 och då blir det bara 4 varv. När k till sist har värdet 4 och l startar på 4 kommer den inre loopen att göra 2 två varv. Totalt blir det 5+4+3+2 = 14. Variabeln sum får till slut värdet 14. En trippelloop är i och för sig inget speciellt, bara det att den innehåller tre for-satser. Exempel 12. En trippelloop 1 for(x1=1; x1<=10; x1++) 2 for(x2=1; x2<=10; x2++) 3 for(x3=1; x3<=10; x3++) 4 printf("oj VAD DET SNURRAR\n"); Texten i printf-satsen kommer att skrivas ut 1000 gånger! Tänk på hur 11

Kapitel 3 snabbt antalet varv växer, när du konstruerar loopar inuti loopar. Exempel 13. Avgör vilket värde SUMMA kommer att få 1 SUMMA=0; 2 for(k=3; k<=6; k++){ 3 for(l=1; l<=3; l++) 4 SUMMA=SUMMA+l; 5 for(l=1; l<=4; l++) 6 SUMMA=SUMMA+1; 7 } Detta är ingen trippelloop. Den yttre loopen innehåller två inre loopar. När den första har gått färdigt exekveras den andra. Den yttre loopen exekveras sex gånger. Den första inre loopen exekveras tre gånger. I tur och ordning läggs talen 1,2 och 3 till SUMMA. Varje gång den loopen utförs ökar alltså SUMMA med 6. Den andra inre loopen snurrar fyra varv och för varje varv adderas 1 till SUMMA, som alltså totalt ökas med 4. Tillsammans ökar de inre looparna på SUMMA med 10. Eftersom den yttre loopen genomlöps fyra gånger får SUMMA till slut värdet 40. Observera förresten det olämpliga i att använda l som identifierare. l är allt för lik 1. Exempel 14. Eftersom det från for-satsens definition framkom att allt utom semikolonen kunde utelämnas mellan parenteserna, så kan man undra vad man åstadkommer genom 1 for(;;) 2 i++; Konstruktionen är en evighetsloop meningslös men ändå möjlig. Evighetsloopar behöver man inte konstruera med vilje de dyker ändå upp som olycksfall i arbetet. 12

3.4 Maximum och minimum Exempel 15. Vilket värde får sum efter denna rutin? 1 sum=0; 2 for(i=1;i<=5;i++); 3 for(j=1;j<=6;j++); 4 sum++; Det rätta svaret är 1 och det beror på att det här inte alls är frågan om en dubbelloop! Semikolon direkt efter högerparentesen i for-satsen gör den till en tom loop. På sin höjd stegas i upp från 1 till 5. En sådan här konstruktion skulle möjligen kunna tjäna som en "vänteloop", men det är inte säkert, eftersom en smart kompilator kan optimera bort den. I början av karriären glömmer man ofta att avsluta satserna med semikolon. Snart lär man sig det och kommer istället in i en fas då man avslutar alla rader med semikolon, vilket kan ge oönskade effekter liknande de i exempel 15. Observera att eftersom skrivsättet är tillåtet kan datorn inte påpeka misstaget, utan det är du själv som måste upptäcka felet. 3.4 Maximum och minimum Eftersom vi i kommande uppgifter ska söka maximum eller minimum kan det vara bra att ha sett en sådan konstruktion. Programsekvensen nedan tar emot 10 heltal från tangentbordet och håller reda på det största respektive det minsta av dessa. Exempel 16. Vilket är det största respektive minsta talet, av de som kommer att matas in? 1 max=0; min=1000; 2 for(k=1;k<=10;k++){ 3 printf("tal nr %d :",k); 4 scanf("%d",&tal); 5 if (tal<min) min=tal; 6 if (tal>max) max=tal; 7 } Varje gång ett nytt tal matas in jämförs det med två andra tal max och 13

Kapitel 3 min. Om talet är mindre än min, har ett rekord slagits och min får ett nytt värde det värde som tal har. På samma sätt kontrolleras om tal är större än max. Ett problem i sammanhanget är startvärdena för max och min. Normalt kan man väl säga att om max ges ett litet värde från början så kommer troligtvis ett större att dyka upp under inmatningen och detta blir åtminstone tillfälligt max. I exempel 16 är det dock möjligt att alla tio talen, som matas in, är negativa och då kommer aldrig (tal>max) att bli sant vilket betyder att max kommer att behålla det felaktiga värdet 0. Om man inte genom problemets natur kan bestämma vilket startvärde max ska ha, kan följande konstruktion vara nödvändig: Exempel 17. En bättre lösning, som alltid fungerar 1 printf("tal nr 1 :"); 2 scanf("%d",&max); 3 min=max; 4 for(k=2;k<=10;k++){ 5 printf("tal nr %d :",k); 6 scanf("%d",&tal); 7 if (tal<min) min=tal; 8 if (tal>max) max=tal; 9 } Det först inmatade talet kommer att ge sitt värde både till max och min. Därefter kommer loopen, som nu bara frågar efter talen 2 till 10. Denna konstruktion ger alltid korrekta värden på max och min. Om max var deklarerad som int, kunde vi ha ändrat i första exemplet till max=-2147483648; eftersom alla inmatade tal måste vara större än eller lika med detta tal. Om vi i exemplet ovan också vill komma ihåg ordningsnumret på det tal som var det största respektive det minsta utvidgar vi if-satserna till 14

3.5 Att programmera Exempel 18. För att minnas vilket tal i ordningen som gav maximum och minimum tvingas man införa ytterligare två variabler 1 if (tal<min) { 2 min=tal 3 mink=k; 4 } 5 if (tal>max) { 6 max=tal; 7 maxk=k; 8 } Variablerna maxk och mink innehåller, efter att loopen exekverats, ordningsnumren, tal mellan 1 och 10, då det största respektive det minsta talet matades in. Det är klamrarna som binder ihop de två satserna och ser till att de endast utförs då villkoret är sant. 3.5 Att programmera I kapitel 1 startade vi en diskussion om problemlösning. När man läst och förstått en uppgift (uppdrag, kravspecifikation) kan man befinna sig i en av följande tre situationer: Jag klarar inte av att lösa problemet för hand, inte ens för givna indata Jag kan beräkna resultatet för hand för givna indata, men har ingen idé om hur programmet ska skrivas Jag vet hur programmet ska konstrueras för att lösa uppgiften I det första fallet är det definitivt ingen idé att sätta sig vid datorn. Det man inte kan uttrycka på sitt eget modersmål, kan man förstås inte uttrycka i C. Hur man beter sig i denna situation ligger utanför kursen. Bäst är säkert att söka upp lämplig litteratur, ta hjälp av en arbetskamrat, gå en kurs i ämnet eller att helt enkelt själv försöka knäcka problemet. Som tur är, finns det inga uppgifter av den kalibern i denna kurs. Möjligtvis kan det hända, att man någon gång behöver uppsöka en matematikbok. 15

Kapitel 3 Det andra fallet är vanligast för den som just håller på att lära sig programmera. Ofta är det trivialt att utföra arbetet för hand, men man vet inte hur programmet ska konstrueras och struktureras. Den här situationen kommer du troligtvis ofta att hamna i. Men genom den hjälp du får genom att studera lösta uppgifter och exempel och framför allt genom den träning du får genom att lösa många uppgifter kommer du allt oftare att klara av ditt uppdrag. Det tredje fallet. Även om man tror att man direkt skulle kunna sätta sig ner vid datorn och skriva in koden till programmet, så är det oftast bäst att tänka igenom arbetet först upprätta en plan. Det underlättar att använda penna och papper. Så länge uppgiften är relativt liten och du inte måste dokumentera ditt arbete, är det onödigt att ställa krav på hur figurer och text ser ut på ditt kladdpapper, men lova att du alltid har ett kollegieblock vid din sida när du sitter vid datorn och programmerar. Är ni flera som tillsammans ska lösa en uppgift ökar dock kraven på begripliga figurer och text. De är ju med detta som underlag du ska kommunicera. 3.6 Programutveckling Vi utgår ifrån att du förstått uppgiften och att du skulle kunna genomföra arbetet för hand, för givna indata, om du hade tid och tålamod. Det här med att förstå problemet ska dock inte underskattas Visst åstadkoms ett fungerande program, men det löste fel problem. Här följer en lista över saker att tänka på när man lägger upp en plan för programmeringsarbetet: Gör klart för dig vilka indata programmet behöver för att kunna lösa uppgiften. Namnge de variabler som ska ta hand om dessa indata och avgör vilka datatyper de ska tillhöra. Ge dessa variabler, som ju är någon form av huvudvariabler, slagkraftiga namn som ger rätt associationer. Så här långt i kursen handlar det bara om enkla variabler, men längre fram kommer du att stöta på mer eller mindre sammansatta variabler. Det är normalt att tänka sig att indata läses in i början av programmet. Men inte alltid så enkelt som hittills, genom ett par scanfsatser. Kanske läses data bäst in genom en loop, som hämtar data 16

3.6 Programutveckling från fil eller tangentbord. Vi kommer att se många exempel, där inläsning av data och beräkning vävts samman i en loop. När indata väl är på plats kan beräkningarna utföras. Dessa kan variera stort i komplexitet. I ett uppdrag kanske det gäller att bestämma medelåldern av Sveriges befolkning. Även om det är en mängd indata (runt 9000000), så är beräkningarna enkla summera alla åldrar och dividera med antalet invånare. I ett annat uppdrag gäller det istället, att bestämma rötterna till en ekvation. Indata är då kanske bara fyra koefficienter, men beräkningarna, att finna rötterna, kan vara mycket omfattande. När du bestämmer beräkningsdelens innehåll, uppstår behov av nya variabler. En del är så kallade hjälpvariabler, andra är de variabler, som till sist kommer att innehålla själva resultatet. Hjälpvariabler, som till exempel loopvariabler, kan ha korta, ej signifikanta namn, medan resultatvariablerna ska ges beskrivande namn. Det är normalt att tänka sig att utdata skrivs ut i slutet av programexekveringen, men det är inte säkert. Om till exempel beräkningen består av ett antal delresultat, beräknade i en loop, kanske det är smidigast att skriva ut ett delresultat för varje varv i beräkningsloopen. Bestäm hur resultatet ska presenteras (eller det kanske någon annan redan gjort). Normalt handlar det just nu bara om enkla printfsatser, men framöver kommer det att handla om grafiska bilder, filer, komplicerade tabeller och printerutskrifter. Om Du håller dig till dessa tankar när du designar ett program kommer du åtminstone en bit på vägen: Bestäm variabler för indata till namn och typ Bestäm hur indatadialogen ska se ut Bestäm variabler för beräkningar och resultat Bestäm hur beräkningarna ska utföras Bestäm vad som ska skrivas ut och dess layout 17

Kapitel 3 3.7 Övningsuppgifter Till kapitlet hör åtta uppgifter. Självklart ska du lösa dem allihop. Med hjälp av for- och if-satsen kan vi nu lösa problem och skriva program som är aningen mer innehållsrika än i tidigare kapitel. Uppgift 3-1. Loopar med for Skriv ett program, som innehåller fyra for-loopar och som var och en skriver ut en av de fyra talföljderna nedan: a) 1 2 3 4... 20 b) 1 3 5 7... 31 c) 30 28 26 24... 0 d) 2.0 2.5 3.0 3.5... 9.5 Uppgift 3-2. Statistik Skriv ett program som tar emot ett önskat antal positiva heltal från tangentbordet. När talen matats in ska programmet skriva ut: talens summa, det minsta inmatade talet, det största inmatade talet och medelvärdet av talen. Dialogen ska se ut som i exemplet nedan: ANTAL TAL: 3 TAL 1 : 10 TAL 2 : 13 TAL 3 : 4 TALENS SUMMA : 27 STÖRSTA TALET : 13 MINSTA TALET : 4 MEDELVÄRDET : 9 18

3.7 Övningsuppgifter Uppgift 3-3. Domare i konståkning En tävling i konståkning döms av åtta domare. Varje domare ger en poäng mellan 0 och 5, med en decimal. Slutpoäng beräknas genom att först ta bort den högsta respektive den lägsta av domarpoängen. Summera de återstående och ta medelvärdet av denna summa. Resultatet presenteras med två decimaler. Skriv ett program som tar emot domarpoängen och beräknar slutpoängen enligt ovan och som ger följande dialog: DOMARE 1 : 4.3 DOMARE 2 : 4.7 DOMARE 3 : 4.7 DOMARE 4 : 4.7 DOMARE 5 : 4.7 DOMARE 6 : 4.7 DOMARE 7 : 4.3 DOMARE 8 : 4.4 SLUTPOÄNGEN BLIR 4.58 Uppgift 3-4. Temperaturtabell I denna uppgift önskas ett program som skapar en tabell över temperaturer i dels Fahrenheit- och dels Celsiusskalan. Med hjälp av denna formel kan en temperatur i Fahrenheit översättas till Celsius Så här ska dialogen se ut: c = 5 9 (f 32) TABELLSTART : 10 TABELLSTLUT : 13 FAHRENHEIT CELSIUS ---------- ------- 10-12.22 11-11.67 12-11.11 13-10.56 Det är viktigt att tabellen ser snygg och prydlig ut. 19

Kapitel 3 Uppgift 3-5. Brevporto Skriv ett program som tar emot uppgift hur mycket ett brev väger och som med hjälp av denna uppgift och tabellen nedan beräknar portokostnaden. Dialogen ska se ut som följer: Brevets vikt (gram): 43 Portot kostar 2.50 kr Då jag saknar en aktuell portotabell använder vi den som gällde 1980! Vikt (g) Kostnad (kr) - 20 1.30 21-100 2.50 101-250 4.50 251-500 6.50 501-1000 8.80 1001- som paket Uppgift 3-6. Hönsgården Denna uppgift kan enkelt lösas, med hjälp av ren matematik. Nu bortser vi från det och låter i stället datorn med sin enorma snabbhet prova sig fram till ett approximativt svar. Figur 3.6: En bonde inhandlade m meter hönsnät för att göra en hönsgård. Han skapade sedan en rektangulär inhägnad, med maximal area, där en av sidorna var ladugårdens vägg, se figur 3.6. 20

3.7 Övningsuppgifter Skriv ett program som tar emot uppgift om hur många meter rullen innehöll och med hjälp av detta bestämmer den maximala arean och sidornas längder. Dialogen kan komma att se ut som nedan: Meter hönsnät: 100 Den största arean 1250 kvm Kortsidan=25 m Långsidan=50 m Alla variabler i programmet ska vara av typen float och sidorna ska bestämmas på 1 cm när. Fyll i tabellen nedan med hjälp av ditt program: Meter hönsnät Area kvm Långsida Kortsida 100 1250 50 25 200 150 214 Figur 3.7: En skiss över badbryggan. Du befinner dig vid A och sjöjungfrun vid B Uppgift 3-7. Sjöjungfrun Du befinner dig vid början av en badbrygga, se figur 3.7, som sträcker sig rakt ut i böljan den blå, i punkten A. Du upptäcker plötsligt en sjöjungfru 21

Kapitel 3 i sjönöd, i punkten B. För att nå den nödställda så fort som möjligt bör du först springa en bit på bryggan och sedan oförfärat kasta dig i vattnet och simma mot målet. Hur ska du snabbast nå målet om du kan springa på den våta bryggan med en hastighet av 3.0 m/s och simma med hastigheten 1.2 m/s Skriv ett program som beräknar tiden för olika värden på s, där s börjar med 0 och stegas fram med 1 cm för varje beräkning. Det bästa valet på s tillsammans med den totala tiden ska presenteras. Uppgift 3-8. Bestäm slutlönen Slutlönen bestäms av timlönen (kr/tim) och av eventuella tillägg efter följande tabell: Tid Påslag 0:00-5:00 100% 5:00-8:00 50% 17:00-20:00 50% 20:00-24:00 100% Skriv ett program som beräknar den totala lönen. Vi antar för enkelhet skull att arbetspasset ligger inom samma dygn och att klockslagen är i hela timmar. Här en dialog: Arbetspassets start (kl)? 7 Arbetspassets slut (kl)? 12 Lön (kr/tim)? 20 Förtjänsten blir 110 kr 22

3.8 Lösningsförslag 3.8 Lösningsförslag Uppgift 3-1. Loopar med for Diskussion: Skriv ett program, som innehåller samtliga for-loopar. 1 #include <stdio.h> 2 int main(void){ 3 int i; 4 float j; 5 for(i=1;i<=20;i++) 6 printf("%3d",i); 7 printf("\n"); 8 for(i=1;i<=31;i=i+2) 9 printf("%3d",i); 10 printf("\n"); 11 for(i=30;i>=0;i=i 2) 12 printf("%3d",i); 13 printf("\n"); 14 for(j=2;j<=9.5;j=j+0.5) 15 printf("%4.1f",j); 16 } Kommentarer: 18 Observera att loopvariabeln j måste vara deklarerad float. Normalt bör man undvika detta, speciellt om steget är ett icke heltal. Nu är steget 0.5 ett snällt steg eftersom det kan lagras exakt i binär form. Uppgift 3-2. Statistik Diskussion: Indata består, dels av ett tal n, som anger hur många tal, som ska läsas in och dels av talen t i,i = 1...n. Eftersom n kan variera från körning till körning måste de n talen läsas in genom en for-loop. Dels efterfrågas summan av de n talen och medelvärdet m, som vi kan få fram genom att dividera summan med n. Dessutom ska vi för varje 23

Kapitel 3 tal hålla reda på om det just aktuella talet är större än det hittills största respektive mindre än det hittills minsta. Om vi först läser in alla tal för att därefter beräkna efterfrågade storheter får vi problem. Vi har ännu inte infört några möjligheter i kursen att lagra undan flera tal, ett varierat antal, som vi sedan kan plocka fram efter behov. Även om vi kände till den tekniken, så skulle det vara en dålig lösning. Lösningen ligger i att väva samman indata och delar av beräkningarna, så att vi aldrig behöver återvända till ett enskilt tal. Vi konstruerar en loop som exekveras i n varv. För varje varv i loopen läser vi in ett tal, adderar det till en subtotal samt kontrollerar om talet är nytt maximum eller minimum. När denna loop har exekverats återstår endast att beräkna medelvärdet och skriva ut de fem storheterna. 1 #include <stdio.h> 2 #include <limits.h> 3 int main(void) { 4 int summa=0,antal,max= 0,min=INT MAX; 5 int tal,k; 6 float medel; 7 printf("antal TAL: "); 8 scanf("%d",&antal); 9 for (k=1;k<=antal;k++) { 10 printf("tal %d ",k); 11 scanf("%d",&tal); 12 if (tal>max) max=tal; 13 if (tal<min) min=tal; 14 summa=summa+tal; 15 } 16 medel=(float)summa/antal; 17 printf("talens SUMMA : %d\n",summa); 18 printf("största TALET: %d\n",max); 19 printf("minsta TALET : %d\n",min); 20 printf("medelvärdet : %6.3f\n",medel); 21 } Kommentarer: 4 I samband med deklarationen tilldelar vi en del variabler startvärden, initierar. min får värdet INT_MAX och max värdet 0, eftersom 24

3.8 Lösningsförslag det enligt förutsättningarna endast skulle matas in positiva heltal. INT_MAX är det största heltal systemet kan anta, konstanten nås via limits.h 7-8 Antalet varv i for-loopen beror förstås på värdet hos antal. 9-15 Satserna i blocket som styrs av for-satsen följer vårt lösningsförslag ovan. För övrigt är det inte aktuellt med några tester av indata. Att de inmatade talen inte är negativa skulle vi kunna testa, men det fel som uppstår, om vi försöker skriva in ett heltal som 3.45 eller femton, har vi ännu ingen möjlighet att kontrollera. 16 Vi önskar medelvärdet uttryckt med 3 decimaler och måste därför se till att det utförs en flyttalsdivision, vilket kommer att ske då vi omvandlar heltalet i summa till flyttal. Uppgift 3-3. Domare i konståkning Diskussion: Uppgiften påminner till sitt väsen mycket om förra uppgiften. Antalet värden som ska skrivas in är dock förutbestämt och den sista beräkningen är möjligtvis något svårare. Idén bygger på att summera alla domarpoäng och samtidigt hålla reda på den största respektive minsta domarpoängen. När alla data lästs in och adderats, kan från den totala domarpoängen, subtraheras minimum och maximum, för att till sist dividera med 6. 1 #include <stdio.h> 2 int main(void) { 3 float summa=0.0,min,max,slutp,poang; 4 int k; 5 min=5; max=0; 6 for(k=1;k<=8;k++){ 7 printf("domare nr %d : ",k); 8 scanf("%f",&poang); 9 if(poang<min) min=poang; 10 if(poang>max) max=poang; 11 summa=summa+poang; 12 } 13 slutp=(summa min max)/6; 14 printf("slutpoängen blir %.2f\n",slutp); 15 } 25

Kapitel 3 Kommentarer: 5 Den här gången vet vi att poängen inte kan vara större än 5, så därför kan vi lugnt sätta min=5. 13 slutp beräknas på ovan angivet sätt. 14 Resultatet skrivs ut med önskade två decimaler. Uppgift 3-4. Temperaturtabell Diskussioner: En tabell ska åstadkommas. Tabellens storlek bestäms av operatören, genom att ange övre och undre gräns. När indata är mottagna kan beräkningarna, som denna gång är sammanvävda med utdata, påbörjas. Det handlar förstås om en loop där loopvariabeln f, som i Fahrenheit, initieras till den undre gränsen och där avbrottsvillkoret utformas med hjälp av den övre. Själva beräkningarna ges genom formeln. Utskriften kan det bli en del pyssel med trail and error rekommenderas. Men vänta nu! Var i programmet ska rubriken placeras? Inte inne i loopen i alla fall (skäms inte, det är ett mycket vanligt fel). Detta betyder att vi ska skriva ut rubriken innan loopen. När beräkningsloopen är utförd är också hela programmet exekverat. 1 #include <stdio.h> 2 int main(void) { 3 int start,stopp; 4 float f,c; 5 printf("tabellstart: "); 6 scanf("%d",&start); 7 printf("tabellstopp: "); 8 scanf("%d",&stopp); 9 printf("\nfarenheit Celsius\n"); 10 printf("--------- -------\n\n"); 11 for (f=start;f<=stopp;f++){ 12 c=5.0/9.0 (f 32); 13 printf("%9.2f %7.2f\n",f,c); 14 } 15 } 26

3.8 Lösningsförslag Kommentarer: 9-10 I stället för en tom printf-sats, för att få önskade tomma rader, kan man i strängen använda flera \n som var och en ger ett radbyte. 13 På varje plats i strängen där man vill ha ett resultat inlagt skriver man som bekant en formatkod. Antalet mellanslag får man prova sig fram till. Formatkoderna fylls i med värden från listan av variabler efter strängen. Uppgift 3-5. Brevporto Diskussion: Först presenterar vi här en lösning, som endast innehåller enkla if-satser, något vi klarat av redan efter förra kapitlet. Ett sätt att klara sig utan else. Lösningen blir kanske aningen mindre effektiv. Listan består av sex olika portosatser, som leder till lika många if-satser. Det finns endast ett indata, brevets vikt. En vikt som genom olika intervall bestämmer portokostnaden. 1 #include <stdio.h> 2 int main(void) { 3 int vikt; 4 float porto; 5 printf("brevets vikt (gram):"); 6 scanf("%d",&vikt); 7 if(vikt>0 && vikt<=20) porto=1.30; 8 if(vikt>20 && vikt<=100) porto=2.50; 9 if(vikt>100 && vikt<=250) porto=4.50; 10 if(vikt>250 && vikt<=500) porto=6.50; 11 if(vikt>500 && vikt<=1000) porto=8.80; 12 if(vikt>1000) porto=0; 13 if(porto>0) 14 printf("portot kostar %.2f kr",porto); 15 if (porto==0) 16 printf("skickas som paket"); 17 } 27

Kapitel 3 Kommentarer: H Under förutsättning att den inmatade vikten är ett positivt heltal kommer någon av villkoren i if-satserna att bli sant. Detta betyder att porto kommer att tilldelas ett värde. 12 Om vikt är > 1000 kommer porto att få värdet 0. Något vi med framgång kan använda senare i programmet. 13-16 Värdet hos porto kan vi använda för att avgöra om försändelsen ska skickas som paket eller brev. Genom två printf-satser kan vi skriva ut önskat resultat. Här följer en alternativ lösning där den centrala delen består av ett batteri av if - else-satser. 1 #include <stdio.h> 2 int main(void) { 3 int vikt; 4 float porto; 5 printf("brevets vikt (gram):"); 6 scanf("%d",&vikt); 7 if(vikt<=20) porto=1.30; else 8 if(vikt<=100) porto=2.50; else 9 if(vikt<=250) porto=4.50; else 10 if(vikt<=500) porto=6.50; else 11 if(vikt<=1000) porto=8.80; else 12 porto=0; 13 if(porto>0) 14 printf("portot kostar %.2f kr",porto); 15 else 16 printf("skickas som paket"); 17 } Kommentarer: 7-12 Ett if-else-komplex på inte mindre än sex rader. När ett villkor blir sant utförs motsvarande tilldelningssats. Därefter hoppar programmet ut ur strukturen och fortsätter på rad 13. Man behöver därför inte kontrollera den undre gränsen i nästa villkor de fall som inte är större än undre gränsen är ju redan avklarade. 28

3.8 Lösningsförslag Det betyder att när vi når fram till vikt> 1000, så behöver vi inte testa över huvud taget, utan kan direkt tilldela portot det artificiella värdet 0. Uppgift 3-6. Hönsgården Diskussion: Programmet behöver uppgift om nätets längd nl, givet i meter. Genom att variera inhägnadens längd l (parallell med väggen), varieras bredden (vinkelrät mot väggen) indirekt. Figur 3.8: I figur 3.8 ser vi åtta olika konstruktioner av inhägnaden. Två av dem har arean 0, dels den då man spikar upp nätet på ladugårdsväggen och dels den där man sätter en pinne halva nätets längd från väggen. Däremellan finns bland andra den vi söker, den med största arean. Eftersom datorn är snabb kan vi testa alla fall då inhägnadens längd l varieras från 0 till hela nätets längd nl, med steg om en centimeter. För till exempel nl = 100 meter kommer vi då att behöva testa 10001 olika fall. Allt detta ordnar vi med hjälp av en for-loop, som varierar l. Inuti loopen beräknar vi sedan inhägnadens bredd b genom formeln b = nl l 2 Därefter kan vi beräkna aktuell area och jämföra den med tidigare beräknade areor. Visar det sig att aktuell area är den hittills största uppdaterar 29

Kapitel 3 vi rekordet och passar samtidigt på att spara undan aktuella värden på l och b. När loopen exekverats klart, kan vi skriva ut det sökta resultatet. Observera att detta inte måste överensstämma med matematiskt maximum. Eftersom vi här stegat oss fram finns förstås möjligheten att vi stegat förbi det matematiskt korrekta värdet på l och därmed också b. 1 #include <stdio.h> 2 int main(void){ 3 float langsida,langd,kortsida,area; 4 float maxlangsida,maxkortsida,maxarea=0.0; 5 printf("meter hönsnät: "); 6 scanf("%f",&langd); 7 for(langsida=0;langsida<=langd 100;langsida++){ 8 kortsida=(langd langsida)/2; 9 area=kortsida langsida; 10 if (area>maxarea) { 11 maxarea=area; 12 maxkortsida=kortsida; 13 maxlangsida=langsida; 14 } 15 } 16 printf("den största arean %.2f kvm\n",maxarea); 17 printf("kortsidan=%.2f m Långsidan=%.2f m\n", 18 maxkortsida,maxlangsida); 19 } Kommentarer: H När vi skriver program har vi helt andra traditioner att välja variabelnamn, än man har inom matematiken (se texten ovan). 4 Det är viktigt att ge maxarea ett startvärde, där 0 passar bra eftersom vi tror oss veta att det finns minst en konstruktion med positiv area. 7-15 Loopen som kommer att snurra 100 langd+1 varv. 8 Först beräknar vi aktuell bredd hos inhägnaden. 9 Sedan arean. 10-14 Den just beräknade arean jämförs med rekordet, maxarea. Om vi funnit ett nytt rekord uppdaterar vi max-variablerna. 30

3.8 Lösningsförslag 16-18 Resultatet kan skrivas ut Vill vi lösa detta problem matematiskt för låt säga nl = 100, ska vi först finna en funktion f(l), som för givet värde l på inhägnadens längd, beräknar arean. Så här ser den funktionen ut: f(l) = l(100 l) 2 En vanlig andragradsfunktion. Om vi deriverar den, sätter derivatan f (l) = 0 och löser den uppkomna ekvationen får vi f (l) = 50 l f (l) = 0 ger l = 50 b = 25 Ur detta får vi att den största arean är 1250 m 2. Uppgift 3-7. Sjöjungfrun Diskussioner: Nu är det dags för matematik. Vad behöver vi? c 2 = a 2 +b 2 t = s v Pythagoras sats och formeln för att beräkna tiden, när hastighet och sträcka är givna. En figur skadar aldrig. Den har du väl på ditt block också? Figur 3.9: Den vägen du ska springa respektive simma är markerad med ett tjockt streck Vi räknar om sträckor och hastigheter till cm respektive cm/s. s, den väg du ska springa på bryggan, kommer i programmet att stegas upp från 31

Kapitel 3 0 cm till 3000 cm med steget 1 cm. För var och en av de 3001 stegen kommer aktuell tid att beräknas. Tiden på bryggan bestäms av formeln t = s/300. Tiden i vattnet bestäms av den simmade sträckans längd dividerat med 120. Hela formeln för tiden ser ut så här t = s 300 + 25002 +(3000 s) 2 120 Observera att programmet saknar indata. Det betyder att detta program, varje gång det körs, kommer att ge samma resultat. Alltså kör man det bara en gång, efter det att man vet att det är korrekt. För att veta att det är korrekt måste man kanske göra en uträkning för hand. Ingen orkar beräkna formeln ovan 3001 gånger för hand, vilket skulle kunna betyda att man aldrig kommer att få veta om resultatet är korrekt eller inte. Resultatet kommer förresten aldrig att bli korrekt, i matematisk mening, eftersom vi använder en approximativ metod. Visserligen skulle man kunna minska stegen till mm och kanske ännu mindre. Man får då bättre resultat, men det är alltid approximativt. Kan du bestämma det korrekta värdet på matematisk väg, med Mathematica eller för hand? 1 #include <stdio.h> 2 #include <math.h> 3 int main(void){ 4 float t,s,min=1e6,smin; 5 printf("s tid\n--- -------\n"); 6 for(s=0;s<=3000;s++){ 7 t=s/300+sqrt(2500.0 2500.0+( 8 3000.0 s) (3000.0 s))/120; 9 if (t<min){ 10 min=t; 11 smin=s; 12 } 13 printf("%3.0f %6.3f\n",s,t); 14 } 15 printf("minimum (%.4f sek) vid s=%3.0f cm", 16 min,smin); 17 } Kommentarer: H Förutom det slutliga resultatet kommer detta program, som överkurs, att producera en tabell. 32

3.8 Lösningsförslag 4 Lite slarvigt antar vi att den sökta tiden är kortare än 1000000, min=1e6 9-12 När t har beräknats jämförs den med min. Om ett nytt rekord upptäcks kommer min (minimitiden) och smin (sträckan att springa på bryggan) att uppdateras. Vi genomför nu den ovan efterlysta matematiska analysen. Vi har f(s) = s 300 + 25002 +(3000 s) 2 120 Då vi tittar på grafen, ser vi det minimum vi är på jakt efter. 32.5 32 31.5 31 30.5 30 29.5 500 1000 1500 2000 2500 3000 Figur 3.10: Direkt från grafen kan vi avläsa ett värde på ungefär 19 m Vi tar fram f (s) och löser ekvationen f (s) = 0 f (s) = 1 300 3000 s 120 2500 2 +(3000 s) 2 Vi får då s 1 = 3000 5000 21 1908.91 vilket stämmer bra med resultatet som programmet producerar. f(s 1 ) ger den aktuella tiden 29.09 s. 33

Kapitel 3 Uppgift 3-8. Bestäm Slutlönen Diskussion: Vi har här tre indata: starttid, sluttid och timlön. Dessutom finns det ett antal konstanter som beskriver tabellen. Utdata är den totala förtjänsten under arbetspasset. Efter att data har lästs in konstruerar vi en loop, som beräknar lönen för en timme i taget och adderar detta belopp till det som till sist ska bli det totala beloppet. Hur många timmar har den, som börjar 9 : 00 och slutar 14 : 00 arbetat? Hur många varv kommer for(t=9;t<=14;t++) att snurra? Varje varv i loopen ska minst ge ett tillskott till det totala beloppet, som är lika med grundtimpenningen. Om det sedan tillkommer övertidsersättning, avgörs med hjälp av fyra if-satser, som var och en tar hand om en rad i tabellen. Är villkoret sant beräknas den extra ersättningen för den timmen. 1 #include <stdio.h> 2 int main(void) { 3 int start,slut,timme; 4 float lon,summa=0.0; 5 printf("arbetspassets start: "); 6 scanf("%d",&start); 7 printf("arbetspassets slut: "); 8 scanf("%d",&slut); 9 printf("lon (kr/tim) : "); 10 scanf("%f",&lon); 11 for(timme=start;timme<=slut 1;timme++) { 12 if (timme>=0 && timme<5) summa=summa+lon; 13 if (timme>=20 && timme<24) summa=summa+lon; 14 if (timme>=5 && timme<8) summa=summa+0.5 lon; 15 if (timme>=17 && timme<20) summa=summa+0.5 lon; 16 summa=summa+lon; 17 } 18 printf("fortjansten blir %.2f kr\n",summa); 19 } Kommentarer: 3-4 start och slut är heltal, medan lon och summa är flyttal. 34

3.9 Eftersnack 11 För att få rätt antal varv i loopen måste avbrottsvillkoret skrivas timme<=slut-1 eller timme<slut. Allmänt kan sägas att for(i=a;i<=b;i++) genererar b a + 1 varv (a och b heltal). 16 Är inget villkor i loopen sant så kommer endast denna sats att utföras. Man får sin grundlön. 12 Ligger arbetstimmen mellan 0 : 00 och 5 : 00 får man 100% övertidsersättning. 12-15 De fyra if-satserna kan krympas ned till två, men då med mer komplicerade villkor. Bra träning! 3.9 Eftersnack Fråga 1. En kapslad if-sats har följande utseende, här återgiven utan indentering för att göra det hela lite knepigare. Hur tolkar du den? if(a==3) if(b==1) c=1; else c=2; Om du nu bestämt dig för den ena tolkningen, hur ska du då uttrycka den andra? Fråga 2. Man vill med hjälp av en if-konstruktion avgöra vilket betyg en viss uppnådd poäng motsvarar. Vilka av följande konstruktioner är korrekta om tabellen ser ut så här? Poäng Betyg 13-16 3 17-20 4 21-24 5 a) b) c) if(p>=13 && p<=16)b=3; if(p>=21)b=5; if(p>=13) b=3; if(p>=17 && p<=20)b=4; if(p>=17)b=4; if(p>=17) b=4; if(p>=21 && p<=24)b=5; if(p>=13)b=3; if(p>=21) b=5; 35

Kapitel 3 Fråga 3. Är det en nybörjare som har skrivit den här if-satsen? if(a!=1); else b=3; Fråga 4. Hur ofta får variabeln b värdet 10? if(a==1); b=10; Fråga 5. Tror du att man kan skriva en for-sats på det här sättet? for(;;){ printf("ett tal:"); scanf("%d",&tal); sum=sum+tal; } Fråga 6. Konstruera en fungerande for-loop som skriver ut talen1...10 och där själva for-satsen har följande utseende: for(;i<=10;). i är tidigare deklarerad int i=1. Fråga 7. Vi vill ha en rutin som upprepat tar emot tal från tangentbordet och summerar dem tills talet 0 skrivs in. För en sådan rutin tar man helst till en while-loop, men den har vi inte studerat ännu. Kan vi klara det hela med en for-loop? Fråga 8. Vi har två variabler a och b och ska tilldela c det största av dessa tal. Vi får dock, av någon anledning, inte använda en if-sats. Hur kan man med hjälp av en tilldelningssats och med funktionen abs (absolutbeloppet) klara problemet? Fråga 9. Två variabler a och b ska byta värden. Är då detta skrivsätt korrekt? a=b; b=a; Om det inte är korrekt, kan man ändå klara problemet med endast två variabler? 36

3.9 Eftersnack Fråga 10. Så avslutar vi med några logiska uttryck. Skriv om dem utan att använda operatorn ICKE (!). a)!(a>b) b)!(a<=b+3) c)!(a+1==b+1) d)!(a>2 b<5) e)!(a<c && c<d) Svar till eftersnack Svar 1. En else-gren hör till den senaste if-satsen. Vi uttrycker det hela, till vänster, genom indentering. if(a==3) if(b==1) c=1; else c=2; if(a==3){ if(b==1) c=1; }else c=2; Den andra tolkningen den då c ska få värdet 2 då a 3, åstadkommer vi med hjälp av ett extra par klamrar. Svar 2. Konstruktionen i mitten (b) är felaktig. Betyder det att även dessa är fel? if(p>=21) b=5; else if(p>=17) b=4; else if(p>=13) b=3; if(p>=21) b=5; else if(p>=17) b=4; else if(p>=13) b=3; Båda konstruktionerna är likvärdiga (de skiljer sig åt endast i layouten) och dessutom korrekta! Finns det ytterligare variationer? if(p>=13 && p<=24) b=(p-1)/4; Eftersom intervallen för de olika betygen är lika stora fungerar denna konstruktion. 37

Kapitel 3 Svar 3. Javisst! Enklast skrivs det hela: if(a==1) b=3; Visserligen är det inget fel på konstruktionen vare sig syntaktiskt eller logiskt, men varför använda dubbla negeringar? Svar 4. Variabeln b kommer alltid att få värdet 10, oavsett vilket värde a har. if-satsen avslutas i och med semikolonet. if-satsen styr en så kallad tom sats. Svar 5. Ja, det är möjligt. Detta är första konstruktionen av en evighetsloop vi ser. Sådana loopar kommer oftast till av misstag. Här verkar det som om programmeraren vet vad han gör. Likväl är just denna konstruktion här meningslös. Vi kommer senare i kursen att se hur man kan ta sig ur en loop som denna med hjälp av break Svar 6. Detta skrivsätt är möjligt, men klumpigt. Dels måste man på något ställe utanför for-satsen initiera loopvariabeln i och dels måste varvräkningen ske inne i loopen. i=1; for(;i<=10;){ printf("%d ",i); i++; } Svar 7. Ja det går, men som sagt bör man använda en while-loop istället. Hur som helst, så här kan den komma att se ut. tal=1; sum=0; for(;tal>0;){ printf("ett tal: "); scanf("%d",&tal); sum=sum+tal; } Först och främst är det viktigt att tal är 0 innan exekvering av loopen påbörjas. För det andra, när avbrottet sker talet 0 skrivs in så måste man vara medveten om att additionen utförs. Nu gör inte det så mycket eftersom talet för avbrott är 0. Annat hade det varit om detta tal varit -1. Då bör sista satsen i loopen skrivas om till if(tal!=-1) sum=sum+tal Svar 8. Genom följande sats: c=(a+b+abs(a-b))/2; 38

3.9 Eftersnack Svar 9. Nej denna konstruktion är inte korrekt. När man tilldelar a=b, så försvinner förstås det värde a hade innan. Normalt löser man problemet med en hjälpvariabel. c=a; a=b; b=c; Men det går faktiskt att klara sig utan extra variabel! a=a+b; b=a-b; a=a-b; Så ont om minne har man dock sällan. Svar 10. Så här kan det komma att se ut: a) a<=b b) a>b+3 c) a!=b d) a<=2 && b>=5 e) a>=c c>=d I ämnet diskret matematik ingår som en del logik, där man till exempel kan läsa mer om De Morgan s lag, som vi använt oss av i de två sista delproblemen. 39