Informatik I - Übung 9

Pascal Schärli

pascscha@student.ethz.ch

03.05.2019

Was gibts heute?

  • Best-Of Vorlesung
    • Structs
    • Function overloading
    • Operator overloading
  • Vorbesprechung

Pascal Schärli 03.05.2019

Vorlesung

Pascal Schärli 03.05.2019

Structs

struct strange_t {
    int n;
    bool b;
    std::vector<int> a;
};
  • Structs erlauben uns eigene "Datentypen" zu erstellen.
  • Sie sind eine Kollektion von Variablen.
  • Nach der Deklaration braucht es ein Semicolon;
  • Es ist Konvention, dass Namen von Structs klein geschrieben sind und mit "_t" enden.

Pascal Schärli 03.05.2019

Structs

struct strange_t {
    int n;
    bool b;
    std::vector<int> a;
};


int main () {
    strange_t x = {1, false, {0,1,2}};

    std::cout << x.n    << std::endl; // Output: 1
    std::cout << x.b    << std::endl; // Output: 0
    std::cout << x.a[2] << std::endl; // Output: 2

    return 0;
}
  • Einen Struct kann man initialisieren in dem man alle Initialisierungswerte in geschwungenen {} klammern schreibt.
  • Diese Werte werden dann in der entsprechenden Reihenfolge in die Variablen geschrieben
  • Elemente können ausgelesen Werden mit "."

Pascal Schärli 03.05.2019

Structs

#include <iostream>
#include <vector>

struct strange_t {
    int n;
    bool b;
    std::vector<int> a;
};

strange_t increase(strange_t x){
    strange_t out = x;
    out.n += 1;
    out.b = true;
    for(unsigned int i = 0; i < out.a.size(); i++){
        out.a[i] *= 1;
    }
    return out;
}

int main () {
    strange_t x = {1, false, {0,1,2}};

    x = increase(x);

    std::cout << x.n << " " << x.b << " "
              << x.a[0] << " " << x.a[1] << " " << x.a[1];

    return 0;
}

Was ist der Output von diesem Programm?

2 1 0 1 1

Pascal Schärli 03.05.2019

In dieser Aufgabe Schauen wir uns dieser 3-D Vektor an. Skizziert folgende Funktionen:

  1. Eine Funktion, welche zwei Vektoren addieren kann
  2. Einen Struct "line_t", welcher eine Linie definiert
  3. Eine Funktion welche eine Linie um einen Bestimmten Vektor verschieben kann.
struct vec_t {
    double x;
    double y;
    double z;
};

struct line_t {
    // TODO
};

// POST: returns the sum of two vectors
vec_t add(const vec_t& lhs, const vec_t& rhs) {
  
}

// POST: shifts a line by a vector
line_t shift_line(const line_t& line, const vec_t& amount){
    // TODO
}

Pascal Schärli 03.05.2019

#include <iostream>

struct vec_t {
  double x;
  double y;
  double z;
};

struct line_t {
  vec_t start;
  vec_t end; // INV: start != end
};


// POST: returns the sum of two vectors
vec_t add(const vec_t& lhs, const vec_t& rhs) {
  vec_t out;
  out.x = lhs.x + rhs.x;
  out.y = lhs.y + rhs.y;
  out.z = lhs.z + rhs.z;
  return out;
}


// POST: returns a new line obtained by shifting l by v.
line_t shift_line (const line_t& line, const vec_t& amount) {
  line_t out;
  out.start = add(line.start, amount);
  out.end = add(line.end, amount);
  return out;
}
int main () {
  vec a = {0.0, 0.0, 0.0};
  vec b = {1.0, 1.0, 1.0};
  line l = {a, b};
  vec c = {2.0, -1.0, 3.0};
  line new_l = shift_line(l, c);
  std::cout << "shifted line: ";
  std::cout << "(x:" << new_l.start.x;
  std::cout << ", y:" << new_l.start.y;
  std::cout << ", z:" << new_l.start.z << ") ";
  std::cout << "(x:" << new_l.end.x;
  std::cout << ", y:" << new_l.end.y;
  std::cout << ", z:" << new_l.end.z << ")" << std::endl;
}

Pascal Schärli 03.05.2019

Function Overloading

In C++ ist es möglich, dass mehrere Funktionen den gleichen Namen haben, solange sie unterschiedliche Übergabewerte haben.

