Øving 4 // Øving 5 Del 1 // Øving 5 Del 2
Oppgave1amain.cpp
#include <iostream>

using namespace std;

void strengKopier( const char* fra, char* til ) {
for( int teller = 0; (til[teller] = fra[teller] ) != '\0'; teller++ );
}

int main() {
char test1[20] = "en test";
char test2[20];

strengKopier( test1, test2 );

cout << test2 << endl;

return 0;

}
Kjøring:
en test
Oppgave1bmain.cpp
#include <iostream>
using namespace std;


int strengLengde( const char* tekst ) {
const char* start = tekst;
int lengde = 0;
while( *(start+lengde)!='\0' ) lengde++;
return lengde;
}

int main() {

char test1[30] = "dette er enda en test";
cout << "Lengden er til \"" << test1 << "\" er " << strengLengde( test1 ) << endl;

return 0;
}
Kjøring:
Lengden er til "dette er enda en test" er 21
Oppgave1cmain.cpp

int tabell[antallRekker][antallKolonner]; // lager todimmensjonal tabell med int
int *pekerTabell[antallRekker]; // lager tabell av int-pekere

for( int i = -; i < antallRekker; i++ ) { // går gjennom rekkene
pekerTabell[i] = tabell[i];// setter tabellen med 1 kolonne til pekerTabellen
for( int j = 0; j < antallKolonner; j++ ) { // går gjennom kolonnene
*(pekerTabell[i]+j) = 0; // setter verdien til (i,j) til 0
// pekerTabell[i] er raden, +j gir offsett ut i kolonne-tabellen
}
}
Oppgave1dmain.cpp
#include <iostream>
#include <cstring>

using namespace std;

void sort( char** name, int n ) {

char* temp;
for( int i = 1; i < n; i++ ) {
for( int j = 0; j < n-i; j++ ) {
if (strcmp( name[i], name[j] ) < 0 ) {
temp = name[j];
name[j] = name[i];
name[i] = temp;
}

}
}
}


int main() {

char* suit[4] = { "Hearts", "Diamonds", "Clubs", "Spades" };

cout << "Før:" << endl;
for( int i = 0; i < 4; i++ )
cout << suit[i] << ", ";

cout << endl;

sort( suit, 4 );


cout << "Etter: " << endl;
for( int i = 0; i < 4; i++ )
cout << suit[i] << ", ";

cout << endl;


return 0;

}
Kjøring:
Før:
Hearts, Diamonds, Clubs, Spades,
Etter:
Clubs, Diamonds, Hearts, Spades,
Oppgave2Dette ser du ikke:
    1. Når vi oppretter et objekt av en klasse som arver fra en annen klasse, lager vi et objekt som har egenskapene og metodene fra begge klassene.
    2. En virtuell metode er en metode som overkjører baseklassen sin metode med samme returtype og argumenter. I motsetning til en vanlig metode, som ville kjørt basisklassens metode.
    3. En ekte virtuel metode er ikke implementert i basisklassen. Man kan ikke ha instanser av klassen, bare pekere.
    4. Virtuelle metoder bruker sene bindinger for å finne ut hvilken metode som skal brukes under kjøring. Tidlig binding brukes av vanlige metoder, som settes under kompilering.
    5. Polyformisme er å ha klasser som arver fra andre klasser. Man kan ha polyformisme uten virtuelle metoder, men det blir vanskeligere å kalle de riktige metodene man vil ha.
    6. En abstrakt klasse er en klasse man ikke kan ha objekter av, men man kan arve fra dem.
    1. En pekertabell av Motor_vehicle pekere.
      eller en vector med Motor_vehicle pekere.

      Polyformismen vil virke fordi vi kan ha pekere til Private_car i en peker av typen Motor_vehicle.

    2. En peker til 1 Motor_vehicle eller
      en vector med Motor_vehicle objekter.

      Polyformismen ville ikke ha virket for vi ville ha flere enn 1, og vi kan ikke ha objekter av Private_vehicle i et Motor_vehcile objekt.

  1. En peker blir ikke slettet før man eksplisitt sier det, mens objekter blir slettet når man går ut av scope-et.
