Skip Navigation LinksNiels > IT > Datamatiker > GP > Besvarelse 1

Grundlæggende Programmering

CV  |  IT  |  AV  |  Motor  |  Maritimt  |  Privat

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.

Programafvikling
Figur 1. Eksempel på programafvikling

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

Om Opdateret 18-03-2019 01:25:21. Se min profil på LinkedIn
SQLAdmin.dk Hentet 09-05-2024 09:37:29.