Register for your free account! | Forgot your password?

Go Back   elitepvpers > Coders Den > General Coding > Coding Tutorials
You last visited: Today at 17:39

  • Please register to post and access all features, it's quick, easy and FREE!

Advertisement



[Tutorial] Erste Schritte mit "C++" / + erstes Programm entwickeln

Discussion on [Tutorial] Erste Schritte mit "C++" / + erstes Programm entwickeln within the Coding Tutorials forum part of the General Coding category.

Reply
 
Old   #1
 
elite*gold: 1
The Black Market: 217/0/0
Join Date: Feb 2012
Posts: 18,587
Received Thanks: 5,580
Post [Tutorial] Erste Schritte mit "C++" / + erstes Programm entwickeln

Hey,
Ich stelle euch nun ein Tutorial vor,
was euch erleichtern soll mit C++ zu arbeiten!



Vorwort

Für dieses Tutorial wurde der Borland C++ Builder 5 eingesetzt.

Folgendes wird erklärt: Eine Anwendung wird geschrieben, die eine Instanz einer Klasse "Datenbank" hat. Diese Datenbank wird sich selbst mit zufälligen Werten füllen können. Die Anwendung wird ein Image haben, das die Datenbank als Diagramm ausgibt. Dann wird die Datenbank noch eine Methode zum sortieren bekommen, die mit einem Timer laufen wird. Der Timer zeichnet jedes mal das Diagramm neu. So kann man mitsehen, wie die Datenbank sortiert wird und wie der jeweilige Sortieralgorithmus funktioniert.

Programm

Startet den Borland C++ Builder und legt ein neues Projekt an. Und zwar wählt ihr "Anwendung". Jetzt speichert erst einmal alle Dateien in einen Ordner und compiliert durch. Lasst die Unit1 Datei so benannt und die Projektdatei auch. Außer ihr wisst nachher selber, wie ihr das Tutorial an eure Wünsche anpassen könnt. Das Programm läuft also und kann weiter programmiert werden!

Folgende Elemente werden wir benötigen, ich werde sie vorher schon nennen, jedoch müsst ihr sie nicht gleich anlegen!

2 Objekte TBevel (damit das ganze schöner aussieht)
3 Objekte TButton
1 Objekt TImage
1 Objekt TTimer

Euer Projekt könnte dann so aussehen:


Die Anordnung ist egal, was aber wichtig ist: Das Image sollte 225x225 px groß sein! Später mehr dazu. Und der Timer sollte von Anfang an auf Enabled = false sein! Damit nicht beim Programmstart schon sortiert wird!

Jetzt geht ihr beim Builder auf Datei -> Neu ... und legt eine neue Headerdatei an. Hier schreiben wir jetzt die Klasse rein. Sie soll "Datenbank" heißen, was auch ihrer Aufgabe enspricht. Zwar eine sinnlose Datenbank, aber es ist eine Datenbank. Wir lassen alle Methoden und Eigenschaften auf public. Wir brauchen jetzt einen Integer für die Liste, also die eigentliche Datenbank, einen Zeiger auf das Bild, eine Funktion, die der Klasse das Bild übergibt, eine Methode die die Liste füllt, eine die zeichnet und eine die alles sortiert. Natürlich wird jede Methode später einzeln beschrieben!
Ihr müsst außerdem die Datei vcl.h einbinden, damit die Klasse auf die Objekte vom Borlandm Builder zugreifen kann.

Das ganze sieht dann so aus:

Datenbank.h
Code:
Code:
class Datenbank
{
* *public:

* *int Liste[225];
* *TImage* mp_Bild;

* *void fuellen();
* *void setImage(TImage* p_Bild);
* *void zeichnen();
* *void sortieren();
};
Speichert nun die Datei ab, wie oben angegeben, unter Datenbank.h. Natürlich in das gleiche Verzeichnis, in dem auch das Projekt liegt. Da ihr die Datei über die Entwicklungsumgebung angelegt habt, während das Projekt geöffnet war, wurde die Headerdatei automatisch dem Projekt zugefügt. Also auf keinen Fall die Headerdatei mit einem Editor anlegen, oder das Projekt vor dem Anlegen schließen! Das gleiche gilt auch bei der nächsten Datei!

Jetzt legen wir die dazugehörige C++ Datei an! Wieder auf Datei -> Neu ... Cpp-Datei. Hier wird die Klasse ausprogrammiert. Damit wir die Struktur der Klasse kennen, müssen wir sie einbinden. Legt die einzelnen Funktionen schonmal an, lasst sie aber noch leer:

Datenbank.cpp
Code:
Code:
#include "Datenbank.h"

void Datenbank::fuellen()
{

}

void Datenbank::setImage(TImage* p_Bild)
{

}


void Datenbank::zeichnen()
{

}

void Datenbank::sortieren()
{

}
Als nächstes programmieren wir die Füllmethode aus. Das geht auch ziemlich einfach:

Datenbank.cpp
Code:
Code:
#include "Datenbank.h"
#include <stdlib.h>

void Datenbank::fuellen()
{
* *for(int i = 0; i < 225; i++)
* *{
* * * Liste[i] = random(226);
* *}
}

void Datenbank::setImage(TImage* p_Bild)
{
* *mp_Bild = p_Bild;
}

void Datenbank::zeichnen()
{

}