Oppgave3Matrise.h
#ifndef GUARD_MATRISE_H
#define GUARD_MATRISE_H

#include <iostream>
#include <stdio.h>
#include <stdlib.h>

#include "OutOfRange.h"
#include "WrongDim.h"

using namespace std;

class Matrise {

friend istream& operator >>( istream& input, Matrise& matObj );
friend ostream& operator <<( ostream& output, const Matrise& matObj );

protected:
void opprettMatrise(); // Opprettelse av pekertabellen
void slettMatrise();// Sletting av pekertabellen

int **m; // Pekertabellen
int rader, kolonner;

public:

// Konstruktør
Matrise( int r, int k );

//Destruktør
~Matrise();

// Kopikonstruktør
Matrise( const Matrise& kopierDenne );

// For brukt på høyresiden
const int& operator() ( int r, int k ) const throw( OutOfRange );

//For bruk på venstresiden
int& operator() ( int r, int k ) throw( OutOfRange );

bool operator ==( const Matrise& annenMatrise ) const;
Matrise operator +( const Matrise& annenMatrise ) const throw( WrongDim );
void operator +=( const Matrise& annenMatrise );
Matrise operator =( const Matrise& rightSide);
Matrise operator *( const Matrise& annenMatrise ) const throw( WrongDim );

// Gir en transponert kopi av matrisen
void transponer();
void lag_identitet();
int sum_diagonal() const;


// Gettere
int getRader() const { return rader; }
int getKolonner() const { return kolonner; }



};

#endif
OutOfRange.h
#ifndef GUARD_OUTOFRANGE
#define GUARD_OUTOFRANGE
#include <string>

using namespace std;

class OutOfRange
{
public:
OutOfRange(string thisMessage, int thisi, int thisj) : message( thisMessage ), i( thisi), j( thisj ) { }
string getMessage() const { return message; }
int geti() const { return i; }
int getj() const { return j; }
private:
string message;
int i,j;
};

#endif
WrongDim.h
#ifndef GUARD_WRONGDIM
#define GUARD_WRONGDIM
#include <string>

using namespace std;

class WrongDim
{
public:
WrongDim(string thisMessage, int thisDimx1, int thisDimy1,
int thisDimx2, int thisDimy2)
: message( thisMessage ),dimx1( thisDimx1 ), dimy1( thisDimy1 ),
dimx2( thisDimx2 ), dimy2( thisDimy2 ) { }
string getMessage() const { return message; }
int getDimx1() const { return dimx1; }
int getDimy1() const { return dimy1; }
int getDimx2() const { return dimx2; }
int getDimy2() const { return dimy2; }
private:
string message;
int dimy1,dimx1,dimy2,dimx2;
};

#endif
Matrise.cpp
#include "Matrise.h"

Matrise::Matrise( int antrader=0, int antkolonner=0 ) : kolonner( antkolonner ), rader( antrader ) {

opprettMatrise();
}

Matrise::~Matrise() {

slettMatrise();
}

void Matrise::slettMatrise() {


for( int i = 0; i < rader; ++i )
delete [] m[i];
if( kolonner > 0 )
delete [] m;
}

const int& Matrise::operator()( int r, int k ) const throw( OutOfRange) {
r--;
k--;

if( r < rader && r >= 0 && k < kolonner && k >= 0 )
return m[r][k];
else
throw OutOfRange( "Ikke lovlig indeks", r, k );

}

int& Matrise::operator()( int r, int k ) throw( OutOfRange ) {
r--;
k--;

if( r < rader && r >= 0 && k < kolonner && k >= 0 )
return m[r][k];
else
throw OutOfRange( "Ikke lovlig indeks", r, k );

}

void Matrise::opprettMatrise() {

// Opprette pekere
m = new int*[ rader ];
for( int i = 0; i < rader; i++ )
m[i] = new int[ kolonner ];

// Initialisere
for( int i = 1; i <= rader; i++ ) {
for( int u = 1; u <= kolonner; u++ ) {
(*this)(i,u) = 0;
}
}
}


