Versions Compared

Key

  • This line was added.
  • This line was removed.
  • Formatting was changed.

Læringsmål:

  • Switch
  • fprintfUtskrift
  • If-setningerBetingelser
  • Funksjoner
  • FOR-løkker
  • ForWHILE-løkker
  • Doble FOR-løkker 

Pensum:

  • 3.3 - Input and Output
  • 3.7 - User-Defined Functions That Return a Single Value
  • Kap 4.1 - The if Statement
  • 4.2 - The if-else Statement
  • 4.3 - Nested if-else Statement
  • 4.4
  • Kap 3.3.2
  • Kap 3.7
  • Kap 5.4
  • - The switch statement
  • 5.1 - The FOR-loop
  • 5.2 - Nested FOR-loops
  • 5.3 - While loops
  • 5.4 - Loops with Vectors and Matrices: Vectorizing

 

Denne øvingen er en mye mer omfattende øving enn hva dere er vant med til nå. Vi skal nå implementere flere forskjellige funksjoner, og til slutt sette alle disse sammen til et program som gir oss en utskrift av en kalender.  
Når koden til slutt I denne øvingen skal vi implementere funksjonen printCalendar. Den skal vise en gyldig månedskalender gitt månednummer og år som parameter. 
Om koden kjøres skal det se omtrent slik ut:

Code Block
languagenone
Oktober 20142017
ma ti on to fr lo so
       			  1   
2  3  4  5
  6  7  8  
9 9 10 11 12
 13 14 15 15 
16 17 18 19
 20 21 22 22 
23 24 25 26
 27 28 29 29 
30 31

Dette problemet må brytes ned i mindre oppgaver. Fra utskriften ser man at den består av tre deler:

  1. Månedsnavn og årstall. Første rad.Dagsnavn. Andre rad.: Oktober 2017
  2. Navn på ukedager: (ma ti on to fr lo so)
  3. Datoer for alle dager på riktig plass. Tredje til syvende rad. (Datoene 1 til 31)

Vi skal nå implementere de forskjellige funksjonene som gir oss disse tre delene. Deretter skal alle disse settes sammen til å produsere utskriften som vist over.

 

 

a)  Første funksjon vi skal lage gir oss navnet på en måned, gitt et månedsnummer input. Hvis funksjonen tar inn tallet 1 skal den returnere 'Januar', hvis den tar inn 2 skal den returnere 'Februar', etc. Lag nå a) Månedsnummer må gjøres om til månedsnavn. Lag funksjonen getMonthName(monthNumber) som returnerer navnet på måneden gitt månedsnrmånedsnummer som inputparameter.  

Andre rad er en enkel iterasjon gjennom en liste av navn på dagene. De siste radene er mer bry: Disse utgjør en 6x7 matrise hvor radene er uker og kolonnene er ukedager. Denne matrisen kan se slik ut: 

Code Block
languagenone
month =
0	0	1	2	3	4	5
6	7	8	9	10	11	12
13	14	15	16	17	18	19
20	21	22	23	24	25	26
27	28	29	30	31	0	0
0	0	0	0	0	0	0

Tallet 0 representerer dager som ikke finnes i måneden.
Neste steg er å definere en funksjon som lager denne matrisen. Det gjør følgende funksjon:

>> getMonthName(7)
ans = 
	'Juli'
Expand
titleHint

Her kan det være lurt å benytte seg av en SWITCH-setning.

 

 

Hvis vi nå ser på oppgaven igjen, og den utskriften vi til slutt skal komme frem til, ser vi at vi på en eller annen måte må få skrevet ut de forskjellige ukedagene i kalenderen. Vi har allerede skrevet kode for deg som tar inn et årstall og et månedsnummer og returnerer en matrise som gir deg en liknende utskrift. Ta nå og kopier koden nedenfor, og lagre det som getCalendar.m i øvingsmappen din.

Code Block
titleKopier følgende kode og lagre i øvingsmappen
Code Block
languagenone
function calendar = getCalendar ( year , month )
	startDay = getMonthStartDay ( year , month );
	numDays = daysInMonth ( yearmonth , monthyear );
	calendar = zeros ( 6, 7 );
	date = 0;
	for week = 1:6
		for day = 1:7
			if ( date == 0 )
				if ( week == 1 && day == startDay )
					date = 1;
				end
			else
				if ( date < numDays )
					date = date + 1;
				else
					date = 0;
				end
			end
			calendar (week , day ) = date ;
		end
	end
