Skip to content

Commit

Permalink
Initial commit
Browse files Browse the repository at this point in the history
  • Loading branch information
rherbrich74 committed Apr 6, 2024
1 parent f5b3fb9 commit 27e6ae8
Show file tree
Hide file tree
Showing 10 changed files with 553 additions and 0 deletions.
Binary file added unit1/Unit1 - Algorithmen.pptx
Binary file not shown.
11 changes: 11 additions & 0 deletions unit2/Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
TARGETS = types pointers const overloading copymove template mystring virtual
CXX = g++
CPPFLAGS = -std=c++17
LDLIBS=-lm

all: $(TARGETS)

clean:
$(RM) $(TARGETS)

.PHONY: all clean
53 changes: 53 additions & 0 deletions unit2/const.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
#include <iomanip>
#include <iostream>

using namespace std;

// This function double the references given to it
void double_number(int& x) {
x *= 2;
return;
}

// This function checks that the number passed by const-reference is even
bool is_even(const int& x) {
// This is a compile time error as the function tries to change the value that x refers to
// x += 2;
return (x % 2 == 0);
}

// main entry point of the program
int main(void) {
int x{10}, y{42};
const int z{66};

// This is not ok b/c of the const-ness of z
// z = 13;

int* const p{&x};
cout << setw(20) << "*p = " << *p << endl;
*p += 17;
cout << setw(20) << "*p + 17 = " << *p << endl;

// This does not compile b/c the pointer is const
// p = &y;

const int* const p2{&y};
cout << setw(20) << "*p2 = " << *p2 << endl;
// This is no longer possible b/c the pointer p2 is const pointing to a const int!
// *p2 += 17;
// cout << setw(20) << "*p + 17 = " << *p2 << endl;

double_number(*p);
cout << setw(20) << "*p (after double) = " << *p << endl;

// This call is not possible because the function double_number MIGHT change the value (it's constness does not promise not to!)
// double_number(*p2);
// cout << setw(20) << "*p2 (after double) = " << *p2 << endl;

cout << setw(20) << "*p is even = " << is_even(*p) << endl;
// This call IS possible because the function is_even promises in its signature not to change the value it's given!
cout << setw(20) << "*p2 is even = " << is_even(*p2) << endl;

return (0);
}
68 changes: 68 additions & 0 deletions unit2/copymove.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
#include <iomanip>
#include <iostream>

using namespace std;

class MyInt {
int value = 0; // actual integer value
public:
MyInt(int i) : value{i} {
cout << "Ordinary constructor MyInt(int = " << i << ")" << endl;
}
MyInt() {
cout << "Default constructor MyInt()" << endl;
}
MyInt(const MyInt& mi) : value{mi.value} {
cout << "Copy constructor MyInt(MyInt& = " << mi.value << ")" << endl;
}
MyInt(MyInt&& mi) : value{mi.value} {
cout << "Move constructor MyInt(MyInt&& = " << mi.value << ")" << endl;
}
MyInt& operator=(const MyInt& mi) {
cout << "Copy assignment MyInt& operator=(const MyInt& = " << mi.value << ")" << endl;
value = mi.value;
return (*this);
}
MyInt& operator=(MyInt&& mi) {
cout << "Move assignment MyInt& operator=(MyInt&& = " << mi.value << ")" << endl;
value = mi.value;
return (*this);
}
~MyInt() {
cout << "Destructor ~MyInt(= " << value << ")" << endl;
}

int val() { return value; }
};

MyInt f(MyInt& mi) {
cout << "\t\tMyInt tmp { mi.val() + 25 };" << endl;
MyInt tmp{mi.val() + 25};

cout << "\t\treturn (tmp);" << endl;
return (tmp);
}

// main entry point of the program
int main(void) {
cout << "\tMyInt m1;" << endl;
MyInt m1;
cout << "\tMyInt m2 { 10 };" << endl;
MyInt m2{10};
cout << "\tMyInt m3 = 12;" << endl;
MyInt m3 = 12;
cout << "\tMyInt m4 { m3 };" << endl;
MyInt m4{m3};

cout << "\tm1 = m2;" << endl;
m1 = m2;

cout << "\tm3 = f(m1);" << endl;
m3 = f(m1);

cout << "\tMyInt m5{move(f(m3))};" << endl;
MyInt m5{move(f(m3))};

cout << "\treturn (0);" << endl;
return (0);
}
163 changes: 163 additions & 0 deletions unit2/mystring.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,163 @@
#include <iomanip>
#include <iostream>

using namespace std;

