Ruprecht Karls Universitńt Heidelberg

CodeSnipplets

From Informatik-Vorkurs
Jump to: navigation, search

Auf dieser Seite sind ein paar Code-Beispiele aus der Vorlesung gesammelt. Die Beispiele machen nichts Sinnvolles, sie sollen nur wichtige Konzepte und die Syntax zeigen.


Zusammengesetzte Typen

#include <iostream>
using namespace std;
  
int main ()
{
  enum language { unknown, german, french };  // einfacher enum	
  language ConfLang;                          // eine Variable vom Typ 'language' 
  ConfLang = german;                          // initialisierung	
  switch (ConfLang) {                         // mache etwas damit...
    case german: cout << "Deutsch\n";  break;
    case french: cout << "Francais\n"; break;
    default:     cout << "???.\n";     break;
  }
  
  enum newtype {ok = 5, bad = 7};             // enum mit fester Initialierung
  newtype test = ok;
  cout << test << "\n";                       // test wird als (int) interpretiert, da
                                              // '<<' (noch) nichts von 'newtype' weiss
  
  struct point3 { float x, y, z; };           // gemischte Struktur
  const int N = 100;
  point3 p;                                   // ein Punkt
  point3 v[N];                                // ein Array von Punkten
  
  p.x = 5.3;                                  // zugriff auf y-Koordinate in p
  for (int i=0; i<N; i++) v[i].x = 0;         // setze alle x-Kooridnaten in v auf 0 
  v[17] = p;                                  // das kopiert den ganzen Vektor!
  
  cout << v[17].x << endl;                    // das ist nun 5.3!
  cout << "Size of float: " << sizeof(float)  << " byte\n";
  cout << "Size of point: " << sizeof(point3) << " byte\n";
  cout << "Size of v    : " << sizeof(v)      << " byte\n";
  
  enum gender {male, female};
  const int NDAY = 365;                       
  struct Mitarbeiter {                        // gemischte Struktur
    char   Name;                              // erst mal nur Buchstabe (sp├Ąter: sting)
    gender g;
    bool   IsOnHoliday[NDAY];
    point3 apoint;                            // nur zur Demo..    
  };
  Mitarbeiter XYZ;
  XYZ.g = female;
  XYZ.IsOnHoliday[0] = false;
  XYZ.Name = 'A';
  XYZ.apoint.x = 4.7;                         // geschachtelter Zugriff
  
  cout << "Hallo " << ((XYZ.g == male) ? "Herr " : "Frau ") << XYZ.Name << "!\n";
 
  cout << "Size of char:        " << sizeof(char)        << " byte\n";
  cout << "Size of bool:        " << sizeof(bool)        << " byte\n";
  cout << "Size of gender:      " << sizeof(gender)      << " byte\n";
  cout << "Size of Mitarbeiter: " << sizeof(Mitarbeiter) << " byte\n";
}

Ausgabe:

Deutsch
5
5.3
Size of float: 4 byte
Size of point: 12 byte
Size of v    : 1200 byte
Hallo Frau A!
Size of char:        1 byte
Size of bool:        1 byte
Size of gender:      4 byte
Size of Mitarbeiter: 388 byte

Funktionen und ├╝berladene Operatoren

#include <iostream>
#include <cmath>
 
struct complex { float re, im; };                  // ein neuer Typ
 
void DruckeComplex(complex k)                      // keine R├╝ckgabe n├Âtig
{
  std::cout << "(" << k.re << "/" << k.im << ")";
}
 
float BetragVonComplex (complex z)                 // mit R├╝ckgabewert
{
  float betrag;
  betrag = std::sqrt(z.re * z.re + z.im * z.im);
  return betrag;
//  return std::sqrt(z.re * z.re + z.im * z.im);   // so geht es kompakter
}
 
//complex SummeComplex(complex a, complex b)       // als Funktion
complex operator+(complex a, complex b)            // als ├╝berladener Operator
{
  complex result;
  result.re = a.re + b.re;
  result.im = a.im + b.im;
  return result;
}
 
