// Lösungen zu "Richard Kaiser: C++ mit dem Borland C++Builder 2007", ISBN: 978-3-540-69575-2
// Copyright Richard Kaiser, 2007. http://www.rkaiser.de. All rights reserved.
// Diese Quelltexte dürfen in eigenen Programmen verwendet werden, wenn sie einen Hinweis auf die Quelle (die ersten beiden Zeilen) enthalten. In keinem Fall wird eine Haftung für direkte, indirekte, zufällige oder Folgeschäden übernommen, die sich aus der Nutzung ergeben.
// It is permitted to use this source text in programs of your own, provided that it contains a reference to the source (the first two lines above). All liabilities for use of the code are disclaimed.

//---------------------------------------------------------------------------
#include <vcl.h>
#pragma hdrstop

#include "FuncObjU.h"
//---------------------------------------------------------------------------
#pragma package(smart_init)
#pragma resource "*.dfm"
TForm1 *Form1;
//---------------------------------------------------------------------------
__fastcall TForm1::TForm1(TComponent* Owner)
        : TForm(Owner)
{
}

#include <algorithm>
#include <functional>
#include <string>
using std::string;
#include <vector>
using std::vector;


// --------------- Aufgaben 9.3 ----------------------------

// --------------- Aufgabe 1 -------------------------------

// a)
bool AnsiCompStr(const string& s1,const string& s2)
{ // lstrcmp verwendet den Windows-Zeichensatz
return lstrcmp(s1.c_str(),s2.c_str())<0;
// mit <=0 wäre das keine strict weak ordering
}

void Aufg1()
{
// b)
const int n=20; // Anzahl der strings in a
char* a[]={".","-","a","b","c","o","u","s","t","ä",
           "ü","Ä","Ö","Ü","ß","A","O","U","S","T"};
vector<string> v1(a,a+n);
std::sort(v1.begin(), v1.end(),AnsiCompStr);
// c)
vector<string> v2(v1.begin(),v1.end());
std::sort(v2.begin(), v2.end());

for (int i=0; i<v1.size(); i++)
  {
    Form1->Memo1->Lines->Add(AnsiString(v1[i].c_str())+" - "+v2[i].c_str());
  }
}

void __fastcall TForm1::Button_3_1Click(TObject *Sender)
{
Aufg1();
}


// --------------- Aufgabe 2 -------------------------------

// Diese Aufgabe kann auf viele verschiedene Arten gelöst werden: 

template<typename T, typename Iterator>
bool is_sorted_1(Iterator first, Iterator last)
{
// Diese Version von is_sorted kann sowohl mit STL-Containern als
// auch mit Arrays verwendet werden. Sie hat aber den kleinen
// Nachteil, dass man den Datentyp immer explizit angeben muss.

// Der Typ-Parameter für den Datentyp T muss der erste Template-
// Parameter sein, damit der Datentyp des Iterators aus dem
// Argument abgeleitet werden kann.

return std::adjacent_find(first,last,std::greater<T>())==last;
}

void test_is_sorted_1()
{
const int Max=5;
int a1[Max]={2,1,2,5,7};
// Aufruf von is_sorted mit Array:
bool b1=is_sorted_1<int>(a1, a1+5); // false
int a2[Max]={1,1,2,5,7};
bool b2=is_sorted_1<int>(a2, a2+5); // true
int a3[Max]={1,1,2,7,5};
bool b3=is_sorted_1<int>(a3, a3+5); // false

vector<int> v1(a1,a1+Max);
// Aufruf von is_sorted mit vector:
bool b4=is_sorted_1<int>(v1.begin(), v1.end()); // false
};


template<typename Iterator>
bool is_sorted_2(Iterator first, Iterator last)
{ // kannn nur mit Iteratoren eines STL-Containers aufgerufen werden,
  // die ein Element value_type haben.
return std::adjacent_find(first,last,
                std::greater<Iterator::value_type>())==last;
/*
Die folgenden Anweisungen sind gleichwertig:
   typedef typename Iterator::value_type T;
   return adjacent_find(first,last,greater<T>())==last;

Die Ableitung des Typs der Elemente aus dem Typ des Iterators geht
nicht;

   typedef Iterator* T;
*/
}

template<typename Iterator, typename binaryPredicate>
bool is_sorted_2(Iterator first, Iterator last,
                                binaryPredicate comp)
{ // kann mit STL-Containern und Arrays aufgerufen werden
return adjacent_find(first,last,comp)==last;
}

template <typename Container>
bool is_sorted(const Container& c)
{ // kann wegen begin() und end() nur mit STL-Containern aufgerufen werden
return adjacent_find(c.begin(), c.end())==c.end();
}

template <typename Container, typename binaryPredicate>
bool is_sorted(const Container& c, binaryPredicate comp)
{
return adjacent_find(c.begin(), c.end() ,comp)==c.end();
}