end

 

Her returnerer funksjonen daysInMonth antall dager i måned, getMonthStartDay returnerer nummeret på den første ukedagen i måneden (1 = Mandag, 2 = Tirsdag, ..., 7 = Søndag). I eksempelet med oktober 2014, returnerer daysInMonth 31 og getMonthStartDay 3.

...

Når du har lagt inn denne koden, vil ikke denne kjøre med det første, dette er noe vi skal fikse etterpå. Det eneste du trenger å merke deg nå er utskriften denne funksjonen (til slutt) skal gi ut:

Code Block
languagenone
month =
0	0	1	2	3	4	5
6	7	8	9	10	11	12
13	14	15	16	17	18	19
20	21	22	23	24	25	26
27	28	29	30	31	0	0
0	0	0	0	0	0	0

Her representerer tallet 0 dager som ikke finnes i måneden. Vi ser at dette begynner å ligne på kalenderen som ble vist som eksempel øverst i øvingsoppgaven.

 

b) Du har sikkert lagt merke til at vi bruker noen funksjoner i getCalendar() som vi ikke har laget enda. Din oppgave nå er å implementere funksjonen daysInMonth(monthNumber, year)Funksjonen skal returnere antall dager i en måned, gitt et månedsnummer av samme type som i oppgave a). Du må også ta hensyn til skuddår.

Expand
titleHint
Her kan du bruke kode du har skrevet i tidligere øvinger dersom du ønsker det.
Code Block
titleEksempel på kjøring
daysInMonth (1, 1999) % skal skrive ut 31
daysInMonth (2, 2001) % skal skrive ut 28
daysInMonth (4, 2017) % skal skrive ut 30
daysInMonth (2, 2004) % skal skrive ut 29

 


c) Du blir nå gitt parametrene startDay = 3 og numDays = 31 i getCalendar-funksjonen over. Gå gjennom funksjonen

...

og skriv ned verdien til variablene week, day og date for hver iterasjon i den indre for-løkken. Du skal med andre ord ikke skrive eller kjøre kode, dette er en øving i å se for seg hvordan koden vil kjøre på forhånd, noe som kreves på eksamen.

.                                                                   Det holder å skrive ned de første 12 iterasjonene, og deler av tabellen er fylt ut nedenfor.

Iterasjonweekdaydate

1
2
...

%fyll inn

12 

1
1
...

%

1
2
...

%

0
0
...

%

10 

 

 

Legg inn funksjonen getCalendar (se over). Denne krever at vi implementerer funksjonene daysInMonth og getMonthStartDay.                                                                                                                                                                    Du kan bruke filene daysInMonth.m og isLeapYear.m fra tidligere øvinger. 

For å kunne definere funksjonen getMonthStartDay trenger d) Vi kommer nå etterhvert til funksjonen getMonthStartDay(). For å skrive denne trenger vi først å vite hvilken dag året starter på.c) starter på. Derfor lager vi først en hendig hjelpefunksjon til å regne ut dette for oss.

Lag funksjonen getYearStartDay(year). Funksjonen skal ta inn et årstall som parameter

...

og returnere hvilken ukedag året starter på (1 = Mandag, 2 = Tirsdag, ..., 7 = Søndag). 

...

Expand
titleHint
Året 1900 startet på en mandag. For hvert år flytter startdagen seg med en dag.

...

Det vil si at 1901 startet på en tirsdag. Hvis året er et skuddår, flytter startdagen i neste år

...

seg med to dager. Dersom du ønsker kan du også her benytte deg av kode du har skrevet i tidligere øvinger.


 For å teste denne funksjonen kan du kjøre følgende skript:

Code Block
titleEksempel på input og tilhørende utskriftlanguagenone
getYearStartDay (1900) % skal returnere 1
getYearStartDay (1901) % skal returnere 2
getYearStartDay (1902) % skal returnere 3
getYearStartDay (1903) % skal returnere 4
getYearStartDay (1904) % skal returnere 5
getYearStartDay (1905) % skal returnere 7
getYearStartDay (1906) % skal returnere 1
getYearStartDay (2012) % skal returnere 7