complex operator+(complex a, float b)              // complex * float
{                                                  // ist was Anderes!
  complex result;
  result.re = a.re + b;
  result.im = a.im;
  return result;
}
 
complex operator+(float b, complex a)             // und auch das!
{                                                 // ('+' muss ja nicht
  return a + b;                                   // kommutativ sein!)
}
 
int main ()
{
  float x = 4.5;
  complex c; c.re = 1.0; c.im = 1;
  complex d = x + c;
  std::cout << "Der Betrag von ";
  DruckeComplex(d);
  std::cout << " ist " << BetragVonComplex(d) << std::endl;
}

Ausgabe:

Der Betrag von (5.5/1) ist 5.59017

Zeiger und dynamische Variablen

#include <iostream>
using namespace std;
 
struct Pair {int left, right;};             // Eine struct
 
struct TBig {                               // Noch eine struct...
  bool  flag;                               //                         4 Byte
  float zahlen [1000];                      //                      4000 Byte
  Pair  pp;                                 // Ein einzelnes Pair      8 Byte
  Pair  parr[10];                           // Ein Array von Pairs    80 Byte
};
 
int  main () {
  int i = 3;                                // Ein int
  cout << "Adresse von i: " << &i << endl;  // Adresse von i ausgeben
  int * pint;                               // pint ist ein Zeiger auf ein int.
  pint = & i;                               // pint zeigt jetzt auf i (er enth├Ąlt die Adresse von i)
  cout<<"pint: " << pint << endl;           // Wert von pint = Adresse von i!
  cout<<"Wert bei pint: " << * pint << endl;// Wert AUF DEN PINT ZEIGT (= i!)
  * pint = 30;                              // Den Wert, auf den pint zeigt ver├Ąndern
  cout << "i ist jetzt: " << i << endl;     // i hat sich ver├Ąndert!
   
  int * arr;                                // arr ist ein Zeiger auf ein (oder mehrere) integers
  arr = new int[i];                         // Platz f├╝r i (hier 30) integers machen
  i = arr[3];                               // Das geht jetzt!
  delete [] arr;                            // Platz wieder frei geben
   
  TBig * p;                                 // p ist pointer auf ein Big Objekt. Noch undefiniert!
  p = new TBig;                             // Erschaffe ein Objekt und weise den Platz p zu
  (* p).flag = true;                        // *p ist das Objekt
  cout << p->flag << endl;                  // 'Sch├Âner' kann man mit -> zugreifen
  p->pp.left = 13;                          // So greift man auf das Pair pp zu,
  p->zahlen[13] = 3.4;                      // so auf das Array,
  p->parr[2].right = 4;                     // und so auf das Array von Pairs.
  cout << "Gr├Â├če von p: " << sizeof(p) << endl;   //  p ist nur 4 Byte gro├č  
  cout << "Gr├Â├če von *p: " << sizeof(*p) << endl; // *p ist ein Big : 4092 byte
  delete p;                                 // Platz wieder frei geben
   
  return 0;
}

Ausgabe:

Adresse von i: 0xbfff3e50
pint: 0xbfff3e50
Wert bei pint: 3
i ist jetzt: 30
1
Gr├Â├če von p: 4
Gr├Â├če von *p: 4092

Klasse und Vererbung

File torte.h:

class Torte
{
public:
       Torte    (int);     // Argument: Anzahl der Kerzen
  void Show     (void);    // Drucke etwas
  void BlaseAus (int);     // Argument: Anzahl der ausgeblasenen Kerzen 
 
protected:                 // Damit die abgeleiteten Klassen Zugriff haben
  int  nkerze;
  int  nbrennen;
};
 
class WackeligeTorte : public Torte    // WackeligeTorte erbt von Torte
{
public:
  WackeligeTorte(int n) : Torte(n) {}  // Rufe den Konstruktor der Basisklasse
  void BlaseAus (int);                 // Diese Funktion ├╝berschreiben wir!
};