void Datenbank::sortieren()
{

}
Die Liste der Klasse wird mit zufälligen Zahlenwerten von 0 - 225 gefüllt. Um random() zu verwenden, müssen wir die Bibliothek stdlib.h einbinden. random(int Zahl) liefert eine Zufallszahl im Bereich von 0 bis (Zahl-1) zurück. Unser Image ist 255x255 px groß, also sehen wir nur Werte die zwischen 0 und 225 liegen, deshalb das Intervall von random().


Jetzt wird es langsam anspruchsvoller, zumindest, wenn man noch nie mit dem TImage Objekt gearbeitet hat. Wir haben jetzt also unseren Zeiger auf das Image mp_Bild. Diesem können wir nun Anweisungen zum zeichnen geben, mit der Methode Canvas.

Datenbank.cpp
Code:
Code:
//...

void Datenbank::zeichnen()
{
* *mp_Bild->Canvas->MoveTo(0,0);
* *mp_Bild->Canvas->Rectangle(0,0,225,225);

* *mp_Bild->Canvas->MoveTo(0,0);

* *for(int i = 0; i < 225; i++)
* *{
* * * mp_Bild->Canvas->LineTo(i,Liste[i]);
* *}
}

//...
Als erstes bewegen wir den Punkt, von dem aus wir anfangen zu zeichnen, ganz nach links oben. Anders als im gewöhnlichen Koordinatensystem, fängt man nicht unten links bei (X/Y) (0/0) an, sondern oben links.*
Wir zeichnen ein Rechteck (Rectangel(X1, Y1, X2, Y2)), damit wir einen Rahmen haben. Das dient nur dazu, dass das ganze schöner aussieht. Ist also nicht unbedingt notwendig. Rectangle zeichnet einen Rahmen vom Punkt (X1/Y1) nach (X2/Y2). Dann setzen wir den "Stift" wieder nach links oben in die Ecke.
Jetzt kommt das eigentliche: Es wird eine Linie gezeichnet, abhängig von den Werten der Liste. Die Linie wird gezeichnet mit X = i und Y = Liste[i]. Wäre die Liste also mit 225 gleichen Werten gefüllt, würde eine gerade durch das Bild gehen.

Nun müssen wir soriteren. Ganz einfach wäre es natürlich mit einer fertigen Sortiermethode. Wir schreiben jedoch selber eine, ihr könnt später das Programm auch mit anderen Methoden ausprobieren.

Unser Sortieralgorithmus wird so funktionieren: Er durchläuft die Liste und überprüft den nächsten Eintrag, ob dieser größer ist. Und tauscht dann ggf. Das bedeutet natürlich, dass man die Liste n-mal sortieren muss. Der Sortieralgorithmus würde beim ersten mal nur klappen, wenn man zwei oder vielleicht sogar noch drei Einträge hätte. Aber bei 225 Einträgen muss der Algorithmus öfters durchlaufen!

Die Problematik beim Tauschen von Variablen beim Programmieren ist in erster Linie die, dass ich, wenn ich zwei Variablen a und b habe, b a zuweise und dann zwei gleiche Werte habe. Dann kann ich nicht mehr a b zuweisen. Deshalb braucht man hier eine Hilfs- bzw. Tauschvariable.


Beispiel:
Code:
Code:
* *| a | b | h |
* *|---|---|---|
* *| 5 | 2 | - |
*1.| 5 | 2 | 5 |
*2.| 2 | 2 | 5 |
*3.| 2 | 5 | 5 |
Unsere Sortierenmethode sieht dann so aus:

Datenbank.cpp
Code:
Code:
//...

void Datenbank::sortieren()
{
* *int h;
* *
* *for(int i = 0; i < 225; i++)
* *{
* * * if(Liste[i] > Liste[i+1])
* * * {
* * * * *h = Liste[i];
* * * * *Liste[i] = Liste[i+1];
* * * * *Liste[i+1] = h;
* * * }
* *}
}

//...
Das wars nun von der Klasse!*


Jetzt müssen wir nurnoch das Form anpassen. Öffnet die Unit1.h und ruft eine Instanz von der Datenbank ins Leben. Bei mir heißt sie DieDatenbank. Schreibt sie unter die public-Anwenderdeklarationen. Und natürlich müsst ihr die Headerdatei Datenbank.h einfügen! So sollte das ganze dann aussehen:

Unit1.h
Code:
Code:
#include <Controls.hpp>
#include <StdCtrls.hpp>
#include <Forms.hpp>
#include <ExtCtrls.hpp>

#include "Datenbank.h"
//---------------------------------------------------------------------------
class TForm1 : public TForm
{
__published:	// Von der IDE verwaltete Komponenten
* * * * TBevel *Bevel1;
* * * * TBevel *Bevel2;
* * * * TButton *Button1;
* * * * TButton *Button2;
* * * * TButton *Button3;
* * * * TImage *Image1;
* * * * TTimer *Timer1;
* * * * void __fastcall Button1Click(TObject *Sender);
* * * * void __fastcall Button2Click(TObject *Sender);
private:	// Anwender-Deklarationen
public:		// Anwender-Deklarationen
* * * * __fastcall TForm1(TComponent* Owner);
* * * * Datenbank DieDatenbank;
};
//---------------------------------------------------------------------------
extern PACKAGE TForm1 *Form1;
//---------------------------------------------------------------------------
#endif
Jetzt wieder zurück zur Unit1.cpp. Dort müssen wir jedem Button seine Funktion zuweisen. Ihr könnt ihre Caption auch demensprechend ändern. Also auf den Button "Füllen", "Zeichnen" und "Soriteren" schreiben. In den Konstruktor von Form1 setzen wir das Bild fest und zeichnen die leere Datenbank. So, dass wir nur einen Rahmen haben.*
Vergesst nicht, dass der Timer Enabled = false sein sollte! Also, falls ihr das noch nicht gemacht habt, stellt das beim Objektinspektor ein oder schreibt es in den Konstruktor von Form1 rein! Ich werde beides machen. Alle Buttons führen direkt eine Methode aus, nur der Sortierbutton setzt den Timer auf Enabled = true. So sollte eure Unit1.cpp nun aussehen:

