HØGSKOLEN I SØR-TRØNDELAG Avdeling for informatikk og e-læring - AITeL Kandidatnr: Eksamensdato: Varighet: Fagnummer: Fagnavn: Klasse(r): Studiepoeng: Faglærer(e): Hjelpemidler: Oppgavesettet består av: 25. mai 2004 4 timer (9:00 13:00) LO182D Programmering i C++ NVU 6 Mildrid Ljosland Alle skriftlige, kalulator 3 oppgaver og 3 sider Vedlegg består av: Merknad: Oppgaveteksten kan beholdes av studenter som sitter eksamenstiden ut. Lykke til!
Oppgave 1 (40%) a) Lag en liten programbit som avrunder et heltall i området 1 til 9 på følgende måte: Hvis tallet er 1 avrunder vi til 2. Hvis tallet er 2, 3 eller 4 avrunder vi til 5. Hvis tallet er større eller lik 5 avrunder vi til 10. int enkelavrunding( int verdi) if (verdi <= 1) return 2; else if (verdi <= 4) return 5; else return 10; (Men det var ikke noe krav om at det skulle være en funksjon, så også bare de tre linjene med funksjonsinnholdet ville vært godkjent svar.) b) Lag en funksjon som avrunder et hvilket som helst heltall på følgende måte: Hvis tallet er 0 eller negativt avrundes til 0. Ellers: Hent ut det første sifferet i tallet. Avrund det som beskrevet i a). Sett på (antall siffer 1) nuller. Eksempel: 364 skal avrundes. Siden 3 avrundes til 5 får vi 500 når vi setter på (3-1) nuller. NB: Du skal ikke bruke tekststrenger i løsning av denne oppgaven. int avrund( int verdi) if (verdi <= 0) return 0; else int hjelp = 1; int temp = verdi; while (temp >= 10) hjelp *= 10; temp /= 10; int siffer = enkelavrunding(temp); return siffer * hjelp; c) Lag en funksjon som lager et avrundet område ved å avrunde de to tallene det består av. De to opprinnelige tallene skal være inn-argumenter mens de to avrundede tallene skal være ut-argumenter. I ut-argumentene skal alltid det minste tallet komme først, mens i inn-argumentene er det tilfeldig om det minste kommer først eller sist. Eksempel: Området 676 237 skal avrundes. Da blir resultatet 500 1000. (676 avrundes til 1000 og 237 til 500. 500 plasseres først siden det er minst.) void avrundomrade( int nedre, int ovre, int &avrundetnedre, // Ut int &avrundetovre) // Ut if (nedre > ovre) int temp = nedre; 2
nedre = ovre; ovre = temp; avrundetnedre = avrund(nedre); avrundetovre = avrund(ovre); d) Lag et lite hovedprogram der du tester funksjonen i c). Programmet skal gå i løkke og framskaffe to tall mellom 0 og 1000 ved hjelp av funksjonen rand(), og så skal avrundet område beregnes. Både de to opprinnelige tallene og de avrundede tallene skal skrives ut. Start programmet med å spørre bruker hvor mange ganger han vil kjøre løkka. const int max = 1000; int main() int antall; cout << "Hvor mange ganger vil du prøve?"; cin >> antall; int nedreavrundet; int ovreavrundet; srand(113); // Se leksjon 8 om bruk av srand() og rand() // 113 er vilkårlig valgt. int i; for (i = 0; i < antall; i++) int nedre = rand() % max; int ovre = rand() % max; avrundomrade(nedre, ovre, nedreavrundet, ovreavrundet); cout << "Opprinnelig: " << nedre << " - " << ovre; cout << " Avrundet: " << nedreavrundet << " - " << ovreavrundet << endl; return 0; Oppgave 2 (20%) a) Lag en funksjon som deler opp et område i like store intervaller, og finner grensene mellom de ulike intervallene. Prototypen skal se slik ut: void finngrenser(double nedregrense, double ovregrense, int antallintervaller, double *intervallgrenser); Eksempel: Hvis nedregrense = -100, ovregrense = 500, antallintervaller = 3, får vi intervallgrensene -100, 100, 300, 500. Utregning: intervalllengde = (ovregrense nedregrense) / antallintervaller; nestegrense = forrigegrense + intervalllengde; void finngrenser( double nedregrense, double ovregrense, int antallintervaller, double *intervallgrenser) // Ut double intervalllengde = (ovregrense nedregrense) / antallintervaller; intervallgrenser[0] = nedregrense; for (int i=0; i < antallintervaller; i++) intervallgrenser[i+1] = 3
intervallgrenser[i] + intervalllengde; b) Lag en funksjon som teller opp antall tall i ulike intervaller. Inn-argumenter skal blant annet være en tabell med tallene som skal telles samt en tabell av grenser for de ulike intervallene. Resultatet skal være en tabell med antall tall i de ulike intervallene. Eksempel: Hvis vi har tallene 6, 3, 8, 3, 4, 8, 7, 9 og skal dele i de to intervallene 0-5 og 5-10, får vi 3 tall i første intervall og 5 tall i andre intervall. void beregnfordeling( const double *tallene, int antalltall, const double *grenser, int antallintervaller, int *antalliintervall) // Ut int i; int j; for (j=0; j<antallintervaller; j++) antalliintervall[j] = 0; for (i=0; i<antalltall; i++) j = 0; while (tallene[i] > grenser[j+1]) j++; // Forutsetter at ingen tall er større // enn øvre grense antalliintervall[j]++; Oppgave 3 (40%) Fila "data.txt" inneholder en lang tekst med opptil 1000 forskjellige ord ("ord" er her definert som en samling tegn med en eller flere blanke eller linjeskifttegn bak, og du skal ikke gjøre noe forsøk på å "normalisere" dem ved å ta vekk spesialtegn eller endre på store/små bokstaver). Denne fila skal du lage statistikk over ved å skrive ut: Hvilket ord som forekom flest ganger, og hvor mange ganger det forekom. Hvor mange ord som forekom bare en gang. Hvor mange forskjellige ord som besto av 10 eller flere tegn. Deretter skal du lage en enkel grafisk framstilling av bruksfrekvensen av ulike ord på følgende måte: Del opp området 0 til maks antall ganger et ord er brukt (gjerne avrundet) i 5 like lange intervaller og tell opp hvor mange ord som havner i de ulike bruksintervallene. For hvert intervall skal du skrive ut intervallgrensene og ei linje med stjerner. Hver stjerne representerer ti forskjellige ord, så hvis antall ord i et intervall er for eksempel mellom 20 og 29, skal to stjerner skrives ut. Ved bedømmelse av denne oppgaven blir det lagt vekt på hvordan du deler programmet opp i funksjoner. Du må gjerne bruke funksjoner fra læreboka, løsningsforslagene og/eller de foregående oppgavene (selv om du ikke har fått til å lage dem). Disse trenger du ikke å skrive (men skriv hvor du har funnet funksjonen). 4
Hvis det er opplysninger du føler mangler, kan du gjøre antakelser, men skriv hvilke antakelser som er gjort. #include <iostream> #include <fstream> #include <string> #include "Oppgave1.h" #include "Oppgave2.h" using namespace std; const string filnavn = "data.txt"; const int maksord = 1000; const int antallintervaller = 5; void registerord(string linje, string *ordene, int *frekvensene, int &antallord); int finnstorstefrekvens(const int *frekvensene, int antallord); int finnantallmedfrekvens(int soektfrekvens, const int *frekvensene, int antallord); int finnantallmedbokstaver(int minmantallbokstaver, const string *ordene, int antallord); void omformtildouble(const int *inttallene, double *doubletallene, int antalltall); void skrivtegn(char tegn, int antall); void tegnstolper(const double *grenser, int antallintervaller, const int *bruksfrekvenser); int main() ifstream innfil; innfil.open(filnavn.c_str()); if (!innfil) cout << "Feil ved åpning av fil" << endl; exit(exit_failure); int antallord = 0; string ordene[maksord]; int frekvensene[maksord]; string linje; while (!innfil.eof()) innfil >> linje; registerord(linje, ordene, frekvensene, antallord); innfil.close(); int maks = finnstorstefrekvens(frekvensene, antallord); cout << "Mest brukte ord var " << ordene[maks] << " som ble brukt " << frekvensene[maks] << " ganger" << endl; int antallenkle = finnantallmedfrekvens( 1, frekvensene, antallord); cout << "Antall ord som bare ble brukt en gang: " << antallenkle << endl; int antalllange = finnantallmedbokstaver( 10, ordene, antallord); cout << "Antall ord med 10 eller flere tegn: " << antalllange << endl; double grenser[antallintervaller + 1]; int avrundetstopp = avrund(frekvensene[maks]); // Fra 1b 5
finngrenser(0, avrundetstopp, antallintervaller, grenser); //2a int bruksfrekvenser[antallintervaller]; double doublefrekvensene[maksord]; omformtildouble(frekvensene, doublefrekvensene, antallord); // For å kunne bruke oppgave 2b beregnfordeling(doublefrekvensene, antallord, grenser, antallintervaller, bruksfrekvenser); // Fra oppgave 2b tegnstolper(grenser, antallintervaller, bruksfrekvenser); return 0; void registerord( string ord, string *ordene, int *frekvensene, int &antallord) /ut /ut /ut int i = 0; while (i < antallord && ordene[i]!= ord) i++; if (i < antallord) frekvensene[i]++; else if (antallord < maksord) ordene[i] = ord; frekvensene[i] = 1; antallord++; int finnstorstefrekvens( const int *frekvensene, int antallord) int maks = 0; for (int i=0; i<antallord; i++) if (frekvensene[i] > frekvensene[maks]) maks = i; return maks; int finnantallmedfrekvens( int soektfrekvens, const int *frekvensene, int antallord) int antall = 0; for (int i=0; i<antallord; i++) if (frekvensene[i] == soektfrekvens) antall++; return antall; int finnantallmedbokstaver( int minantallbokstaver, const string *ordene, int antallord) int antall = 0; for (int i=0; i<antallord; i++) if (ordene[i].length() >= minantallbokstaver) antall++; return antall; void omformtildouble( const int *inttallene, 6
double *doubletallene, int antalltall) // Ut int i; for (i = 0; i < antalltall; i++) doubletallene[i] = (double)inttallene[i]; void skrivtegn( char tegn, int antall) for (int i=0; i < antall; i++) cout << tegn; void tegnstolper( const double *grenser, int antallintervaller, const int *bruksfrekvenser) for (int i=0; i < antallintervaller; i++) cout << grenser[i] << " - " << grenser[i+1] << ": "; skrivtegn('*', bruksfrekvenser[i] / 10); cout << endl; /* Kjøreresultat: Mest brukte ord var int som ble brukt 47 ganger Antall ord som bare ble brukt en gang: 63 Antall ord med 10 eller flere tegn: 37 0-10: ********* 10-20: 20-30: 30-40: 40-50: */ 7