File torte.cc:

#include <iostream>
#include "torte.h"
 
Torte::Torte (int n) {
  nkerze   = n;
  nbrennen = n;   // Zu Beginn brennen alle Kerzen
}
 
void Torte::Show (void) {
  std::cout << "Es brennen " << nbrennen << " Kerzen\n";
}
 
void Torte::BlaseAus (int n) {
  nbrennen -= n;
  if (nbrennen < 0) nbrennen = 0;
}
 
void WackeligeTorte::BlaseAus (int n) {
  if (n > 10) {
    std::cout << "Zu heftig: Alle Kerzen gehen aus!\n";
    nbrennen = 0;
  } else {
    nbrennen -= n;
    if (nbrennen < 0) nbrennen = 0;
  }
}

File geburtstag.cc:

#include "torte.h"
int main (void)
{
  Torte T(20);     // oder:   WackeligeTorte T(20)
  T.Show();
  T.BlaseAus(2);
  T.Show();
  T.BlaseAus(20);
  T.Show();
  return 0;
}

Vererbung und Filestruktur

Hier wird in einem weiteren sehr primitiven Beispiel gezeigt, wie man eine Klasse definiert, die von einer anderen 'erbt'. Hier sieht man auch, wie man mit mehreren Files arbeitet:

Hier das Header File f├╝r einen Typ 'T_Color' im file color.h

#ifndef SOMEUNIQUEIDENTIFIER                // sorgt daf├╝r, dass File nur einmal eingebunden wird
 
enum T_colcode {RED, GREEN, BLUE, UNKNOWN}; // nur f├╝r das Beispiel...
 
class T_color {
public:
  void print    (void);
  void SetToRed (void);                     // nur f├╝r die Demo...
  T_colcode col;                            // besser: private
};
 
#define SOMEUNIQUEIDENTIFIER
#endif

Die Implementierung im File color.cc

#include <iostream> 
 
#include "color.h"
 
void T_color::print (void) {
  switch (col) {
    case RED:   std::cout << "rot"; break;
    case GREEN: std::cout << "gr├╝n"; break;
    case BLUE:  std::cout << "blau"; break;
    default:    std::cout << "???"; break;
  }
}
 
void T_color::SetToRed (void) {
  col = RED;
}

Dann nutzen wir einen zweidimensionalen Punkt aus dem File vect2.h

struct vect2 {
  float x, y;
};
 
vect2 operator+ (const vect2 &, const vect2 &);

mit der Implementierung im File vect2.cc:

#include <iostream>
#include "vect2.h"
 
vect2 operator+ (const vect2 & a, const vect2 & b) {
  vect2 result;
  result.x = a.x + b.x;
  result.y = a.y + b.y;
  return result;
}

Und hier unser Hauptfile shape_test.cc:

#include <iostream>
#include "vect2.h"
#include "color.h"
 
class T_Shape {                                        // Eine allgemeine Form
public:
  void      SetColor (T_colcode c) {color.col = c;};
  T_colcode GetColor (void)      {return color.col;};
 
  vect2     pos;
  T_color   color;
};
 
class T_Circle: public T_Shape {                     // Eine spezielle Form. Sie erbt Variablen
public:                                              //  (pos, color) und Methoden von T_Shape
  float radius;                                      // eine weitere Eigenschaft.
};
 
int main ()
{
  T_Shape a;                                         // allgemeine Shape
  a.color.SetToRed();                                // color ist public, und 'kann' SetToRed()
  a.pos.y = 3.0;                                     // a hat eine pos.
  std::cout << "Shape a hat die Farbe ";
  a.color.print();
  std::cout << std::endl;
 
  T_Circle circ;                                     // Ein T_Circ, ist aber auch ein T_Shape!
  circ.radius = 3.3;                                 // Das hat nur ein T_Circ!
  circ.SetColor(GREEN);
  std::cout << "Der Kreis hat die Farbe ";
  circ.color.print();
  std::cout << std::endl; 
 
  vect2 c = a.pos + circ.pos;
}