deLag funksjonen getMonthStartDay(year, monthNumber). Den skal ta inn et årstall og et månedsnummer som parameter (1 = Januar, 2 = Februar, ..., 12 = Desember). Funksjonen skal returnere hvilken ukedag måneden starter på (1 = Mandag, 2 = Tirsdag, ..., 7 = Søndag). 

Code Block
languagenone
getMonthStartDay (2012 , 0) % skal returnere 0
getMonthStartDay (2012 , 1) % skal returnere 7
getMonthStartDay (2012 , 2) % skal returnere 3
getMonthStartDay (2012 , 3) % skal returnere 4
getMonthStartDay (2012 , 4) % skal returnere 7
getMonthStartDay (2012 , 5) % skal returnere 2
getMonthStartDay (2012 , 6) % skal returnere 5
getMonthStartDay (2012 , 7) % skal returnere 7
getMonthStartDay (2012 , 8) % skal returnere 3
getMonthStartDay (2012 , 9) % skal returnere 6
getMonthStartDay (2012 , 10) % skal returnere 1
getMonthStartDay (2012 , 11) % skal returnere 4
getMonthStartDay (2012 , 12) % skal returnere 6
getMonthStartDay (2012 , 13) % skal returnere 0

...

Du har hittil brutt kalenderen ned i mindre funksjoner. Nå skal de settes sammen og en kalender skal vises. 
disp() er for enkel, derfor må fprintf() benyttes.  Se fprintf for bruk. 

Å vise matrisedelene matrisedelen av kalenderen bør være en egen funksjon.:


efLag funksjonen printDays(daysmonth). Den skal ta inn matrisen som funksjonen i oppgave 3 lager som parameteren matrise med datoer som parameter, og printe skrive ut datoene disse som vist i toppen av øvingen. Denne funksjonen skal ikke returnere noen verdi. Funksjonshodet kan dermed se slik ut:

Code Block
languagenone
function printDays ( days )
	% Din kode
end

under. Her må vi nå benytte oss av getCalendar()-funksjonen vi la inn tidligere, og du kan se eksempelutskriften fra denne for å se for deg hvordan input vil se ut. printDays() skal ikke returnere noen verdi, men skrive ut en utskrift ved hjelp av fprintf()

 

Code Block
titleEksempel på utskrift ved kjøring av funksjonen
>> printDays(month)
 
         		  1  
2  3  4  5  6  7  8  
9  10 11 12 13 14 15 
16 17 18 19 20 21 22 
23 24 25 26 27 28 29 
30 31

Merk deg at vi nå har erstattet 0-tallene fra getCalendar med mellomrom (whitespace). Det er opp til deg selv å finne en god løsning på dette.



gf) Lag funksjonen printCalendar(year, monthNumber). Parameterene er år og månedsnummer. Den benytter Funksjonen skal sette sammen alle de tidligere funksjonene. For å gjøre dette må funksjonen benytte seg av getMonthName og getCalendar og printer ut de to første linjene av kalenderen før den  og lagre resultatene fra å kjøre disse funksjonene, før den til slutt kaller på printDays(). Den Denne funksjonen skal heller ikke returnere noe, bare vise utskrift. men skal skrive ut utskriften som vist i eksempelet nedenfor.

 

Det ferdige resultatet kan se slik ut, dersom man kaller på printCalendar(2017, 10):

Code Block
titleEksempel på utskrift
Oktober 2017
ma ti on to fr lo so
       			  1  
2  3  4  5  6  7  8  
9  10 11 12 13 14 15 
16 17 18 19 20 21 22 
23 24 25 26 27 28 29 
30 31

 

 

h) ((star)(star)) Frivillig.

Utvid printCalendar til også å printe ukenummer. For å få til dette, må du også lage nye funksjoner og utvide eksisterende.

Dette er en veldig vanskelig oppgave.

Code Block
languagenone
 
>> printCalendar(2017, 9)
	September 2017
Uke	ma ti on to fr lo so
35	             1  2  3 
36	 4  5  6  7  8  9 10 
37	11 12 13 14 15 16 17 
38	18 19 20 21 22 23 24 
39	25 26 27 28 29 30    
 
>> printCalendar(2017, 1)
	Januar 2017
Uke	ma ti on to fr lo so
52	                   1 
1	 2  3  4  5  6  7  8 
2	 9 10 11 12 13 14 15 
3	16 17 18 19 20 21 22 
4	23 24 25 26 27 28 29 
5	30 31