Unit1.cpp
Code:
Code:
//---------------------------------------------------------------------------

#include <vcl.h>
#pragma hdrstop

#include "Unit1.h"
//---------------------------------------------------------------------------
#pragma package(smart_init)
#pragma resource "*.dfm"
TForm1 *Form1;
//---------------------------------------------------------------------------
__fastcall TForm1::TForm1(TComponent* Owner)
* * * * : TForm(Owner)
{
* *Timer1->Enabled *= false;
* *Timer1->Interval = 100;
* *
* *DieDatenbank.setImage(Image1);
* *DieDatenbank.zeichnen();
}
//---------------------------------------------------------------------------

void __fastcall TForm1::Button1Click(TObject *Sender)
{
* *DieDatenbank.fuellen();
}
//---------------------------------------------------------------------------
void __fastcall TForm1::Button2Click(TObject *Sender)
{
* *DieDatenbank.setImage(Image1);
* *DieDatenbank.zeichnen();
}
//---------------------------------------------------------------------------
void __fastcall TForm1::Button3Click(TObject *Sender)
{
* *Timer1->Enabled = true;
}
//---------------------------------------------------------------------------


void __fastcall TForm1::Timer1Timer(TObject *Sender)
{
* *DieDatenbank.sortieren();
* *DieDatenbank.zeichnen(); * * * *
}
//---------------------------------------------------------------------------
So sollte euer Programm nun funktionieren:





C++ Wecker / Zeitgesteuerte Codeausführung

Für unseren Wecker benötigen wir eine Klasse (Wecker). Diese Klasse hat die set- und get-Methoden (beim Wecker: set: stellen(...) und get: Weckzeit()). Eine Methode, die die aktuelle Windows-Uhrzeit auf dem Bildschirm ausgibt Uhrzeit(). Und natürlich das wichtigste: Die Methode, die ausgeführt wird, wenn die Weckzeit mit der Uhrzeit übereinstimmt: klingeln().
Meine Klasse wird also ein Wecker. Man kann natürlich auch alles andere machen. Ein Wecker ist bloß in diesem Fall das beste Beispiel, passt wunderbar in das Prinzip rein!

Was noch wichtig ist: Wir müssen die Uhrzeit regelmäßig abfragen. Also brauchen wir eine Endlosschleife mit einer Sleep()-Methode.

Und außerdem habe ich die Methode system("CLS") auch ein paar Mal gebraucht. Sie löscht den Bildschirm in der Konsole. Folgende Bibliotheken sind nun wichtig für uns:

Code:
Code:
#include <stdio.h>
#include <conio.h>
#include <stdlib.h> *// system()
#include <time.h> * *// time
#include <dos.h> * * // time

class Wecker
{
* *// ...
};

void main()
{
* *getch();
}
Die Klasse braucht natürlich ihre Weckzeit, die sie speichert. Also geben wir ihr drei Integerwerte. Außerdem noch die Variable, mit der wir die Zeit abfragen. Diese Variablen setzen wir alle auf private, da wir sie nur innerhalb der Klasse benötigen. Und time t setzen wir in die Klasse und nicht in die einzelnen Methoden, da wir sie in mehr als einer Methode benötigen!

Code:
Code:
#include <stdio.h>
#include <conio.h>
#include <stdlib.h> *// system()
#include <time.h> * *// time
#include <dos.h> * * // time


class Wecker
{
private:
* *int * *WZ_h; * *//WeckZeit Stunde
* *int * *WZ_m;
* *int * *WZ_s;

* *struct time t;

public:
* *void stellen(int h, int m, int s)
* *{

* *}

* *void Uhrzeit()
* *{

* *}

* *void Weckzeit()
* *{

* *}

* *bool klingeln()
* *{

* *}
};

//---------------------------------------------------------------------------

void main()
{
* *getch();
}
So, die leeren Methoden hab ich auch gleich hinzugefügt. stellen() benötigt natürlich Parameter und übergibt die Werte von außen nur der Klasse. klingeln() hat den Rückgabetyp bool (true / false), damit man später die Klasse fragen kann: Ist die Weckzeit schon erreicht? Nein? -> false; Ja? -> true.
Das ganze sieht dann so aus:

Code:
Code:
class Wecker
{
private:
* *int * *WZ_h; * *//WeckZeit Stunde
* *int * *WZ_m;
* *int * *WZ_s;

* *struct time t;

public:
* *void stellen(int h, int m, int s)
* *{
* * * WZ_h = h;
* * * WZ_m = m;
* * * WZ_s = s;
* *}

* *void Uhrzeit()
* *{

* *}

* *void Weckzeit()
* *{

* *}

* *bool klingeln()
* *{
* * * gettime(&t);
* * **
* * * if(WZ_h == t.ti_hour && WZ_m == t.ti_min && WZ_s == t.ti_sec)
* * * {
* * * * *return true;
* * * }
* * * else
* * * {
* * * * *return false;
* * * }
* *}
};
gettime(&t) holt die aktuelle Zeit und dann können wir mit t.ti_hour usw. die Uhrzeit abfragen. Ihr könnt natürlich gettime() nicht an einer Stelle ausführen, wo sich das Programm 5 Minuten vor der Abfrage befindet, da dann in t der Wert von vor 5 Minuten stehen würde. Ich hoffe das ist so einigermaßen klar!
So, und dann ist die Abfrage mit UND verknüpft. Das ergebnis muss überall true sein, damit das Ereignis eintritt. Also Stunde, Minute und Sekunde müssen übereinstimmen (Weckzeit / Uhrzeit).

Jetzt kommen wir noch schnell zur Ausgabe von den beiden Zeiten:

Code:
Code:
class Wecker
{
private:
* *int * *WZ_h; * *//WeckZeit Stunde
* *int * *WZ_m;
* *int * *WZ_s;

* *struct time t;

public:
* *void stellen(int h, int m, int s)
* *{
* * * WZ_h = h;
* * * WZ_m = m;
* * * WZ_s = s;
* *}

* *void Uhrzeit()
* *{
* * * gettime(&t);

* * * printf("Uhrzeit: %i:%i:%i\n", t.ti_hour, t.ti_min, t.ti_sec);
* * * sleep(1);
* * * system("CLS");
* *}

* *void Weckzeit()
* *{
* * * printf("Weckzeit: %i:%i:%i\n", WZ_h, WZ_m, WZ_s);
* *}

* *bool klingeln()
* *{
* * * gettime(&t);
* * **
* * * if(WZ_h == t.ti_hour && WZ_m == t.ti_min && WZ_s == t.ti_sec)
* * * {
* * * * *return true;
* * * }
* * * else
* * * {
* * * * *return false;
* * * }
* *}
};
Wichtig ist, dass Uhrzeit() später nach Weckzeit() ausgeführt wird, da sich die sleep()-Methode in Uhrzeit() befindet und man sonst nichts von der Weckzeit mitbekommen würde. Aber das ist auch nicht so wichtig! Das dient uns im Moment nur zur Kontrolle.
So, Weckzeit() ist klar. Gibt einfach nur die 3 Integer auf dem Bildschirm aus. Und Uhrzeit(): Holt sich erst wieder die aktuelle Uhrzeit mit gettime() und gibt sie dann auf dem Bildschirm aus. Daraufhin folgt sleep(). 1 ist der kleinste Wert. sleep() erwartet einen unsignet int , das bedeutet einen Integer ohne Vorzeichen. Negative Werte sind ausgeschlossen. Was aber viel schlimmer ist: Wir können keine Kommazahlen (double, float) verwenden! Das heißt, manchmal wird der Wecker nicht ausgelöst, wenn sich die sleep() Methode grade an einem unpassenden Zeitpunkt befindet. Ihr werdet es noch beim Test sehen!
Aber das ist nunmal die einfachste Methode und vorerst ausreichend.
Als nächstes wird der Bildschirm gelöscht, damit wir nicht eine endlose Liste von Uhrzeiten haben, wenn wir später jede Sekunde die Uhrzeit aufrufen.

Das wars von der Klasse! Jetzt fehlt uns nurnoch die main()-Funktion! Bei dieser fasse ich mich kurz.

Code:
Code:
void main()
{
* *Wecker meinWecker;

* *int scan_h; * // Zwischenspeicher fuer Eingabe
* *int scan_m;
* *int scan_s;

* *printf("Wecker einstellen: \n");
* *printf("hh: ");
* *scanf("%i", &scan_h);

* *printf("mm:");
* *scanf("%i", &scan_m);

* *printf("ss:");
* *scanf("%i", &scan_s);

* *system("cls");

* *meinWecker.stellen(scan_h, scan_m, scan_s);

* *while(1)
* *{
* * * meinWecker.Weckzeit();
* * * meinWecker.Uhrzeit();

* * * if(meinWecker.klingeln() == true)
* * * {
* * * * *printf("BEEEEEP!");
* * * * *//printf("\a"); * * * * // PC macht einen Beepton
* * * * *break;
* * * }
* *}

* *getch();

* *system("CLS");

* *printf("Programm beenden durch Tastendruck ...");
* *getch();
}
Als erstes rufen wir eine Instanz ins Leben (meinWecker). Dann kommen Zwischenspeichervariablen für den Wecker, da wir mit scanf jede Variable einzeln abfragen. Das erstpart uns den Stress mit den Doppelpunkten, dass wir nicht noch einen String außeinander nehmen müssen. Dieses Tutorial soll ja nur das Minimum erklären! Die Texte aus den printf()-Methoden dienen nur zur Orientierung des Benutzers. Dann wird der Bildschirm noch mal gelöscht und die Werte an die Klasse übergeben (meinWecker.stellen(...)), bevor's los geht! Und dann kommt die (theoretische) Endlosschleife. Jedoch befindet sich ein break in ihr.
Jetzt werden immer beide Zeiten ausgegeben. Uhr- und Weckzeit. Insgesamt wird dann ca. eine Sekunde gewartet, dann verglichen: Wenn der Vergleich positiv ausfällt, liefert klingeln() true zurück. Und dann kommt es zum Beep und zum Abbruch der while()-Schleife.
Dann noch ein Tastendruck und man wird raus geführt.