Das ganze wird nun ├╝bersetzt und gelinkt mit

g++ -Wall -c color.cc
g++ -Wall -c vect2.cc
g++ -Wall -c shape_test.cc
g++ -o xxx shape_test.o vect2.o color.o

STL Container

#include <iostream>
#include <vector>
#include <list>
#include <set>
using namespace std;       // sonst: std::vector<..> etc. !!!
 
struct SomeType {int aint; bool abool;};
 
int main ()
{
  /**********************************************
   ********            vector            ********
   **********************************************/
  cout << endl << "VECTOR:" << endl;
 
  // es gibt viele Konstruktoren zur Initialisierung:
  vector<int>   v1;          // leerer vector (f├╝r ints)
  vector<int>   v2 (4);      // vector f├╝r int mit 4 Elementen (werden auf 0 gesetzt)
  vector<float> v3 (7,1.23); // float vector, 7 Elemente, init mit 1.23 
 
  cout << "v3[3]:      " << v3[3] << endl;
 
  // Gr├Â├čen ausgeben & ver├Ąndern
  cout << "Groesse v1: " << v1.size() << endl;
  cout << "Groesse v2: " << v2.size() << endl;
  cout << "Groesse v3: " << v3.size() << endl;
  v1.resize(10);
  cout << "Groesse v1: " << v1.size() << " (nach resize)" << endl;
  v1.push_back(7);
  cout << "Groesse v1: " << v1.size() << " (nach pushback)" << endl;
 
  // Dynamisches Anlegen und Zugriff:
  vector<SomeType> * pv;     // Pointer definieren
  pv = new vector<SomeType>(5);
  (*pv)[3].aint = 3;
  for (unsigned int i=0; i<(*pv).size(); i++)
    cout << (*pv)[i].aint << " ";
  cout << endl;
 
  /**********************************************
   ********             list             ********
   **********************************************/
  cout << endl << "LISTE:" << endl;
 
  list<int> l(3,7);    // Liste mit 3 ints
  cout << "Groesse Anfang: " << l.size() << endl;
 
  list<int>::iterator it;
 
  l.push_back(9);  // Hinten einf├╝gen: 7 7 7 9
  l.push_front(5); // Vorne  einf├╝gen: 5 7 7 7 9
 
  it = l.begin();  // it zeigt auf 5
  it++; it++;      // it zeigt auf zweite '7'
 
  l.insert(it,3);  // '3' davor einf├╝gen:  5 7 3 7 7 9
                   // it zeigt immer noch auf die '7'
  l.insert(it,4);  // nochwas einf├╝gen     5 7 3 4 7 7 9
 
  cout << "Groesse nach Einfuegen: " << l.size() << endl;
 
  cout << "Liste:";
  for (it=l.begin(); it!=l.end(); it++)
    cout << " " << *it;
  cout << endl;
 
  /**********************************************
   ********             set              ********
   **********************************************/
  cout << endl << "SET:" << endl;
  
  set<char> s;             // leere Menge von chars
  s.insert('a');           // ein paar chars einf├╝gen
  s.insert('b');
  s.insert('A');
  s.insert('b');
  cout << "Groesse: " << s.size() << endl; // Groesse
  cout << "Menge (Set):";
  for (set<char>::iterator it=s.begin(); it!=s.end(); it++)
    cout << " " << *it;
  cout << endl;
 
  return 0;
}

Ausgabe:

VECTOR:
v3[3]:      1.23
Groesse v1: 0
Groesse v2: 4
Groesse v3: 7
Groesse v1: 10 (nach resize)
Groesse v1: 11 (nach pushback)
0 0 0 3 0 
 
LISTE:
Groesse Anfang: 3
Groesse nach Einfuegen: 7
Liste: 5 7 3 4 7 7 9
 
SET:
Groesse: 3
Menge (Set): A a b
Personal tools