int foo1(int a){ ... }
int foo1(int a, int b){ ... }
int foo2(int a){ ... }
int foo2(float a){ ... }
int foo3(int a){ ... }
int foo3(int b){ ... }
int foo4(int a){ ... }
float foo4(int a){ ... }

Pascal Schärli 03.05.2019

Function Overloading

#include <iostream>

void out (const int i) {
    std::cout << i << " (int)\n";
}

void out (const double i) {
    std::cout << i << " (double)\n";
}

int main () {
    out(3.5);
    out(2);
    out(2.0);
    out(0);
    out(0.0);
    return 0;
}
3.5 (double)
2 (int)
2 (double)
0 (int)
0 (double)

Pascal Schärli 03.05.2019

Operator Overloading

Genau wie Funktionen können auch Operatoren wie +-*/ überschrieben werden.

struct vec_t {
    double x;
    double y;
    double z;
};

vec_t add(const vec_t& lhs, const vec_t& rhs) {
  vec_t out;
  out.x = lhs.x + rhs.x;
  out.y = lhs.y + rhs.y;
  out.z = lhs.z + rhs.z;
  return out;
}
struct vec_t {
    double x;
    double y;
    double z;
};

vec_t operator+(const vec_t& lhs, const vec_t& rhs){
  vec_t out;
  out.x = lhs.x + rhs.x;
  out.y = lhs.y + rhs.y;
  out.z = lhs.z + rhs.z;
  return out;
}

Pascal Schärli 03.05.2019

Operator Overloading

#include <iostream>

struct vec_t {
  double x;
  double y;
  double z;
};

// POST: returns the sum of two vectors
vec_t operator+(const vec_t& lhs, const vec_t& rhs) {
  vec_t out;
  out.x = lhs.x + rhs.x;
  out.y = lhs.y + rhs.y;
  out.z = lhs.z + rhs.z;
  return out;
}

std::ostream& operator<< (std::ostream &out, vec_t vec) {
    out << "(" << vec.x << ", " << vec.y << ", " << vec.z << ")";
    return out;
}

int main () {
  vec_t a = {1, 2, 1};
  vec_t b = {3, 3, 2};

  std::cout << a + b << std::endl;
}

Pascal Schärli 03.05.2019

Tribool

AND false
unknown true
false false false false
unknown false unknown unknown
true false unknown true
OR false unknown true
false false unknown true
unknown unknown unknown true
true true true true

Pascal Schärli 03.05.2019

Tribool

int main(){
    tribool_t t1, t2;

    std::cout << "Please enter your first tribool: ";
    std::cin >> t1;

    std::cout << "Please enter your second tribool: ";
    std::cin >> t2;

    std::cout << t1 << " or " << t2 << " = " << (t1 || t2) << std::endl;
    std::cout << t1 << " and " << t2 << " = " << (t1 && t2) << std::endl;
}

Wir möchten einen "tribool" Struct erstellen.

Operator overloading soll uns helfen, dass dieser Wie normale Datentypen benutzt werden kann.

Pascal Schärli 03.05.2019

Tribool

struct tribool_t{
    int value;
};

tribool_t tribool_false() {
    tribool_t out = {0};
    return out;
}

tribool_t tribool_unknown() {
    tribool_t out = {1};
    return out;
}

tribool_t tribool_true() {
    tribool_t out = {2};
    return out;
}

Pascal Schärli 03.05.2019

#include <iostream>

struct tribool_t{
    int value;
};

tribool_t tribool_false() {
    tribool_t out = {0};
    return out;
}

tribool_t tribool_unknown() {
    tribool_t out = {1};
    return out;
}

tribool_t tribool_true() {
    tribool_t out = {2};
    return out;
}

bool operator== (const tribool_t &lhs, const tribool_t &rhs) {
  // TODO
}

tribool_t operator&& (const tribool_t &lhs, const tribool_t &rhs) {
  // TODO
}

tribool_t operator|| (const tribool_t &lhs, const tribool_t &rhs) {
  // TODO
}

std::istream& operator>> (std::istream& in, tribool_t& t){
  // TODO
}

std::ostream& operator<< (std::ostream &out, const tribool_t& t) {
  // TODO
}

int main(){
    tribool_t t1, t2;

    std::cout << "Please enter your first tribool: ";
    std::cin >> t1;

    std::cout << "Please enter your second tribool: ";
    std::cin >> t2;

    std::cout << t1 << " or " << t2 << " = " << (t1 || t2) << std::endl;
    std::cout << t1 << " and " << t2 << " = " << (t1 && t2) << std::endl;
}