template<typename Container>
bool is_sorted_2(const Container& c)
{ // Bei einem Container kann als Datentyp der zu vergleichenden Elemente
  // auch aus der Datentyp der Container-Elemente verwendet werden.
return (std::adjacent_find(c.begin(),c.end(),
            std::greater<Container::value_type>())==c.end());
}

void test_is_sorted_2()
{
const int Max=5;
int a1[Max]={2,1,2,5,7};
// Aufruf von is_sorted mit Array:
bool b1=is_sorted_2(a1, a1+5, std::greater<int>()); // false
int a2[Max]={1,1,2,5,7};
bool b2=is_sorted_2(a2, a2+5,std::greater<int>()); // true
int a3[Max]={1,1,2,7,5};
bool b3=is_sorted_2(a3, a3+5, std::greater<int>()); // false

// Aufruf von is_sorted mit vector:
vector<int> v1(a1,a1+Max);
bool b6=is_sorted_2(v1.begin(), v1.end(),std::greater<int>()); // false
vector<int> v2(a2,a2+Max);
bool b7=is_sorted_2(v2.begin(), v2.end(),std::greater<int>()); // true
vector<int> v3(a3,a3+Max);
bool b8=is_sorted_2(v3.begin(), v3.end(),std::greater<int>()); // false

bool b10=is_sorted(v1);
bool b11=is_sorted(v2);
bool b12=is_sorted(v3);

bool b20=is_sorted(v1,std::greater<int>());
bool b21=is_sorted(v2,std::greater<int>());
bool b22=is_sorted(v3,std::greater<int>());
}


// d)
namespace Boost_is_sorted  { // *********************************
 // In der Boost-Bibliothek findet man auch noch diese Variante:

 // http://www.boost.org/boost/detail/algorithm.hpp

 // (C) Copyright Jeremy Siek 2001.
 // Distributed under the Boost Software License, Version 1.0. (See accompany-
 // ing file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)


 template <typename ForwardIterator>
  bool is_sorted(ForwardIterator first, ForwardIterator last)
  {
    if (first == last)
      return true;

    ForwardIterator next = first;
    for (++next; next != last; first = next, ++next) {
      if (*next < *first)
        return false;
    }
    return true;
  }

  template <typename ForwardIterator, typename StrictWeakOrdering>
  bool is_sorted(ForwardIterator first, ForwardIterator last,
                 StrictWeakOrdering comp)
  {
    if (first == last)
      return true;

    ForwardIterator next = first;
    for (++next; next != last; first = next, ++next) {
      if (comp(*next, *first))
        return false;
    }

    return true;
  }

} // end of namespace N3 *********************************



inline bool notAnsiCompStr(const string& s1,const string& s2)
{ // lstrcmp verwendet den Windows-Zeichensatz
return !AnsiCompStr(s1,s2);
}

void test_is_sorted_strings()
{
using namespace std;
// b)
const int n=20; // Anzahl der strings in a
char* a[]={".","-","a","b","c","o","u","s","t","ä",
           "ü","Ä","Ö","Ü","ß","A","O","U","S","T"};
vector<string> v1(a,a+n);

bool r1=is_sorted_2(v1.begin(),v1.end(),notAnsiCompStr);
sort(v1.begin(), v1.end(),AnsiCompStr);
bool r2=is_sorted_2(v1.begin(),v1.end(),notAnsiCompStr);
}

void __fastcall TForm1::Button_3_2Click(TObject *Sender)
{
test_is_sorted_1();
test_is_sorted_2();
test_is_sorted_strings();
}


// --------------- Aufgabe 3 -------------------------------

class C {
 public:
  virtual void f()
  {
  Form1->Memo1->Lines->Add("C");
  }
  virtual void g(int i)
  {
  Form1->Memo1->Lines->Add("C-g"+IntToStr(i));
  }
};

class D : public C{
 public:
  void f()
  {
  Form1->Memo1->Lines->Add("D");
  }
  void g(int i)
  {
  Form1->Memo1->Lines->Add("D-g"+IntToStr(i));
  }
};

class E : public D{
 public:
  void f()
  {
  Form1->Memo1->Lines->Add("E");
  }
  void g(int i)
  {
  Form1->Memo1->Lines->Add("E-g"+IntToStr(i));
  }
};

void Aufg3()
{
using namespace std;
C c;
D d;
E e;
vector<C*> v;
v.push_back(&c);
v.push_back(&d);
v.push_back(&e);
// for_each(v.begin(),v.end(),C::f); // das geht nicht
// a)
for_each(v.begin(),v.end(),mem_fun(&C::f));
// b)
for_each(v.begin(),v.end(),bind2nd(mem_fun(&C::g),17));
// c)
{
vector<C> w;
w.push_back(c);
w.push_back(d);
w.push_back(e);
for_each(w.begin(),w.end(),mem_fun_ref(&C::f));
}
}

void __fastcall TForm1::Button_3_3Click(TObject *Sender)
{
Aufg3();
}





