// Solutions to "Richard Kaiser: C++ with Borland C++Builder", ISBN: 3540010270
// Copyright Richard Kaiser, 2004, All rights reserved
// oder doch besser weglassen ???


// Diese Funktionen werden in PointerU.cpp aufgerufen

// --------------- Aufgaben 3.12.10 ------------------------

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

// a)
int Leerzeichen(const char* s)
{
int n=0;
while (*s!='\0')
  {
  if (*s==' ') n++;
  s++;
  }
return n;
}

// b)
// Der Funktionsname "Leerzeichen" wird mit "LZ" abgekürzt:
// { LZ("");0 | LZ("1");0 | LZ("1 ");1 | LZ(" 1");1 | LZ(" 1 ");2 }

// c)
#include "..\..\CppUtils\TestUtils.cpp"

bool Test_Leerzeichen()
{// ein einfacher Test für die Funktion Leerzeichen
// { LZ("");0 | LZ("1");0 | LZ("1 ");1 | LZ(" 1");1 | LZ(" 1 ");2 }
bool result = true;
if (!CheckEqual_int(Leerzeichen(""),   0,"Leerzeichen(\"\")"))
  result=false;
if (!CheckEqual_int(Leerzeichen("1"),  0,"Leerzeichen(\"1\")"))
  result=false;
if (!CheckEqual_int(Leerzeichen("1 "), 1,"Leerzeichen(\"1 \")"))
  result=false;
if (!CheckEqual_int(Leerzeichen(" 1"), 1,"Leerzeichen(\" 1\")"))
  result=false;
if (!CheckEqual_int(Leerzeichen(" 1 "),2,"Leerzeichen(\" 1 \")"))
  result=false;
return result;
}



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

void Aufgabe_3_12_10_2()
{ /*
char *x;     // Diese Definition reserviert Speicher für die
       // Adresse eines Zeigers auf char.
x = "hello"; // Hier wird Speicherplatz für das Literal "hello"
       // reserviert und dessen Adresse x zugewiesen.

a) Falsch: Es wird kein nicht reservierter Speicherbereich
       überschrieben

b) Falsch: Diese Anweisung hat keine Zugriffsverletzung zur Folge.

c) Richtig: a) und b) sind gleichwertig, wenn man vom
       unterschiedlichen Zeitpunkt der Zuweisung absieht.

d) Auch diese Deklaration ist möglich. Allerdings hat x hier den
       Datentyp "Array mit Elementen des Datentyps char".
*/
}


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

void Aufgabe_3_12_10_3()
{
char const* s="blablabla";
// a)
  if (s==" ") ;    // Vergleicht die Adressen der beiden Stringliterale
           // "blablabla" und " " und nicht etwa die Strings

// b)
//  if (*s==" ") ; // char und char* können nicht verglichen werden

// c)
  if (*s=='a'+1) ; // Vergleicht das Zeichen an der Adresse von s (also
           // 'b') mit dem Zeichen 'a'+1 (ebenfalls 'b').
           // Ergebnis: true

// d)
//  if (s==' ') ;  // char* und char können nicht verglichen werden

// e)
Form1->Memo1->Lines->Add(s);    // "blablabla"
Form1->Memo1->Lines->Add(s+1);  // "lablabla"
Form1->Memo1->Lines->Add(s+20); // undefiniert, eventuell
                // eine Zugriffsverletzung

// f)
char c='A';char a[100];
strcpy(a,&c); // Kopiert alle Zeichen ab der Adresse von c bis zum
        // nächsten Nullterminator. Falls in den ersten 100 Bytes,
        // die auf c folgen, kein Nullterminator kommt, kann das
        // zu einer Zugriffsverletzung führen.
}


// --------------- Aufgabe 4 -------------------------------

void Aufgabe_3_12_10_4()
{
const int i=17;
int* p1;    char* q1;
const int* p2;    const char* q2;
int const* p3;    char const* q3;
int* const p4=p1;  char* const q4=q1;

// a)
   // p1=p2; // cannot convert 'const int *' to 'int *'
// b)
   // p1=&i; // cannot convert 'const int *' to 'int *'
// c)
   p2=p1;
// d)
   // *p3=i; // connot modify const object
// e)
//   *p4=18; // Syntaktisch ok, aber kein Speicher reserviert für *p4.

// f)
   // q1=q2;  // cannot convert 'const char *' to 'char *'
// g)
   q1="abc";  // deprecated
// h)
   q2=q1;
// i)
   // *q3='x'; // cannot modify const object
// j)
//   *q4='x'; // Syntaktisch ok, aber kein Speicher reserviert für *p4.
}


// --------------- Aufgabe 5 -------------------------------

int Checksum(const char* name)
{
char a[10]; // 10 is enough
strcpy(a,name);
int s=0;
for (int i=0; a[i]!=0; i++) s=s+a[i];
return s;
}

void Aufgabe_3_12_10_5()
{
int c= Checksum("Check me, baby");
/*
Der Aufruf von Checksum mit einem Argument, das länger als 10
Zeichen ist, kann dazu führen, dass nicht reservierte
Speicherbereiche überschrieben werden (buffer overflow).

Solche Funktionen werden gerne von Viren-Programmierern benutzt.
Mit geschickt gewählten Argumenten wird
1. die Rücksprungadresse auf dem Stack überschrieben, und
2. Code übergeben, der dann ausgeführt wird.
*/
}


// --------------- Aufgabe 6 -------------------------------

void assign_c(int*& x, int* y)
{ // Da *y nie verändert wird, könnte es als const definiert werden.
  // Aber dann könnte es nicht mehr einem nicht konstanten Zeiger wie
  // x zugewiesen werden.
x=y;
}

void replace_c(int* x, const int* y)
{ // Da *y nie verändert wird, kann es als const definiert werden.
*x=*y;
}

void clone_c(int*& x, const int* y)
{ // Da *y nie verändert wird, kann es als const definiert werden.
x=new int(*y);
}

void Aufgabe_3_12_10_6()
{
int* x=new int(17);
int* y=new int(18);
assign_c(x,y);
replace_c(x,y);
clone_c(x,y);
}