Pascal Schärli 03.05.2019

Tribool

bool operator== (const tribool_t &lhs, const tribool_t &rhs) {

}
bool operator== (const tribool_t &lhs, const tribool_t &rhs) {
  return lhs.value == rhs.value;
}

Pascal Schärli 03.05.2019

Tribool

tribool_t operator&& (const tribool_t &lhs, const tribool_t &rhs) {









}
tribool_t operator&& (const tribool_t &lhs, const tribool_t &rhs) {
  if(lhs == tribool_false() || rhs == tribool_false()){
    return tribool_false();
  }
  else if(lhs == tribool_unknown() || rhs == tribool_unknown()){
    return tribool_unknown();
  }
  else{
    return tribool_true();
  }
}

Pascal Schärli 03.05.2019

Tribool

tribool_t operator|| (const tribool_t &lhs, const tribool_t &rhs) {









}
tribool_t operator|| (const tribool_t &lhs, const tribool_t &rhs) {
  if(lhs == tribool_true() || rhs == tribool_true()){
    return tribool_true();
  }
  else if(lhs == tribool_unknown() || rhs == tribool_unknown()){
    return tribool_unknown();
  }
  else{
    return tribool_false();
  }
}

Pascal Schärli 03.05.2019

Tribool

std::istream& operator>> (std::istream& in, tribool_t& t){












}
std::istream& operator>> (std::istream& in, tribool_t& t){
  std::string value;
  in >> value;
  if(value == "false"){
    t = tribool_false();
  }
  else if(value == "true"){
    t = tribool_true();
  }
  else if(value == "unknown"){
    t = tribool_unknown();
  }
  return in;
}

Pascal Schärli 03.05.2019

Tribool

std::ostream& operator<< (std::ostream &out, const tribool_t& t) {











}
std::ostream& operator<< (std::ostream &out, const tribool_t& t) {
  if (t == tribool_false()) {
    out << "false";
  } else if (t == tribool_unknown()) {
    out << "unknown";
  } else if(t == tribool_true()){
    out << "true";
  }
  else{
    out << "INVALID";
  }
  return out;
}

Pascal Schärli 03.05.2019

Vorbesprechung

Pascal Schärli 03.05.2019

Erstellt einen Struct, für eine Zahl, welche nur  Werte von 0-6 annehmen kann.

 

  1. finite_ring.h Invariante bestimmen (Was muss geten, damit der Struct korrekt ist)
  2. finite_ring.cpp Implementiert die Addition, Subtraktion und Multiplikation

Tipp: Modulo 7

+ | 0 1 2 3 4 5 6
--+--------------
0 | 0 1 2 3 4 5 6
1 | 1 2 3 4 5 6 0
2 | 2 3 4 5 6 0 1
3 | 3 4 5 6 0 1 2
4 | 4 5 6 0 1 2 3
5 | 5 6 0 1 2 3 4
6 | 6 0 1 2 3 4 5
* | 0 1 2 3 4 5 6
--+--------------
0 | 0 0 0 0 0 0 0
1 | 0 1 2 3 4 5 6
2 | 0 2 4 6 1 3 5
3 | 0 3 6 2 5 1 4
4 | 0 4 1 5 2 6 3
5 | 0 5 3 1 6 4 2
6 | 0 6 5 4 3 2 1

Pascal Schärli 03.05.2019

Erstellt einen Struct, welcher Komplexe Zahlen darstellen kann.

  1. complex.h Deklariert euren Struct und die Funktionen. (Wie in der Finite Rings Aufgabe schon gemacht wurde)
  2. complex.cpp Implementiert Input-/Output Funktionen
  3. complex.cpp Implementiert alle anderen Operatoren

Tipp:

std::istream& operator>>(std::istream& in, Complex& a)
std::ostream& operator<<(std::ostream& out, const Complex a)

Pascal Schärli 03.05.2019

Erstellt ein Programm, welche Komplexe Rechnungen lösen kann:

  1. Kopiert eure Lösung von 2a
  2. Kopiert den Inhalt von calculator_double.txt in main.cpp
  3. Importiert euer "complex.h" File
  4. Ersetzt double mit eurem Struct

Pascal Schärli 03.05.2019

Program of the Week

Pascal Schärli 03.05.2019

Viel Spass!

Pascal Schärli 03.05.2019