Programm[/SIZE]

Startet den Borland C++ Builder und legt ein neues Projekt an. Und zwar wählt ihr "Anwendung". Jetzt speichert erst einmal alle Dateien in einen Ordner und compiliert durch. Lasst die Unit1 Datei so benannt und die Projektdatei auch. Außer ihr wisst nachher selber, wie ihr das Tutorial an eure Wünsche anpassen könnt. Das Programm läuft also und kann weiter programmiert werden!

Folgende Elemente werden wir benötigen, ich werde sie vorher schon nennen, jedoch müsst ihr sie nicht gleich anlegen!

2 Objekte TBevel (damit das ganze schöner aussieht)
3 Objekte TButton
1 Objekt TImage
1 Objekt TTimer

Euer Projekt könnte dann so aussehen:


Die Anordnung ist egal, was aber wichtig ist: Das Image sollte 225x225 px groß sein! Später mehr dazu. Und der Timer sollte von Anfang an auf Enabled = false sein! Damit nicht beim Programmstart schon sortiert wird!

Jetzt geht ihr beim Builder auf Datei -> Neu ... und legt eine neue Headerdatei an. Hier schreiben wir jetzt die Klasse rein. Sie soll "Datenbank" heißen, was auch ihrer Aufgabe enspricht. Zwar eine sinnlose Datenbank, aber es ist eine Datenbank. Wir lassen alle Methoden und Eigenschaften auf public. Wir brauchen jetzt einen Integer für die Liste, also die eigentliche Datenbank, einen Zeiger auf das Bild, eine Funktion, die der Klasse das Bild übergibt, eine Methode die die Liste füllt, eine die zeichnet und eine die alles sortiert. Natürlich wird jede Methode später einzeln beschrieben!
Ihr müsst außerdem die Datei vcl.h einbinden, damit die Klasse auf die Objekte vom Borlandm Builder zugreifen kann.

Das ganze sieht dann so aus:

Datenbank.h
Code:
Code:
class Datenbank
{
* *public:

* *int Liste[225];
* *TImage* mp_Bild;

* *void fuellen();
* *void setImage(TImage* p_Bild);
* *void zeichnen();
* *void sortieren();
};
Speichert nun die Datei ab, wie oben angegeben, unter Datenbank.h. Natürlich in das gleiche Verzeichnis, in dem auch das Projekt liegt. Da ihr die Datei über die Entwicklungsumgebung angelegt habt, während das Projekt geöffnet war, wurde die Headerdatei automatisch dem Projekt zugefügt. Also auf keinen Fall die Headerdatei mit einem Editor anlegen, oder das Projekt vor dem Anlegen schließen! Das gleiche gilt auch bei der nächsten Datei!

Jetzt legen wir die dazugehörige C++ Datei an! Wieder auf Datei -> Neu ... Cpp-Datei. Hier wird die Klasse ausprogrammiert. Damit wir die Struktur der Klasse kennen, müssen wir sie einbinden. Legt die einzelnen Funktionen schonmal an, lasst sie aber noch leer:

Datenbank.cpp
Code:
Code:
#include "Datenbank.h"

void Datenbank::fuellen()
{

}

void Datenbank::setImage(TImage* p_Bild)
{

}


void Datenbank::zeichnen()
{

}

void Datenbank::sortieren()
{

}
Als nächstes programmieren wir die Füllmethode aus. Das geht auch ziemlich einfach:

Datenbank.cpp
Code:
Code:
#include "Datenbank.h"
#include <stdlib.h>

void Datenbank::fuellen()
{
* *for(int i = 0; i < 225; i++)
* *{
* * * Liste[i] = random(226);
* *}
}

void Datenbank::setImage(TImage* p_Bild)
{
* *mp_Bild = p_Bild;
}

void Datenbank::zeichnen()
{

}

void Datenbank::sortieren()
{

}
Die Liste der Klasse wird mit zufälligen Zahlenwerten von 0 - 225 gefüllt. Um random() zu verwenden, müssen wir die Bibliothek stdlib.h einbinden. random(int Zahl) liefert eine Zufallszahl im Bereich von 0 bis (Zahl-1) zurück. Unser Image ist 255x255 px groß, also sehen wir nur Werte die zwischen 0 und 225 liegen, deshalb das Intervall von random().


Jetzt wird es langsam anspruchsvoller, zumindest, wenn man noch nie mit dem TImage Objekt gearbeitet hat. Wir haben jetzt also unseren Zeiger auf das Image mp_Bild. Diesem können wir nun Anweisungen zum zeichnen geben, mit der Methode Canvas.

Datenbank.cpp
Code:
Code:
//...

void Datenbank::zeichnen()
{
* *mp_Bild->Canvas->MoveTo(0,0);
* *mp_Bild->Canvas->Rectangle(0,0,225,225);

* *mp_Bild->Canvas->MoveTo(0,0);

* *for(int i = 0; i < 225; i++)
* *{
* * * mp_Bild->Canvas->LineTo(i,Liste[i]);
* *}
}

//...
Als erstes bewegen wir den Punkt, von dem aus wir anfangen zu zeichnen, ganz nach links oben. Anders als im gewöhnlichen Koordinatensystem, fängt man nicht unten links bei (X/Y) (0/0) an, sondern oben links.*
Wir zeichnen ein Rechteck (Rectangel(X1, Y1, X2, Y2)), damit wir einen Rahmen haben.