Matrise Matrise::operator =(const Matrise& rightSide) {

if (this!= &rightSide) //ulike objekter
{

slettMatrise();

rader = rightSide.rader;
kolonner = rightSide.kolonner;
opprettMatrise();

for( int i = 1; i <= rader; ++i ) {
for( int u = 1; u <= kolonner; u++ ) {
(*this)(i, u ) = rightSide(i, u );
}
}
}



return *this;

}

Matrise::Matrise( const Matrise& kopierDenne ) {
rader = kopierDenne.rader;
kolonner = kopierDenne.kolonner;
opprettMatrise();

for( int i = 1; i <= rader; ++i ) {
for( int u = 1; u <= kolonner; u++ ) {
(*this)(i, u ) = kopierDenne(i, u );
}
}
}

istream& operator >>( istream& ainput, Matrise& matObj ) {
cout << "Matrisen er " << matObj.rader << "x" << matObj.kolonner << endl;

int verdi = 0;

for( int i = 1 ; i <= matObj.rader; i++ ) {
for( int u = 1; u <= matObj.kolonner; u++ ) {
cout << "Skriv inn verdi for element " << i << "x" << u << ": ";
ainput >> verdi;
if( verdi < 0 ) {
cout << "Ugyldig!" << endl;
u--;
continue;
}
matObj(i, u ) = verdi;

}
}

return ainput;

}


ostream& operator <<( ostream& output, const Matrise& matObj ) {
output << "Matrisen er " << matObj.rader << "x" << matObj.kolonner << endl;

int verdi = 0;

for( int i = 1 ; i <= matObj.rader; i++ ) {
for( int u = 1; u <= matObj.kolonner; u++ ) {
output << i << "x" << u << ": " << matObj( i, u ) << endl;
}
}

return output;
}

bool Matrise::operator ==( const Matrise& annenMatrise ) const {

for( int i = 1; i <= rader; ++i ) {
for( int u = 1; u <= kolonner; u++ ) {
if( (*this)(i, u ) != annenMatrise(i, u ) )
return false;
}
}
return true;
}

Matrise Matrise::operator +( const Matrise& annenMatrise ) const throw( WrongDim ) {
if( rader != annenMatrise.rader || kolonner != annenMatrise.kolonner ) {
throw WrongDim( "Kan ikke legge sammen disse to matrisene.", rader, kolonner, annenMatrise.rader, annenMatrise.kolonner );
}


Matrise sum( rader, kolonner );

for( int i = 1; i <= rader; ++i ) {
for( int u = 1; u <= kolonner; u++ ) {
sum( i, u ) = (*this)(i, u ) + annenMatrise(i, u );
}
}
return sum;

}

void Matrise::operator +=( const Matrise& annenMatrise) {
(*this) = (*this) + annenMatrise;
}


Matrise Matrise::operator *( const Matrise& annenMatrise ) const throw( WrongDim ) {

if( kolonner != annenMatrise.rader ) {
throw WrongDim( "Kan ikke gange matriser", rader, kolonner, annenMatrise.rader, annenMatrise.kolonner );
}

Matrise tmp( rader, annenMatrise.kolonner );

for(int i = 1; i <= rader; i++) {
for(int j = 1; j <= annenMatrise.kolonner; j++) {
int tmpV = 0;
for(int k = 1; k <= annenMatrise.kolonner; k++) {
tmpV += (*this)(i, k) * annenMatrise(k, j);
}
tmp(i , j) = tmpV;
}
}

return tmp;
}

void Matrise::transponer() {

Matrise tmp(kolonner, rader); // omvendt

for( int i = 1; i <= rader; ++i ) {
for( int u = 1; u <= kolonner; ++u ) {
tmp(u,i) = (*this)(i,u);
// DBUG
// cout << "tmp( " << u << "," << i << " ) = " << tmp(u,i) << " ... this( " << i << "," << u << " ) = " << (*this)(i,u) << endl;
}
}

(*this) = tmp;
}


void Matrise::lag_identitet() {

for( int i = 1; i <= rader; ++i ) {
for( int u = 1; u <= kolonner; ++u ) {
if( i == u )
(*this)(i,u) = 1;
else
(*this)(i,u) = 0;
}
}
}

