Kursusopgave 1
Tegne en UML-beskrivelse af klassen Ansoeger.
|
Ansoeger
|
navn: String
koen: char
foedselsDato: int
matematikKarakter: short
kemiKarakter: short
engelskKarakter: short
|
Ansoeger (navn_: String,
koen_: char,
foedselsDato_: int,
matematikKarakter_: short,
kemiKarakter_: short,
engelskKarakter_: short)
hentNavn(): String
hentKoen(): char
hentFoedselsDato(): int
hentMatematikKarakter(): short
hentKemiKarakter(): short
hentEngelskKarakter(): short
|
Vurdere klassen Ansoeger, herunder
- De valgte datatyper og operationer.
- Diskutere, om du ville have udarbejdet klassen med samme indhold.
- Argumentere for eventuelle ændringer og tilføjelser.
- Skrive den ændrede klasseerklæring som UML-diagram og klasseerklæring.
|
'Typen' (læs klassen) String passer umiddelbart fint til attributten navn
.
Det kan måske være hensigtsmæssigt at dele oplysningen ud på to attributter
fornavn
og efternavn
, begge af klassen String.
Da attributten koen umiddelbart kun kan have to forskellige værdier, kan det måske spare memory at
benytte en binær type. Men vi har ikke lært om typen bool endnu, og samtidig udelukkes muligheden for
at registrere en manglende viden om ansøgerens køn, så det er bruge typen char er ok.
Til foedselsDato
-attributten er brugt typen int, men den er kompiler-/platformsafhængig, så den
kan være 16-bits, hvilket selv som unsigned kun når op til 65.535, og da formen for en fødselsdato en
på otte cifre, duer det ikke. Jeg har dog en mistanke om at dagens tidssvarende oversættere på ditto
platform betragter int som en 32-bits type, hvilket gør at der ikke er noget problem.
De tre karakterattributter matematikKarakter
, kemiKarakter
og engelskKarakter
har
navne der entydigt henviser til et fag, hvilket ikke er særligt fleksibelt. Både at der fast er tre attributter,
og at attributnavnene indeholder specifikke fagnavne. Et array vil være lidt mere fleksibelt, men en
separat klasse med en mange til mange relation vil eliminere ikke-eksisterende karakterer og give
mulighed for at ændre antallet af fag og hvilke fag, der registreres. Kort sagt vil en normalisering være
på sin plads, hvis dette er en designopgave. Hvis der indtastes et nul som første ciffer, vil det af
programmet blive opfattet som en oktal værdi, men da det sandsynligvis kun vil ske ved
karakterværdierne 00 og 03, og disse har samme værdi oktalt og decimalt, vil dette forhold ikke have
nogen betydning for data.
Med hensyn til metoderne, virker det lidt uhensigtmæssigt at konstruktøren skal have en værdi til alle
attributterne, men hvis det er hvad institutionen kræver nu og er sikker på at den vil kræve hele
programmets levetid, er det jo bare dét...
Med hensyn til metoderne hentNavn()
, hentKoen()
og hentFoedselsDato()
er
overvejelserne som for de tilhørende attributter.
Generelt er metoderne ud over koknstruktøren kun til læsning af attibutterne, hvilket ikke giver
mulighed for at redigere attributterne. Det er vel bare et spørgsmål om uddannelse af brugerne...
Eller også skal brugergrænsefladen validere data inden de lagres i objekterne, hvilket er et brud med
idealerne.
Den eneste reelle ændring er derfor - under hensyntagen til at dette er en undervisningsopgave i
programmering - en præcicering af typen for attributten foedselsDato
og metoden
hentFoedselsDato()
. Det er næppe ulejligheden værd at definere alle heltalstyperne som
unsigned, da der er masser af plads.
UML-diagram for den ændrede klasseerklæring:
Ansoeger
|
navn: String
koen: char
foedselsDato: long
matematikKarakter: short
kemiKarakter: short
engelskKarakter: short
|
Ansoeger (navn_: String,
koen_: char,
foedselsDato_: long,
matematikKarakter_: short,
kemiKarakter_: short,
engelskKarakter_: short)
hentNavn(): String
hentKoen(): char
hentFoedselsDato(): long
hentMatematikKarakter(): short
hentKemiKarakter(): short
hentEngelskKarakter(): short
|
Den ændrede klasseerklæring:
class Ansoeger {
private:
String navn;
char koen;
long foedselsDato;
short matematikKarakter;
short kemiKarakter;
short engelskKarakter;
public:
Ansoeger(String navn_,
char koen_,
long foedselsDato_,
short matematikKarakter_,
short kemiKarakter_,
short engelskKarakter_);
String hentNavn();
char hentKoen();
long hentFoedselsDato();
short hentMatematikKarakter();
short hentKemiKarakter();
short hentEngelskKarakter();
};
Ansoeger::Ansoeger(String navn_, char koen_, long foedselsDato_,
short matematikKarakter_, short kemiKarakter_,
short engelskKarakter_) {
navn = navn_;
koen = koen_;
foedselsDato = foedselsDato_;
matematikKarakter = matematikKarakter_;
kemiKarakter = kemiKarakter_;
engelskKarakter = engelskKarakter_;
}
String Ansoeger::hentNavn() {
return navn;
}
char Ansoeger::hentKoen() {
return koen;
}
long Ansoeger::hentFoedselsDato() {
return foedselsDato;
}
short Ansoeger::hentMatematikKarakter() {
return matematikKarakter;
}
short Ansoeger::hentKemiKarakter() {
return kemiKarakter;
}
short Ansoeger::hentEngelskKarakter() {
return engelskKarakter;
}
Overveje, hvilke ændringer det ville medføre i erklæringen af klassen Ansoeger,
hvis det blev et krav, at en ansøgers CPR-nummer også skulle registreres.
|
Attributten foedselsDato
skiftes ud med attributten cprNummer
,
der (også) er af typen long. Der kan så laves en udskriftmetode, der grafisk adskiller fødselsdato
og kontrolcifre, for eksempel med '-'.
Tilsvarende udskiftes metoden hentFoedselsDato()
med hentCprNummer()
, der har den
samme funktionalitet som de andre hentemetoder.
Desuden vil attributten koen
blive overflødig, da køn kan bestemmes ud fra det sidste kontrolciffer.
Udarbejde er program, der kan indlæse oplysninger om en ansøger fra tastaturet, oprette denne
ansøger og udskrive denne ansøgers data efter ovenstående retningslinier.
|
#include <iostream.h>
#include "tstring.h"
#include "Ansoeger.h"
char getSex();
int getBirthdate();
short getGrade(String subject);
int main() {
String name;
unsigned int foedselsAar,
foedselsMaaned,
foedselsDato,
alder;
cout << "Indtast ansøgers navn: ";
cin >> name;
Ansoeger person(name, getSex(), getBirthdate(),
getGrade("matematik"), getGrade("kemi"),
getGrade("engelsk"));
foedselsAar = person.hentFoedselsDato() % 100;
alder = 100 - foedselsAar;
foedselsMaaned = (person.hentFoedselsDato() / 10000) % 100;
foedselsDato = person.hentFoedselsDato() / 1000000;
cout << endl << "Ansøgers navn\t\t: " << person.hentNavn() << endl
<< "Ansøgers køn\t\t: ";
if(person.hentKoen() == 'm')
cout << "Mand" << endl;
else
cout << "Kvinde" << endl;
cout << "Ansøgers alder\t\t: " << alder << endl
<< "Ansøgers fødselsdato\t: " << foedselsDato << "/"
<< foedselsMaaned << "/" << foedselsAar % 100 << endl
<< "Ansøgers gennemsnit\t: " << (person.hentMatematikKarakter() +
person.hentKemiKarakter() + person.hentEngelskKarakter()) / 3
<< endl;
cin >> name; // halt program
return 0;
}
char getSex() {
char sex;
do {
cout << "Indtast ansøgers køn [m/k]: ";
cin >> sex;
if(sex < 97) sex += 32; // convert uppercase to lowercase
} while(sex !='m' && sex !='k');
return sex;
}
int getBirthdate() {
int birthdate;
do {
cout << "Indtast ansøgers fødselsdato [ddmmåååå]: ";
cin >> birthdate;
} while(birthdate < 1000000);
return birthdate;
}
short getGrade(String subject) {
short grade; // repliers grade in subject
do {
cout << "Indtast ansøgers karakter i " << subject << ": ";
cin >> grade;
} while(grade < 0 || grade > 13 || grade == 1 || grade == 2 ||
grade == 4 || grade == 12);
return grade;
}
Begrunde valget af de datatyper, du har brugt i dit program.
|
De frie funktioner getSex()
, getBirthdate()
og getGrade(String subject)
har
typer, der svare til de attributter i klassen Ansoeger, som de skal behandle indirekte. Tilsvarende gælder
for de frie funktioners lokale variable.
main()
har typen int, selv om den kun returnerer værdien nul. Typen er valgt comme-il-faut. De
lokale variable foedselsAar
, foedselsMaaned
, foedselsDato
og alder
er unsigned, da de kun skal behandle positive værdier, og har typen int ud fra de overvejelser
der tidligere er foretaget i klassen Ansoeger
.
Dokumenterer at dit program virker ved at tage skærmdump af programmet.
|
Figur 1. Eksempel på programafvikling
Figur 2. Eksempler på fejlindtastning af en karakter ved for stor og forkert karakter.
Fejlindtastning af køn, og samtidig visning af at versal kan være korrekt.
Jeg har forsøgt at skifte tegnsæt, så de danske tegn bliver korrekte,
men endnu har jeg meget at lære om Win2K...