Das dient nur dazu, dass das ganze schöner aussieht. Ist also nicht unbedingt notwendig. Rectangle zeichnet einen Rahmen vom Punkt (X1/Y1) nach (X2/Y2). Dann setzen wir den "Stift" wieder nach links oben in die Ecke.
Jetzt kommt das eigentliche: Es wird eine Linie gezeichnet, abhängig von den Werten der Liste. Die Linie wird gezeichnet mit X = i und Y = Liste[i]. Wäre die Liste also mit 225 gleichen Werten gefüllt, würde eine gerade durch das Bild gehen.


Nun müssen wir soriteren. Ganz einfach wäre es natürlich mit einer fertigen Sortiermethode. Wir schreiben jedoch selber eine, ihr könnt später das Programm auch mit anderen Methoden ausprobieren.

Unser Sortieralgorithmus wird so funktionieren: Er durchläuft die Liste und überprüft den nächsten Eintrag, ob dieser größer ist. Und tauscht dann ggf. Das bedeutet natürlich, dass man die Liste n-mal sortieren muss. Der Sortieralgorithmus würde beim ersten mal nur klappen, wenn man zwei oder vielleicht sogar noch drei Einträge hätte. Aber bei 225 Einträgen muss der Algorithmus öfters durchlaufen!


Die Problematik beim Tauschen von Variablen beim Programmieren ist in erster Linie die, dass ich, wenn ich zwei Variablen a und b habe, b a zuweise und dann zwei gleiche Werte habe. Dann kann ich nicht mehr a b zuweisen. Deshalb braucht man hier eine Hilfs- bzw. Tauschvariable.



Beispiel:
Code:
Code:
* *| a | b | h |
* *|---|---|---|
* *| 5 | 2 | - |
*1.| 5 | 2 | 5 |
*2.| 2 | 2 | 5 |
*3.| 2 | 5 | 5 |
Unsere Sortierenmethode sieht dann so aus:

Datenbank.cpp
Code:
Code:
//...

void Datenbank::sortieren()
{
* *int h;
* *
* *for(int i = 0; i < 225; i++)
* *{
* * * if(Liste[i] > Liste[i+1])
* * * {
* * * * *h = Liste[i];
* * * * *Liste[i] = Liste[i+1];
* * * * *Liste[i+1] = h;
* * * }
* *}
}

//...
Das wars nun von der Klasse!*


Jetzt müssen wir nurnoch das Form anpassen. Öffnet die Unit1.h und ruft eine Instanz von der Datenbank ins Leben. Bei mir heißt sie DieDatenbank. Schreibt sie unter die public-Anwenderdeklarationen. Und natürlich müsst ihr die Headerdatei Datenbank.h einfügen! So sollte das ganze dann aussehen:

Unit1.h
Code:
Code:
#include <Controls.hpp>
#include <StdCtrls.hpp>
#include <Forms.hpp>
#include <ExtCtrls.hpp>

#include "Datenbank.h"
//---------------------------------------------------------------------------
class TForm1 : public TForm
{
__published:	// Von der IDE verwaltete Komponenten
* * * * TBevel *Bevel1;
* * * * TBevel *Bevel2;
* * * * TButton *Button1;
* * * * TButton *Button2;
* * * * TButton *Button3;
* * * * TImage *Image1;
* * * * TTimer *Timer1;
* * * * void __fastcall Button1Click(TObject *Sender);
* * * * void __fastcall Button2Click(TObject *Sender);
private:	// Anwender-Deklarationen
public:		// Anwender-Deklarationen
* * * * __fastcall TForm1(TComponent* Owner);
* * * * Datenbank DieDatenbank;
};
//---------------------------------------------------------------------------
extern PACKAGE TForm1 *Form1;
//---------------------------------------------------------------------------
#endif
Jetzt wieder zurück zur Unit1.cpp. Dort müssen wir jedem Button seine Funktion zuweisen. Ihr könnt ihre Caption auch demensprechend ändern. Also auf den Button "Füllen", "Zeichnen" und "Soriteren" schreiben. In den Konstruktor von Form1 setzen wir das Bild fest und zeichnen die leere Datenbank. So, dass wir nur einen Rahmen haben.


Vergesst nicht, dass der Timer Enabled = false sein sollte! Also, falls ihr das noch nicht gemacht habt, stellt das beim Objektinspektor ein oder schreibt es in den Konstruktor von Form1 rein! Ich werde beides machen. Alle Buttons führen direkt eine Methode aus, nur der Sortierbutton setzt den Timer auf Enabled = true. So sollte eure Unit1.cpp nun aussehen:

Unit1.cpp
Code:
Code:
//---------------------------------------------------------------------------

#include <vcl.h>
#pragma hdrstop

#include "Unit1.h"
//---------------------------------------------------------------------------
#pragma package(smart_init)
#pragma resource "*.dfm"
TForm1 *Form1;
//---------------------------------------------------------------------------
__fastcall TForm1::TForm1(TComponent* Owner)
* * * * : TForm(Owner)
{
* *Timer1->Enabled *= false;
* *Timer1->Interval = 100;
* *
* *DieDatenbank.setImage(Image1);
* *DieDatenbank.zeichnen();
}
//---------------------------------------------------------------------------

