TDT4102: Prosedyre- og objektorientert programmering
Introduksjon
C++ er et programmeringspråk Bjarne Stoustrup lagde med C som basis. C++ gir C objekt-orientert funksjonalitet. Kode skrevet som C er gyldig C++, men kode skrevet som C++ er ikke nødvendigvis gyldig C.
Læringsmål
Fra https://www.ntnu.no/studier/emner/TDT4102/2013
Kunnskap
- Har bred og praktisk orientert kunnskap om programmeringsspråket C++. Kan syntaks og regler for variabeldeklarasjoner og datatyper, typekonvertering, kontrollstrukturer, funksjoner og operatorer, overlagring, klasser, arv, templates, unntakshåndtering.
- Har kunnskap om automatisk og dynamiske variabler og bruk av pekere.
- Har kunnskap om rekursjon, enkle algoritmer og datastrukturer.
- Har kunnskap om prosedural og objektorientert modularisering av koden og har kunnskap om hvordan kode kan organiseres i flere kildekodefiler, kompilering og lenking.
- Har kunnskap om standardbiblioteket, inn/ut datahåndtering, vanlig brukte funksjoner og template-klasser.
- Har kunnskap om moderne utviklingsverktøy, teknikker for feilfinning og enkel testing av egen kode.
- Har kunnskap om diagramtyper for objektorienterte programmer.
Ferdigheter
- Kan utvikle et program fra problembeskrivelse til fungerende og feilfri løsning.
- Kjenner vanlige brukte kodingsteknikker og kan jobbe iterativt og effektivt med konstruksjon av egen kode.
- Kan programmere proseduralt hvor koden er fornuftig modularisert i funksjoner og objektorientert hvor koden er organisert i klasser. Kan velge hvilke hvilken løsning som er best for et gitt problem.
- Kan skrive kode som er gjenbrukbar, lesbar og enkel å vedlikeholde.
- Kan lese kode og forstå hvordan koden oppfører seg i kjøretid.
Generell kompetanse
- Kan jobbe effektivt med å analysere et problem og konstruere en løsning.
- Kan kommunisere og diskutere kodeløsninger og forklare hvordan et program fungerer.
- Kan finne frem til å benytte nødvendige hjelpemidler, kan bruke dokumentasjon for programmeringsspråket og standarbiblioteket.
Grunnleggende
Hello World
include <iostream>
using namespace std;
int main(){
cout << "Hello, World! "<< endl;
return 0;
}
Slik ser "Hello, World!" ut i C++. Linje 1 henter inn iostream, den delen av standardbiblioteket som omhandler i_nput _o_utput _stream. Konsollen som vi skriver ut til i dette programmet er en stream. int main er der programmet starter å kjøre, ingenting annet enn det som står i main (direkte eller indirekte), blir kjørt. main er en funksjon, vi ser at den har en returdatatype, et navn, paranteser og en funksjonskropp, krøllparanteser som omslutter kode. Koden som omsluttes er cout << "Hello, World" << endl; som skal tolkes som at vi stapper "Hello, World! " inn i cout, så endl. cout er console out og representerer utskrift til konsollen. "Hello, World! " er en string og kommer ut på skjerm/konsoll uten hermetegnene. endl representerer slutten på en linje og hopper en linje ned og tilbake til venstre.
I utgangspunktet starter programmet fra main
og går linje for linje nedover til der main
returnerer.
Datatyper
Innebygde datatyper
Type | Størrelse | Beskrivelse |
int | 32 bit | Heltall |
double | 64 bit | Flyttall. Eks.: -2.4, 4.0 |
float | 32 bit | Flyttall |
char | 8 bit | Enkelt bokstav |
bool | true /false |
Objektstrukturer
Enum
En enumerering er en datatype hvor man navngir alle lovlige verdier den kan ha. En lykt kan enten være på eller av.
enum Light {ON,OFF}
Struct
En struct lar oss definere egne datatyper som består av flere andre datatyper. Navnet kommer av structured data. Structer blir vanligvis brukt til å holde informasjon som hører sammen. Eksempelvis har et rektangel to vesentlige biter informasjon, bredde og høyde, og en rectangle-struct ville inneholdt begge.
struct Rectangle{
double width;
double height
};
Class
En klasse lar oss også definere egne datatyper på samme måte som struct, men klasser brukes til å håndtere noe mer kompliserte datatyper. En klasse kan som regel gjøre noe, for eksempel kan vi lage en klasse for andregradspolynomer og gi denne funksjoner for å regne ut røtter.
Headerfil: polynomial.hpp
enum PolynomialClassification{DOUBLE_ROOT,TWO_REAL_ROOTS,CONJUGATE_ROOTS}
struct complexRoots{
double real1;
double imag1;
double real2;
double imag2;
};
class SecondDegreePolynomial{
double a;
double b;
double c;
SecondDegreePolynomial( double a, double b, double c);
PolynomialClassification solutionType();
complexRoot findRoots();
};
Kildekodefil: polynomial.cpp
SecondDegreePolynomial::SecondDegreePolynomial( double a, double b, double c ){
this->a = a;
this->b = b;
this->c = c;
}
PolynomialClassification SecondDegreePolynomial::solutionType(){
if ( b*b-sqrt(4*a*c)> 0){
return TWO_REAL_ROOTS;
}else if (b*b-sqrt(4*a*c)== 0){
return DOUBLE_ROOT;
}else{
return CONJUGATE_ROOTS;
}
}
SecondDegreePolynomial::findRoots(){
ComplexRoots complexRoots;
if ( DOUBLE_ROOT == solutionType()){
complexRoots.real1 = -b/2/a;
complexRoots.real2 = -b/2/a;
complexRoots.imag1 = 0;
complexRoots.imag2 = 0;
}else if ( TWO_REAL_ROOTS == solutionType()){
complexRoots.real1 = -b/2/a + sqrt(b*b-4*a*c)/2/a;
complexRoots.real2 = -b/2/a - sqrt(b*b-4*a*c)/2/a;
complexRoots.imag1 = 0;
complexRoots.imag2 = 0;
}else {
complexRoots.real1 = -b/2/a;
complexRoots.real2 = -b/2/a;
complexRoots.imag1 = sqrt(b*b-4*a*c)/2/a;
complexRoots.imag2 = sqrt(b*b-4*a*c)/2/a;
}
}
Tilfeldige tall
Ettersom datamaskiner er deterministiske, kan de ikke finne på tilfeldige tall. Man må derfor lage ett pseudo-random tall ved hjelp av klokkeslettet. På denne måten får man et tall som er tilfeldig nok til de fleste formål.
Eksempel
Hver gang dette kjøres vil ti ulike tilfeldige tall fra og med 5 til (ikke med) 10 printes.
#include <iostream>
#include <cstdlib>
#include <ctime>
#include <cmath>
int randomNumber( int from, int to) {
return ( rand() % (to-from) ) + from;
}
int main () {
std::srand( (unsigned)time(0) );
for ( int i = 0; i < 10; i++ )
std::cout << randomNumber(5, 10) << std::endl;
}
I første linje i main "seeder" man tallgeneratoren med klokken. Merk at dette må gjøres utenfor selve random-funksjonen. Hadde denne linjen vært inni randomNumber, hadde alle de tilfeldige tallene blitt det samme.
I randomNumber finner rand() et tall mellom 0 og en maksgrense satt av kompilatoren. En modulusoperasjon gjør at tallet reduseres til et tall mellom 0 og