// A class that represents strings of fixed length efficiently
class MyString {
char* str; // the pointer to the actual (non-zero-terminated!) string
int len; // the length of the string
public:
// default constructor
MyString() : str(nullptr), len(0) {}

// default constructor for undefined string with fixed length
MyString(const int l) {
if (l < 0) exit(-1);
len = l;
str = new char[len];
}

// constructs a string from a C-style string
MyString(const char* s) {
// counts the length of the C-string (without the terminating '\0')
len = 0;
for (int i = 0; s[i]; i++, len++)
;

// allocate the memory for all the characters
str = new char[len];

// copy all the characters
for (int i = 0; i < len; i++)
str[i] = s[i];
}
// copy constructor
MyString(const MyString& ms) : len(ms.len) {
// allocate the memory for all the characters
str = new char[len];

// copy all the characters
for (int i = 0; i < len; i++)
str[i] = ms.str[i];
}
// move constructor
MyString(MyString&& ms) : len(ms.len), str(ms.str) {
ms.len = 0;
ms.str = nullptr;
}
// destructor
~MyString() {
delete[] str;
}
// copy assignment operator
MyString& operator=(const MyString& ms) {
// free the existing string
delete[] str;

// copy the length of the assigned string
len = ms.len;

// allocate the memory for all the characters
str = new char[len];

// copy all the characters
for (int i = 0; i < len; i++)
str[i] = ms.str[i];
return (*this);
}
// move assignment operator
MyString& operator=(MyString&& ms) {
// free the existing string
delete[] str;

// copy the length of the assigned string
len = ms.len;

// copy the pointer from the moved MyString ...
str = ms.str;

// ... and invalidate the moved data
ms.len = 0;
ms.str = nullptr;
return (*this);
}
// index operator overload
char& operator[](size_t pos) const {
if (pos < 0 || pos > (len - 1))
exit(-1);
return (str[pos]);
}

// returns the length of the string
int length() const { return len; }

// output the string on an output stream
void print() const {
for (int i = 0; i < len; i++)
cout << str[i];
return;
}
};

// implementation of the stream output of MyString
ostream& operator<<(ostream& out, const MyString& ms) {
for (int i = 0; i < ms.length(); i++)
out << ms[i];
return (out);
}

// string concatenation as the addition operation
MyString operator+(const MyString& lhs, const MyString& rhs) {
MyString out(lhs.length() + rhs.length());

// first copy the characters of the left hands side ...
int i = 0;
for (int j = 0; j < lhs.length(); j++, i++)
out[i] = lhs[j];
// ... and then copy the characters of the right hand side
for (int j = 0; j < rhs.length(); j++, i++)
out[i] = rhs[j];

return (out);
}

// Transforms a string to upper case
MyString to_upper(const MyString& ms) {
MyString tmp = ms;

for (int i = 0; i < tmp.length(); i++)
tmp[i] = toupper(tmp[i]);
return (tmp);
}

// main entry point of the program
int main(void) {
MyString s1("Hello world!");
MyString s2(s1);
MyString s3;
MyString s4 = "Hello";
MyString s5 = " World!";
MyString s6;

// change one character in the first string
s1[5] = ',';

// then set the default initialized string to the result of an operation
s3 = to_upper(s2);

// and then concatenate two string
s6 = s4 + s5;

cout << setw(10) << "s1 = ";
s1.print();
cout << endl;

cout << setw(10) << "s2 = " << s2 << endl;
cout << setw(10) << "s3 = " << s3 << endl;
cout << setw(10) << "s4 = " << s4 << endl;
cout << setw(10) << "s5 = " << s5 << endl;
cout << setw(10) << "s6 = " << s6 << endl;

return (0);
}
65 changes: 65 additions & 0 deletions unit2/overloading.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
#include <iomanip>
#include <iostream>

using namespace std;

// A simple struct to demonstrate operator overloading
struct Rational {
int p;
int q;

// Operator overloading for a typecast operator
operator double() const { return ((double)p / (double)q); }
};

// overloading of the addition operator
Rational operator+(Rational const& a, Rational const& b) {
Rational c = {a.p * b.q + b.p * a.q, a.q * b.q};
return (c);
}

// overloading of the multiplication operator
Rational operator*(Rational const& a, Rational const& b) {
Rational c = {a.p * b.q, a.q * b.q};
return (c);
}

// prints a rational number on the output stream
void print_rational(const Rational& r, int width = 10) {
cout << setw(width) << (double)r.p / (double)r.q;
return;
}

// integer version of the function f
int f(int x, int y) {
return (x + y);
}

// double version of the function f
int f(double x, double y) {
return ((int)(x * y));
}

// main entry point of the program
int main(void) {
cout << setw(20) << "f(4,3) = " << f(4, 3) << endl;
cout << setw(20) << "f(4.0,3.0) = " << f(4.0, 3.0) << endl;
cout << setw(20) << "f(5,(int) 6.0) = " << f(5, (int)6.0) << endl;
cout << setw(20) << "f(5.0,(double) 6) = " << f(5.0, (double)6) << endl;

Rational a = {1, 2};
Rational b = {1, 4};
Rational c = a + b;
Rational d = a * b;

cout << setw(20) << "1/2 + 1/4 = " << (double)c.p / (double)c.q << endl;
cout << setw(20) << "1/2 * 1/4 = " << a * b << endl;
cout << setw(20) << "1/2 * 1/4 = ";
print_rational(d);
cout << endl;
cout << setw(20) << "1/2 * 1/4 = ";
print_rational(d, 5);
cout << endl;

return (0);
}
Loading

0 comments on commit 27e6ae8

Please sign in to comment.