int Matrise::sum_diagonal() const {

int sum = 0;

for( int i = 1; i <= rader; ++i ) {
for( int u = 1; u <= kolonner; ++u ) {
if( i == u )
sum += (*this)(i,u);
}
}

return sum;
}
Oppgave4apfarray.h
//This is the header file pfarray.h. This is the interface for the class
//PFArray. Objects of this type are partially filled arrays with base type T.
#ifndef PFARRAY_H
#define PFARRAY_H

namespace PFArraySavitch
{
template<class T>
class PFArray
{
public:
PFArray( ); //Initializes with a capacity of 50.

PFArray(int capacityValue);

PFArray(const PFArray<T>& pfaObject);

void addElement(T element);
//Precondition: The array is not full.
//Postcondition: The element has been added.

bool full( ) const; //Returns true if the array is full, false otherwise.

int getCapacity( ) const;

int getNumberUsed( ) const;

void emptyArray( );
//Resets the number used to zero, effectively emptying the array.

T& operator[](int index);
//Read and change access to elements 0 through numberUsed - 1.

PFArray<T>& operator =(const PFArray<T>& rightSide);

virtual ~PFArray( );
private:
T *a; //for an array of T.
int capacity; //for the size of the array.
int used; //for the number of array positions currently in use.
void expand();
};
}// PFArraySavitch
#endif //PFARRAY_H
16-07.cpp
//Program to demonstrate the template class PFArray.
#include <iostream>
#include <string>
using std::cin;
using std::cout;
using std::endl;
using std::string;

#include "pfarray.h"
#include "pfarray.cpp"
using PFArraySavitch::PFArray;

int main( )
{
PFArray<int> a(5);

cout << "Enter up to 10 nonnegative integers.\n";
cout << "Place a negative number at the end.\n";
int next;
cin >> next;
while ((next >= 0) && (!a.full( )))
{
a.addElement(next);
cin >> next;
}
if (next >= 0)
{
cout << "Could not read all numbers.\n";
//Clear the unread input:
while (next >= 0)
cin >> next;
}

cout << "You entered the following:\n";
int index;
int count = a.getNumberUsed( );
for (index = 0; index < count; index++)
cout << a[index] << " ";
cout << endl;

PFArray<string> b(3);

cout << "Enter three words:\n";
string nextWord;
for (index = 0; index < 3; index++)
{
cin >> nextWord;
b.addElement(nextWord);
}

cout << "You wrote the following:\n";
count = b.getNumberUsed( );
for (index = 0; index < count; index++)
cout << b[index] << " ";
cout << endl;
cout << "I hope you really mean it.\n";

return 0;
}
pfarray.cpp
//This is the implementation file: pfarray.cpp.
//This is the implementation of the template class PFArray.
//The interface for the template class PFArray is in the file pfarray.h.

#include "pfarray.h"
#include <iostream>
#include <stdlib.h>

using std::cout;
using std::endl;

namespace PFArraySavitch
{
template<class T>
PFArray<T>::PFArray( ) :capacity(50), used(0)
{
a = new T[capacity];
}

template<class T>
PFArray<T>::PFArray(int size) :capacity(size), used(0)
{
a = new T[capacity];
}

template<class T>
PFArray<T>::PFArray(const PFArray<T>& pfaObject)
:capacity(pfaObject.getCapacity( )), used(pfaObject.getNumberUsed( ))
{
a = new T[capacity];
for (int i =0; i < used; i++)
a[i] = pfaObject.a[i];
}

template<class T>
void PFArray<T>::addElement(T element)
{
if (used >= capacity)
{
expand();
}
a[used] = element;
used++;
}

template<class T>
bool PFArray<T>::full( ) const
{
return false;
}

template<class T>
int PFArray<T>::getCapacity( ) const
{
return capacity;
}

template<class T>
int PFArray<T>::getNumberUsed( ) const
{
return used;
}

template<class T>
void PFArray<T>::emptyArray( )
{
used = 0;
}

template<class T>
T& PFArray<T>::operator[](int index)
{
if (index >= used)
{
cout << "Illegal index in PFArray.\n";
exit(0);
}

return a[index];
}

template<class T>
PFArray<T>& PFArray<T>::operator =(const PFArray<T>& rightSide)
{
if (this != &rightSide) {
if (capacity != rightSide.capacity)
{
delete [] a;
a = new T[rightSide.capacity];
}

capacity = rightSide.capacity;
used = rightSide.used;
for (int i = 0; i < used; i++)
a[i] = rightSide.a[i];
}
return *this;
}

template<class T>
PFArray<T>::~PFArray( )
{
delete [] a;
}


template<class T>
void PFArray<T>::expand() {

capacity += 10;

T* tmp = new T[capacity];

for( int i = 0; i < used; i++ )
tmp[i] = a[i];

delete [] a;
a = new T[capacity];


for( int i = 0; i < used; i++ )
a[i] = tmp[i];

delete [] tmp;
}
}// PFArraySavitch
Kjøring:
Enter up to 10 nonnegative integers.
Place a negative number at the end.
1 2 3 4 5 6 7 8 9 10 11 -1
You entered the following:
1 2 3 4 5 6 7 8 9 10 11
Enter three words:
asd dsa sad
You wrote the following:
asd dsa sad
I hope you really mean it.
Oppgave4bSet.h
#ifndef GUARD_SET
#define GUARD_SET

