HØGSKOLEN I SØR-TRØNDELAG Avdeling for informatikk og e-læring - AITeL Kandidatnr: Eksamensdato: 22. desember 2005 Varighet: 4 timer (9:00 13:00) Fagnummer: LO182D Fagnavn: Programmering i C++ Klasse(r): FU Studiepoeng: 6 Faglærer(e): Mildrid Ljosland / Ivar Ørstavik Hjelpemidler: Alle skriftlige, kalkulator Oppgavesettet består av: 3 oppgaver og 4 sider Vedlegg består av: 0 sider Merknad: Oppgaveteksten kan beholdes av studenter som sitter eksamenstiden ut. Lykke til!
Oppgave 1 (40%) I Norge i dag er det vanlig at foreldre har hvert sitt etternavn. Dette skaper unødvendig hodebry når etternavnet til nyfødte barn skal velges. I denne oppgaven skal du lage et C++program som automatisk generer et kjønnsnøytralt etternavn basert på foreldrenes etternavn. a) Lag en klasse som du kaller Person. Person skal inneholde private datamedlemmer som beskriver en persons fornavn, etternavn, fødselsdato og kjønn. b) Lag sett- og finn-funksjoner som kan sette inn og hente ut innholdet av alle datamedlemmene i Person-klassen. c) Lag en medlemsfunksjon lagnyttetternavn( ) som lager nytt etternavn til en Person. Funksjonen skal ha to innargumenter (dvs. kunne ta imot to etternavn). Du kan selv velge hvilke kriterier som skal brukes når et etternavn skal lages, men funksjonen skal likestille menn og kvinner og synliggjøre slektskap til minst en av foreldrene. Kreativitet og humor belønnes! Forklar hvordan funksjonen generer et nytt etternavn. d) Lag deretter en funksjon (ikke-medlemsfunksjon) som kan lese inn data fra brukeren og sette fornavn, etternavn, fødselsdato og kjønn på et Person-objekt. e) Lag så et program som oppretter tre objekter av klassen Person og som bruker funksjonen fra oppgave d til å sette data i alle objektene. f) Person nummer tre skal nå få nytt etternavn basert på etternavnene til de to andre objektene. Avslutt programmet med å skrive ut alle dataene om alle tre Personobjektene. using namespace std; class Person { private: string kjonn; string fnavn; string enavn; string fdato; public: void settfornavn(string n); void settetternavn(string n); void settfodselsdato(string yyyymmdd); void settkjonn(string kjonn); void lagnyttetternavn(string navn1, string navn2); string finnfornavn() const; string finnetternavn() const; string finnfodselsdato() const; string finnkjonn() const; ; 2
void Person::settForNavn(string navn){ fnavn = navn; void Person::settEtterNavn(string navn){ enavn = navn; void Person::settFodselsDato(string dato){ fdato = dato; void Person::settKjonn(string k){ kjonn = k; string Person::finnForNavn() const{ return fnavn; string Person::finnEtterNavn() const{ return enavn; string Person::finnFodselsDato() const{ return fdato; string Person::finnKjonn() const{ return kjonn; void Person::lagNyttEtternavn(string n1, string n2) { enavn = n1 + n2 + "_improved_version"; Person lesperson(){ Person aperson; string n1, n2, d, k; cout << "skriv inn fornavn: " << endl; getline(cin, n1); aperson.settfornavn(n1); cout << "skriv inn etternavn: " << endl; getline(cin, n2); aperson.settetternavn(n2); cout << "skriv inn fødselsdato: " << endl; getline(cin, d); aperson.settfodselsdato(d); cout << "skriv inn kjønn: " << endl; getline(cin, k); aperson.settkjonn(k); return aperson; void skrivperson(person p){ cout << p.finnfornavn() << " " << p.finnetternavn(); cout << " (" <<p.finnkjonn() << ")" << endl; cout << p.finnfodselsdato() << endl << endl; int main() { 3
Person en; Person to; Person tre; en = lesperson(); to = lesperson(); tre = lesperson(); tre.lagnyttetternavn(en.finnetternavn(), to.finnetternavn()); skrivperson(en); skrivperson(to); skrivperson(tre); Oppgave 2 (40%) En veileder ønsker seg et C++-program som holder rede på innleverte øvinger i et fag. a) Definer én endimensjonal tabell med plass til 20 studentnavn og én todimensjonal tabell av heltall med plass til 12 øvinger for hver student. Definer og bruk navngitte konstanter for tabellgrensene. const int maxantstudenter = 20; const int antovinger = 12; string navn[maxantstudenter]; int status[maxantstudenter][antovinger]; b) Data om studentene og øvingene ligger på tekstfilen student.txt. For hver student har vi to linjer: en linje med navnet og deretter en linje med 12 heltall i området 0 til 3 adskilt med mellomrom. Under er et eksempel på en student.txt-fil: Frida Korason 3 3 3 2 3 3 2 1 2 3 0 0 Peter Luring 1 1 3 1 2 2 1 2 0 0 0 0 Lag programlinjer som viser hvordan du vil lese inn dataene om alle studentene og plassere dem i tabellene du definerte i oppgave a. Husk å ta hensyn til at det kan være færre enn 20 studenter som tar faget. int antstudenter = 0; ifstream innfil; innfil.open("student.txt"); if (!innfil) { cout << "feil ved åpning av fil" << endl; exit(exit_failure); string etnavn; getline(innfil, etnavn); while (!innfil.eof() && antstudenter < maxantstudenter) { navn[antstudenter] = etnavn; for (i=0; i < antovinger; i++) innfil >> status[antstudenter][i]; antstudenter++; innfil.ignore(); getline(innfil, etnavn); 4
innfil.close(); c) Programmer en funksjon som finner hvilken indeks en bestemt student (angitt ved navn) finnes på. Eksempel: Søk etter Peter Luring skal returnere verdien 1. (Opplysninger om Peter Lurings øvinger finnes derfor i linje 1 i den todimensjonale tabellen.) int finnplassering( string etnavn, // Inn string *navn, // Inn int antallstudenter) // Inn { int indeks = 0; while (indeks < antallstudenter && etnavn!= navn[indeks]) indeks++; if (indeks >= antallstudenter) return -1; // Ikke funnet else return indeks; d) Programmer en funksjon som finner ut hvor mange 3-tall det finnes blant øvingene til studenten på en bestemt indeks. int finnantallgodkjente( int indeksnr, // Inn int antallstudenter, // Inn int status[maxantstudenter][antovinger]) // Inn { int antall = 0; if (indeksnr >= 0 && indeksnr < antallstudenter) { for (i=0; i < antovinger; i++) { if (status[indeksnr][i] == 3) antall++; return antall; else return -1; // studenten finnes ikke e) I denne deloppgaven kan du velge om du vil skrive C++-kode, pseudokode eller en blanding. Det viktige her er å vise hvordan programmet tenkes bygd opp, og hvordan du vil dele det opp i mindre deler. Vi skal ha et program som gir brukeren mulighet til å gjøre følgende: i. Legge til et nytt studentnavn og sette statusen til 0 for alle øvingene for denne studenten hvis det er plass til flere. Hvis ikke, skal en passende tekst skrives ut til brukeren. ii. Finne status for en bestemt øving for en bestemt student. Status angis slik: 0 betyr Ikke levert, 1 betyr Levert, 2 betyr Ikke godkjent og 3 betyr Godkjent. Studenten angis ved navn, mens øvingene nummereres fra 1 til 12. iii. Endre status for en bestemt øving for en bestemt student. iv. Finne ut hvor mange godkjente øvinger en bestemt student har. v. Finne ut hvor mange studenter som har fått godkjent en bestemt øving. 5
vi. Skrive ut en liste over alle studenter som har fått godkjent minst 8 øvinger. Programmet skal begynne med å hente dataene fra fil og avslutte med å skrive datene til filen igjen. Hovedprogram: Les inn data fra fil (oppgave b) valg = lesmenyvalg (se side 398 i læreboka) Så lenge valg!= avslutt Utfør valg valg = lesmenyvalg Skriv data til fil Utfør valg: Velg mellom Legge til ny student Finne status for en øving Endre status for en øving Finne antall godkjente øvinger Finne antall studenter som har en øving godkjent Skrive liste over studenter med nok godkjente Legge til ny student: Hvis antstudenter >= maxantstudenter skriv melding om at lageret er fullt. Ellers Les navn Finn indeks for studenten (oppgave c) Hvis indeks >= 0 skriv melding om at studenten finnes fra før Ellers navn[antstudenter] = det nye navnet status[antstudenter][i] = 0 (gjøres for i fra 0 til antovinger) antstudenter++ Finne status for en øving Les navn Finn indeks for studenten Hvis indeks < 0 skriv melding om at studenten ikke finnes Ellers Les øvingsnr (bruker lestalliintervall(1,12) fra side 153 i læreboka) øvingsstatus = status[indeks][ovingsnr-1] finn tilhørende tekst return tekst Finn tilhørende tekst hvis status==0 return Ikke levert ellers hvis status == 1 return Levert ellers hvis status == 2 return Ikke godkjent ellers return Godkjent 6
Endre status for en øving Les navn Finn indeks for studenten Hvis indeks < 0 skriv melding om at studenten ikke finnes Ellers Les øvingsnr (bruker lestalliintervall(1,12) fra side 153 i læreboka) Les nystatus (bruker lestalliintervall(0, 3) ) status[indeks][øvingsnr-1] = nystatus Finne antall godkjente øvinger Les navn Finn indeks for studenten Hvis indeks < 0 skriv melding om at studenten ikke finnes Ellers return finnantallgodkjente(indeks) (fra oppgave d) Finne antall studenter som har en øving godkjent Les øvingsnr (bruker lestalliintervall) antall = 0 for (i=0; i < antstudenter; i++) if (status[i][øvingsnr-1] == 3) antall++ return antall Skrive liste over studenter med nok godkjente for (i=0; i < antstudenter; i++) antall = finnantallgodkjente(i) hvis (antall >= 8) skriv navn[i] Oppgave 3 (20%) Fibonaccitallene er en spesiell tallrekke som dukker opp i ulike sammenhenger. Bl.a. har det vært påvist at antall skjell i furukongler og hvorvidt biegg blir til hannbier eller hunnbier fordeler seg etter samme mønster som denne tallrekken. De ti første fibonaccitallene er 0, 1, 1, 2, 3, 5, 8, 13, 21, 34. Neste tall dannes hele tiden som summen av de to foregående, f.eks. er 34 = 13+21. Fibonaccitallene nummereres fra 0 og oppover og betegnes med f med en indeks som angir hvilket nummer de har. Altså: f 0 betyr fibonaccitall nr 0, som har verdien 0, mens f 9 betegner fibonaccitall nr 9, som har verdien 34. I denne oppgaven skal vi lage funksjoner i C++ som på ulike måter beregner verdien på fibonaccitall. a) Den enkleste måten å beregne fibonaccitall på, er å starte med f 0 og f 1 og lage en løkke som summerer to og to inntil vi kommer fram til det nummeret i rekka som vi er på jakt etter. Eksempel: For å beregne f 4, beregner vi først f 2 = f 1 +f 0 =1+0=1, deretter (i neste runde av løkka) f 3 =f 2 +f 1 =1+1=2, og i tredje og siste runde f 4 =f 3 +f 2 =2+1=3. Lag funksjonen int fib1(int n) som gjør dette. fib1(4) skal altså gi 3 som svar, mens fib1(9) skal gi svaret 34. int fib1(int n) { int x1 = 1; 7
int x2 = 0; if (n <= 0) return 0; for (i=1; i < n; i++) { int temp = x1 + x2; x2 = x1; x1 = temp; return x1; b) Nå skal vi se på en mer komplisert, men (for datamaskinen) raskere måte å beregne fibonaccitall på. Det første skrittet i denne prosessen er å lage en funksjon som gjør følgende: Hvis vi sender inn tallene a, b, c og d, skal vi få ut igjen tallene x og y der x=(a+b)*c+a*d og y=a*c+b*d. Lag funksjonen beregnxy( ) som utfører dette. void beregnxy(int a, int b, int c, int d, int &x, int &y) { x = (a+b)*c + a*d; y = a*c + b*d; c) Det viser seg at dersom vi lar: a være et fibonaccitall (vi kaller dette f k ), b være det fibonaccitallet som kommer like foran a (altså f k-1 ), c = 1 og d = 0, så vil x fra funksjonen beregnxy( ) bli f k+1 og y bli f k. Lag funksjonen int fib2(int n) som beregner f n ved hjelp av denne metoden. Denne funksjonen må også ha en løkke slik som funksjonen i oppgave a, samt bruke funksjonen beregnxy( ). int fib2(int n) { int x1 = 1; int x2 = 0; if (n <= 0) return 0; for (i=1; i < n; i++) beregnxy(x1, x2, 1, 0, x1, x2); return x1; d) Videre viser det seg at hvis vi lar c = 1 og d = 1, så vil vi i stedet for å få ut x = f k+1 og y = f k, få ut x = f k+2 og y = f k+1. Dette gjør at løkka trenger å gå halvparten så mange ganger. Lag en funksjon int fib3(int n) som gjør dette. int fib3(int n) { int x1 = 1; int x2 = 0; for (i=1; i < n; i+=2) beregnxy(x1, x2, 1, 1, x1, x2); if (n%2 == 0) return x2; else return x1; 8