Læringsmål:

  • Switch
  • Utskrift
  • Betingelser
  • Funksjoner
  • FOR-løkker
  • WHILE-løkker
  • Doble FOR-løkker 

Pensum:

  • 3.3 - Input and Output
  • 3.7 - User-Defined Functions That Return a Single Value
  • 4.1 - The if Statement
  • 4.2 - The if-else Statement
  • 4.3 - Nested if-else Statement
  • 4.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 kjøres skal det se omtrent slik ut:

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

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

  1. Månedsnavn og årstall: Oktober 2017
  2. Navn på ukedager: (ma ti on to fr lo so)
  3. Datoer for alle dager på riktig plass. (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å funksjonen getMonthName(monthNumber) som returnerer navnet på måneden gitt månedsnummer som inputparameter. 

>> getMonthName(7)
ans = 
	'Juli'

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.

Kopier følgende kode og lagre i øvingsmappen
function calendar = getCalendar ( year , month )
	startDay = getMonthStartDay ( year , month );
	numDays = daysInMonth ( month , year );
	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

 

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:

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.

Her kan du bruke kode du har skrevet i tidligere øvinger dersom du ønsker det.
Eksempel 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 

 

 

d) Vi kommer nå etterhvert til funksjonen getMonthStartDay(). For å skrive denne trenger vi først å vite hvilken dag året 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). 
Å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:

Eksempel på input og tilhørende utskrift
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



e) Lag nå 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). 

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 matrisedelen av kalenderen bør være en egen funksjon:


f) Lag funksjonen printDays(month). Den skal ta inn en matrise med datoer som parameter, og skrive ut disse som vist 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()

 

Eksempel 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.



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

 

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

Eksempel 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.

 
>> 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