#include <vector>

using namespace std;

template<class T>
class Set {

public:
Set() { }

// Add new item to the set
void add( T newItem ) {
data.push_back( newItem );
}



// Return size of set
int getSize() {
return data.size();
}



// Return dynamic array of set data
T* getArray() {

T* returnData = new T[ getSize() ];

for( int i = 0; i < getSize(); i++ )
returnData[i] = data[i];

return returnData;

}

private:
vector<T> data;

};

#endif
main.cpp
#include <iostream>
#include <string>

#include "Set.h"

using namespace std;

int main( int argc, char** argv ) {

Set<string> strSet;

strSet.add( "test1" );
strSet.add( "test2" );
strSet.add( "test3" );

string* strSetCpy = strSet.getArray();

for( int i = 0; i < strSet.getSize(); i++ )
cout << "strSetCpy #" << i << ": " << strSetCpy[i] << endl;

delete [] strSetCpy;



Set<int> intSet;
intSet.add( 1 );
intSet.add( 2 );
intSet.add( 3 );

int* intSetCpy = intSet.getArray();

for( int i = 0; i < intSet.getSize(); i++ )
cout << "intSetCpy #" << i << ": " << intSetCpy[i] << endl;

delete [] intSetCpy;



return 0;

}
Kjøring:
strSetCpy #0: test1
strSetCpy #1: test2
strSetCpy #2: test3
intSetCpy #0: 1
intSetCpy #1: 2
intSetCpy #2: 3
Oppgave5GradeProgram.h
#ifndef GUARD_GRADEPROGRAM
#define GUARD_GRADEPROGRAM

#include <vector>
#include <iostream>
#include <map>

using namespace std;

class GradeProgram {

friend istream& operator >>( istream& input, GradeProgram& GP );
friend ostream& operator <<( ostream& output, const GradeProgram& GP );

public:
GradeProgram() { }

private:
vector<int> grades;
map<int,int> histogram;



};

#endif
GradeProgram.cpp
#include "GradeProgram.h"

istream& operator >>( istream& input, GradeProgram& GP ) {
int tall;
cout << "Skriv inn karakterer adskilt med mellomrom, avslutt med -1." << endl;
while( input >> tall && tall != -1 ) {
GP.grades.push_back( tall );

//if( histogram.find( tall ) == histogram.end() )
GP.histogram[tall]++;
}

return input;
}


ostream& operator <<( ostream& output, const GradeProgram& GP ) {
map<int,int>::const_iterator it;

for (it=GP.histogram.begin(); it != GP.histogram.end(); ++it)
output << it->second << " of grade " << it->first << endl;

return output;
}


main.cpp
#include <iostream>
#include <string>

#include "GradeProgram.h"

using namespace std;

int main( int argc, char** argv ) {

GradeProgram gp;

cin >> gp;

cout << gp;



return 0;

}
Kjøring:
Skriv inn karakterer adskilt med mellomrom, avslutt med -1.
1 2 3 1 2 1 1 1 -2 -1
1 of grade -2
5 of grade 1
2 of grade 2
1 of grade 3