void __fastcall TForm1::Button1Click(TObject *Sender)
{
* *DieDatenbank.fuellen();
}
//---------------------------------------------------------------------------
void __fastcall TForm1::Button2Click(TObject *Sender)
{
* *DieDatenbank.setImage(Image1);
* *DieDatenbank.zeichnen();
}
//---------------------------------------------------------------------------
void __fastcall TForm1::Button3Click(TObject *Sender)
{
* *Timer1->Enabled = true;
}
//---------------------------------------------------------------------------


void __fastcall TForm1::Timer1Timer(TObject *Sender)
{
* *DieDatenbank.sortieren();
* *DieDatenbank.zeichnen(); * * * *
}
//---------------------------------------------------------------------------
So sollte euer Programm nun funktionieren:





C++ Wecker / Zeitgesteuerte Codeausführung

Für unseren Wecker benötigen wir eine Klasse (Wecker). Diese Klasse hat die set- und get-Methoden (beim Wecker: set: stellen(...) und get: Weckzeit()). Eine Methode, die die aktuelle Windows-Uhrzeit auf dem Bildschirm ausgibt Uhrzeit(). Und natürlich das wichtigste: Die Methode, die ausgeführt wird, wenn die Weckzeit mit der Uhrzeit übereinstimmt: klingeln().
Meine Klasse wird also ein Wecker. Man kann natürlich auch alles andere machen. Ein Wecker ist bloß in diesem Fall das beste Beispiel, passt wunderbar in das Prinzip rein!


Was noch wichtig ist: Wir müssen die Uhrzeit regelmäßig abfragen. Also brauchen wir eine Endlosschleife mit einer Sleep()-Methode.



Und außerdem habe ich die Methode system("CLS") auch ein paar Mal gebraucht. Sie löscht den Bildschirm in der Konsole. Folgende Bibliotheken sind nun wichtig für uns:

Code:
Code:
#include <stdio.h>
#include <conio.h>
#include <stdlib.h> *// system()
#include <time.h> * *// time
#include <dos.h> * * // time

class Wecker
{
* *// ...
};

void main()
{
* *getch();
}
Die Klasse braucht natürlich ihre Weckzeit, die sie speichert. Also geben wir ihr drei Integerwerte. Außerdem noch die Variable, mit der wir die Zeit abfragen. Diese Variablen setzen wir alle auf private, da wir sie nur innerhalb der Klasse benötigen. Und time t setzen wir in die Klasse und nicht in die einzelnen Methoden, da wir sie in mehr als einer Methode benötigen!

Code:
Code:
#include <stdio.h>
#include <conio.h>
#include <stdlib.h> *// system()
#include <time.h> * *// time
#include <dos.h> * * // time


class Wecker
{
private:
* *int * *WZ_h; * *//WeckZeit Stunde
* *int * *WZ_m;
* *int * *WZ_s;

* *struct time t;

public:
* *void stellen(int h, int m, int s)
* *{

* *}

* *void Uhrzeit()
* *{

* *}

* *void Weckzeit()
* *{

* *}

* *bool klingeln()
* *{

* *}
};

//---------------------------------------------------------------------------

void main()
{
* *getch();
}
So, die leeren Methoden hab ich auch gleich hinzugefügt. stellen() benötigt natürlich Parameter und übergibt die Werte von außen nur der Klasse. klingeln() hat den Rückgabetyp bool (true / false), damit man später die Klasse fragen kann: Ist die Weckzeit schon erreicht? Nein? -> false; Ja? -> true.
Das ganze sieht dann so aus:

Code:
Code:
class Wecker
{
private:
* *int * *WZ_h; * *//WeckZeit Stunde
* *int * *WZ_m;
* *int * *WZ_s;

* *struct time t;

public:
* *void stellen(int h, int m, int s)
* *{
* * * WZ_h = h;
* * * WZ_m = m;
* * * WZ_s = s;
* *}

* *void Uhrzeit()
* *{

* *}

* *void Weckzeit()
* *{

* *}

* *bool klingeln()
* *{
* * * gettime(&t);
* * **
* * * if(WZ_h == t.ti_hour && WZ_m == t.ti_min && WZ_s == t.ti_sec)
* * * {
* * * * *return true;
* * * }
* * * else
* * * {
* * * * *return false;
* * * }
* *}
};
gettime(&t) holt die aktuelle Zeit und dann können wir mit t.ti_hour usw. die Uhrzeit abfragen. Ihr könnt natürlich gettime() nicht an einer Stelle ausführen, wo sich das Programm 5 Minuten vor der Abfrage befindet, da dann in t der Wert von vor 5 Minuten stehen würde.

Ich hoffe das ist so einigermaßen klar!
So, und dann ist die Abfrage mit UND verknüpft. Das ergebnis muss überall true sein, damit das Ereignis eintritt. Also Stunde, Minute und Sekunde müssen übereinstimmen (Weckzeit / Uhrzeit).

Jetzt kommen wir noch schnell zur Ausgabe von den beiden Zeiten:

Code:
Code:
class Wecker
{
private:
* *int * *WZ_h; * *//WeckZeit Stunde
* *int * *WZ_m;
* *int * *WZ_s;

* *struct time t;

public:
* *void stellen(int h, int m, int s)
* *{
* * * WZ_h = h;
* * * WZ_m = m;
* * * WZ_s = s;
* *}

* *void Uhrzeit()
* *{
* * * gettime(&t);

* * * printf("Uhrzeit: %i:%i:%i\n", t.ti_hour, t.ti_min, t.ti_sec);
* * * sleep(1);
* * * system("CLS");
* *}

* *void Weckzeit()
* *{
* * * printf("Weckzeit: %i:%i:%i\n", WZ_h, WZ_m, WZ_s);
* *}

* *bool klingeln()
* *{
* * * gettime(&t);
* * **
* * * if(WZ_h == t.ti_hour && WZ_m == t.ti_min && WZ_s == t.ti_sec)
* * * {
* * * * *return true;
* * * }
* * * else
* * * {
* * * * *return false;
* * * }
* *}
};
Wichtig ist, dass Uhrzeit() später nach Weckzeit() ausgeführt wird, da sich die sleep()-Methode in Uhrzeit() befindet und man sonst nichts von der Weckzeit mitbekommen würde. Aber das ist auch nicht so wichtig! Das dient uns im Moment nur zur Kontrolle.


So, Weckzeit() ist klar. Gibt einfach nur die 3 Integer auf dem Bildschirm aus. Und Uhrzeit(): Holt sich erst wieder die aktuelle Uhrzeit mit gettime() und gibt sie dann auf dem Bildschirm aus. Daraufhin folgt sleep(). 1 ist der kleinste Wert. sleep() erwartet einen unsignet int , das bedeutet einen Integer ohne Vorzeichen.
Negative Werte sind ausgeschlossen. Was aber viel schlimmer ist: Wir können keine Kommazahlen (double, float) verwenden! Das heißt, manchmal wird der Wecker nicht ausgelöst, wenn sich die sleep() Methode grade an einem unpassenden Zeitpunkt befindet. Ihr werdet es noch beim Test sehen!
Aber das ist nunmal die einfachste Methode und vorerst ausreichend.
Als nächstes wird der Bildschirm gelöscht, damit wir nicht eine endlose Liste von Uhrzeiten haben, wenn wir später jede Sekunde die Uhrzeit aufrufen.


Das wars von der Klasse! Jetzt fehlt uns nurnoch die main()-Funktion! Bei dieser fasse ich mich kurz.

Code:
Code:
void main()
{
* *Wecker meinWecker;

* *int scan_h; * // Zwischenspeicher fuer Eingabe
* *int scan_m;
* *int scan_s;

* *printf("Wecker einstellen: \n");
* *printf("hh: ");
* *scanf("%i", &scan_h);

* *printf("mm:");
* *scanf("%i", &scan_m);

* *printf("ss:");
* *scanf("%i", &scan_s);

* *system("cls");

* *meinWecker.stellen(scan_h, scan_m, scan_s);

* *while(1)
* *{
* * * meinWecker.Weckzeit();
* * * meinWecker.Uhrzeit();

* * * if(meinWecker.klingeln() == true)
* * * {
* * * * *printf("BEEEEEP!");
* * * * *//printf("\a"); * * * * // PC macht einen Beepton
* * * * *break;
* * * }
* *}

* *getch();

* *system("CLS");

* *printf("Programm beenden durch Tastendruck ...");
* *getch();
}
Als erstes rufen wir eine Instanz ins Leben (meinWecker). Dann kommen Zwischenspeichervariablen für den Wecker, da wir mit scanf jede Variable einzeln abfragen.
Das erstpart uns den Stress mit den Doppelpunkten, dass wir nicht noch einen String außeinander nehmen müssen. Dieses Tutorial soll ja nur das Minimum erklären! Die Texte aus den printf()-Methoden dienen nur zur Orientierung des Benutzers. Dann wird der Bildschirm noch mal gelöscht und die Werte an die Klasse übergeben (meinWecker.stellen(...)), bevor's los geht! Und dann kommt die (theoretische) Endlosschleife. Jedoch befindet sich ein break in ihr.
Jetzt werden immer beide Zeiten ausgegeben. Uhr- und Weckzeit. Insgesamt wird dann ca. eine Sekunde gewartet, dann verglichen: Wenn der Vergleich positiv ausfällt, liefert klingeln() true zurück. Und dann kommt es zum Beep und zum Abbruch der while()-Schleife.
Dann noch ein Tastendruck und man wird raus geführt.



Dies war nun mein erstes Tutorial zu C++.
Ich hoffe es hat eic ein wenig geholfen, und wir hoffe das ihr bald richtige programmer werdet

Es folgt bald noch ein 2. Tutorial zu C++, dies ist jedoch nur für die, je dieses Tut verstanden haben.

Mit Freundlichen Grüßen,
_Inv¡sible'_
Monkry is offline  
Thanks
3 Users
Old 06/19/2012, 18:48   #2
 
elite*gold: 0
Join Date: Jun 2012
Posts: 75
Received Thanks: 3
Thumbs up

Cool danke funktioniert Super!!

Freue mich schon auf das nächste tut ^^

MfG
Tuffe is offline  
Old 06/19/2012, 21:33   #3
 
BlackWu's Avatar
 
elite*gold: 4
Join Date: Nov 2008
Posts: 1,189
Received Thanks: 395
Quelle angeben.

btw. Ist das Tutoial nicht das Gelbe vom Ei.
BlackWu is offline  
Reply

Tags
c plus plus, c++, lernen, programmieren, tutorial




All times are GMT +2. The time now is 17:39.


Powered by vBulletin®
Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
SEO by vBSEO ©2011, Crawlability, Inc.
This site is protected by reCAPTCHA and the Google Privacy Policy and Terms of Service apply.

Support | Contact Us | FAQ | Advertising | Privacy Policy | Terms of Service | Abuse
Copyright ©2024 elitepvpers All Rights Reserved.