Klasse, Struktur, Schoblonen, Funktionen?
-
Guten Tag.
Ich habe vor ein Programm über Matrizenrechnung zu schreiben (Invertieren, Determinate, Multiplikation, Adjungierte Matrix, u.v.m berechnen). Die Algorithmen sind mir klar, da ich Mathe studiere, doch allerdings fehlt mir die Idee bei der Programmierung.
Mein Einfall ist es eine Klasse zu schreiben, mit Variablen für Breite und Höhe der Matrix und ein 2-dimensionales Feld für die Elemente.
Mit geeigneten Methoden lässt sich leicht die Determinante (zum Beispiel) berechnen.Mein Problem ist jetzt aber, wie ich Operationen mit 2 Matrizen ausführen kann, also zum Beispiel die Multiplikation. Kann man 2 Exemplare von Klassen als Funktionsparameter nehmen und einen als Rückgabewert? Wenn ich mich richtig erinnere ging das irgendwie nur mit Pointern oder irre ich mich da?
Das nächste Problem ist, dass ich das ganze irgendwie in eine .h-Datei (oder in irgendein externes Modul) reinpacken möchte, so etwas habe ich allerdings noch nie gemacht und weiß nicht, wie ich das anstellen könnte.
Wäre nett, wenn mir jemand bei dem Problem helfen könnte, oder mir nützliche Links schicken könnte.
Ich kenne leider den Fachausdruck für dieses Problem mit den .h-Dateien nicht, sonst würd ich ja selber rumgoogeln.Schonmal Vielen Dank für jede Bemühung eurerseits.
Gruß
Max
-
Hi...
Max3000 schrieb:
Mein Problem ist jetzt aber, wie ich Operationen mit 2 Matrizen ausführen kann, also zum Beispiel die Multiplikation. Kann man 2 Exemplare von Klassen als Funktionsparameter nehmen und einen als Rückgabewert? Wenn ich mich richtig erinnere ging das irgendwie nur mit Pointern oder irre ich mich da?
Das geht ganz einfach. Du kannst den operator* für deine Klasse überladen, sodass du sowas machen kannst:
Matrix a,b; // ... Matrix c = a*b;Das überladen sieht dann so aus:
const Matrix operator*(const Matrix& a, const Matrix& b) { Matrix res; // res.bla(a.f()*b.f()); etc. : Berechnen und in Matrix schreiben return res; }Max3000 schrieb:
Das nächste Problem ist, dass ich das ganze irgendwie in eine .h-Datei (oder in irgendein externes Modul) reinpacken möchte, so etwas habe ich allerdings noch nie gemacht und weiß nicht, wie ich das anstellen könnte.
Du willst wahrscheinlich Implementation und Schnittstelle trennen

Dafür schreibst du deine Klassendeklaration in eine .h ( Header ) - Datei:#ifndef _MATRIX_ #define _MATRIX class Matrix { ... }; #endifUnd definierst sie dann in einer .cpp:
#include "matrix.h" Matrix::Matrix() { ... } void Matrix::bla(...) { }Jenachdem welche Entwicklungsumgebung du nutzt, wird alles zusammengelinkt und *tataa*
-
Max3000 schrieb:
Guten Tag.
....
Mein Problem ist jetzt aber, wie ich Operationen mit 2 Matrizen ausführen kann, also zum Beispiel die Multiplikation. Kann man 2 Exemplare von Klassen als Funktionsparameter nehmen und einen als Rückgabewert? Wenn ich mich richtig erinnere ging das irgendwie nur mit Pointern oder irre ich mich da?Das nächste Problem ist, dass ich das ganze irgendwie in eine .h-Datei (oder in irgendein externes Modul) reinpacken möchte, so etwas habe ich allerdings noch nie gemacht und weiß nicht, wie ich das anstellen könnte.
Wäre nett, wenn mir jemand bei dem Problem helfen könnte, oder mir nützliche Links schicken könnte.
...Das Überladen wird hier erklärt:
http://www.oop-mit-cpp.de/kap9.pdfBeispiel mit Matrizen (die ihrerseits auf Vektoren basieren):
http://www.oop-mit-cpp.de/cppbuch/k11/matrix/
Gruß!
-
Hallo nochmal.
Ich habe jetzt mal angefangen die Klasse zu schreiben und bekomme beim Compilieren schon 14 Fehler, die eigentlich total unlogisch sind.
Ich schick einfach mal meinen Code:matrix.h:
#ifndef _MATRIX_ #define _MATRIX class matrix { private: int m, n; float *elements; public: char name[3]; bool init(int k, int l); ~matrix(void); int errcode; }; #endifmatrix.cpp:
#include "matrix.h" bool matrix::init(int k, int l) { if((k>0) && (l>0)) { if ((k<10) && (l<10)) { matrix.m=k; matrix.n=l; matrix.elements = (float*)malloc(sizeof(float)*k*l); matrix.errcode = 0; return true; }else{ matrix.errcode = 2; }; }else{ matrix.errcode = 1; }; return false; } matrix::~matrix(void) { free(matrix.elements); }Und die Fehlermeldung:
--------------------Configuration: Matrizen - Win32 Debug--------------------
Compiling...
matrix.cpp
c:\dokumente und einstellungen\max\eigene dateien\c++\matrizen\matrix.cpp(9) : error C2143: syntax error : missing ';' before '.'
c:\dokumente und einstellungen\max\eigene dateien\c++\matrizen\matrix.cpp(9) : error C2143: syntax error : missing ';' before '.'
c:\dokumente und einstellungen\max\eigene dateien\c++\matrizen\matrix.cpp(10) : error C2143: syntax error : missing ';' before '.'
c:\dokumente und einstellungen\max\eigene dateien\c++\matrizen\matrix.cpp(10) : error C2143: syntax error : missing ';' before '.'
c:\dokumente und einstellungen\max\eigene dateien\c++\matrizen\matrix.cpp(11) : error C2143: syntax error : missing ';' before '.'
c:\dokumente und einstellungen\max\eigene dateien\c++\matrizen\matrix.cpp(11) : error C2143: syntax error : missing ';' before '.'
c:\dokumente und einstellungen\max\eigene dateien\c++\matrizen\matrix.cpp(12) : error C2143: syntax error : missing ';' before '.'
c:\dokumente und einstellungen\max\eigene dateien\c++\matrizen\matrix.cpp(12) : error C2143: syntax error : missing ';' before '.'
c:\dokumente und einstellungen\max\eigene dateien\c++\matrizen\matrix.cpp(15) : error C2143: syntax error : missing ';' before '.'
c:\dokumente und einstellungen\max\eigene dateien\c++\matrizen\matrix.cpp(15) : error C2143: syntax error : missing ';' before '.'
c:\dokumente und einstellungen\max\eigene dateien\c++\matrizen\matrix.cpp(18) : error C2143: syntax error : missing ';' before '.'
c:\dokumente und einstellungen\max\eigene dateien\c++\matrizen\matrix.cpp(18) : error C2143: syntax error : missing ';' before '.'
c:\dokumente und einstellungen\max\eigene dateien\c++\matrizen\matrix.cpp(25) : error C2065: 'free' : undeclared identifier
c:\dokumente und einstellungen\max\eigene dateien\c++\matrizen\matrix.cpp(25) : error C2275: 'matrix' : illegal use of this type as an expression
Main.cpp
c:\dokumente und einstellungen\max\eigene dateien\c++\matrizen\main.cpp(98) : warning C4700: local variable 'hButtonCreate' used without having been initialized
Error executing cl.exe.Matrizen.exe - 14 error(s), 1 warning(s)
Hat da jemand eine Ahnung, was da falsch sein kann?
Muss ich da vielleicht nochwas im Compiler linken?
Wenn ja bitte ins Compilerforum verschieben.
Ich benutze MS VC++ 6.0 Professional.Danke
Gruß Max
-
Max3000 schrieb:
Hallo nochmal.
#ifndef _MATRIX_ #define _MATRIXDer "Einschlusswächter"(*) stimmt nicht:
#define _MATRIX_ist glaube ich eher das was Du meinst.
Grüsse
*this
P.S.: (*) "Inclusion-Guard" klingt irgendwie besser

-
Hab das _ irgendwie verloren
Zudem sprichst du alle deine Elemente mit matrix. an. Das matrix. muss davor weg 
-
Danke.
Ich habe aber den Hauptfehler eben gefunden.
Bei den Methoden muss ich doch nicht nochmal matrix:: vor jede Variable schreiben.Ihr könnt mich jetzt hier ruhig aufs Übelste beschimpfen.
Ich habs verdient.Grüße
Max
-
Sorry, aber ich hab doch noch einmal eine Frage:
Beim Compilieren meldet sich jedesmal der Debugger mit dem Fehler:
User breakpoint called from code at 0xa66775Im Output Fenster steht:
First-chance exception in Matrizen.exe (45AD9FCA.DLL): 0xC0000005: Access Violation.Und es wird ein ewig langer Text geladen mit einer Markierung an folgender Zeile:
00A66775 int 3Genauer kann ich das Problem leider nicht beschreiben.
Hier nochmal mein ganzer Code:
# include <windows.h> # include "matrix.h" TCHAR szAppName[] = TEXT("Matrizen"); LRESULT CALLBACK WndProc (HWND, UINT, WPARAM, LPARAM); int WINAPI WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpszCmdLine, int iCmdShow) { HWND hwnd; WNDCLASS wndclass; MSG msg; wndclass.style = CS_HREDRAW| CS_VREDRAW; wndclass.cbClsExtra = 0; wndclass.cbWndExtra = 0; wndclass.lpfnWndProc = WndProc; wndclass.hInstance = hInstance; wndclass.hCursor = LoadCursor(NULL, IDC_ARROW); wndclass.hIcon = LoadIcon(NULL, IDI_APPLICATION); wndclass.lpszMenuName = (NULL); wndclass.lpszClassName = szAppName; wndclass.hbrBackground = (HBRUSH) GetStockObject (WHITE_BRUSH); if(!RegisterClass(&wndclass)) { MessageBox(NULL, TEXT("Fehler: Programm setzt Unicode voraus."), szAppName, MB_ICONERROR); return 0; }; hwnd = CreateWindow (szAppName, szAppName, WS_CAPTION | WS_THICKFRAME | WS_OVERLAPPED | WS_MINIMIZEBOX | WS_SYSMENU, 100, 100, 500, 500, NULL, NULL, hInstance, NULL); ShowWindow(hwnd, iCmdShow); UpdateWindow(hwnd); while(GetMessage(&msg, NULL, 0, 0)) { TranslateMessage(&msg); DispatchMessage(&msg); }; return msg.wParam; }; LRESULT CALLBACK WndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) { HWND hEditM, hEditN, hButtonCreate, hGroupAdd; HDC hdc; PAINTSTRUCT ps; matrix m1; switch(message){ case WM_PAINT: hdc = BeginPaint(hwnd, &ps); TextOut(hdc, 50, 35, TEXT("Dimension:"),10); TextOut(hdc, 215, 35, TEXT("x"), 1); EndPaint(hwnd, &ps); return 0; case WM_CREATE: hButtonCreate = CreateWindow (TEXT("button"), TEXT("Matrix erstellen"), WS_CHILD | WS_VISIBLE | BS_PUSHBUTTON, 330, 30, 130, 30, hwnd, NULL, ((LPCREATESTRUCT) lParam)->hInstance, NULL); hGroupAdd = CreateWindow (TEXT("button"), TEXT("Neue Matrix hinzufügen"), WS_CHILD | WS_VISIBLE | BS_GROUPBOX, 20, 10, 460, 60, hwnd, NULL, ((LPCREATESTRUCT) lParam)->hInstance, NULL); hEditM = CreateWindow (TEXT("edit"), NULL, WS_CHILD | WS_BORDER | WS_VISIBLE | ES_CENTER, 150, 35, 40, 20, hwnd, NULL, ((LPCREATESTRUCT) lParam)->hInstance, NULL); hEditN = CreateWindow (TEXT("edit"), NULL, WS_CHILD | WS_BORDER | WS_VISIBLE | ES_CENTER, 250, 35, 40, 20, hwnd, NULL, ((LPCREATESTRUCT) lParam)->hInstance, NULL); return 0; case WM_DESTROY: PostQuitMessage (0); return 0; case WM_COMMAND: if(LOWORD(wParam)==GetWindowLong (hButtonCreate, GWL_ID) && HIWORD(wParam)==BN_CLICKED) MessageBox(hwnd, TEXT("Geht!"), szAppName, NULL); return 0; }; return DefWindowProc(hwnd, message, wParam, lParam); };matrix.h
#ifndef _MATRIX_H_ #define _MATRIX_H_ class matrix { private: int m, n; float *elements; public: char name[3]; bool init(int k, int l); ~matrix(void); int errcode; }; #endifmatrix.cpp
#include <iostream> #include "matrix.h" using namespace std; bool matrix::init(int k, int l) { if((k>0) && (l>0)) { if ((k<10) && (l<10)) { m=k; n=l; elements = (float*)calloc(l*k+1,sizeof(float)); errcode = 0; return true; }else{ errcode = 2; }; }else{ errcode = 1; }; return false; }; matrix::~matrix(void) { free(elements); };In welcher Zeile der Fehler ist, steht leider nicht dabei.
Die main.cpp muss aber richtig sein, die hat schonmal geklappt bevor ich die Klasse eingefügt habe.Gruß
Max
-
Obs daran liegt weisz ich nicht, aber was willst du mit
elements = (float*)calloc(l*k+1,sizeof(float));anstatt die C++ Mittel new und delete zu nutzen.
Ergo sowas wieelements=new float(l*k+1);oder so ähnlich. Im Destruktor dann statt free eben delete aufrufen.
Vielleicht lieg ich auch daneben.
Auszerdem: die ; nach den } können überall weg auszer nach Deklaration einer Klasse, Struct, enum usw. Also nach allen if Blöcken und Funktionen z.B.
-
Erstmal: Das was Shinja gesagt hat, solltest du befolgen.
Zeitens: Der Fehler kommt davon das du in deinem Code deine matrix erzeugst (m1) und am Ende des Blocks der Destruktor vom Matrix aufgerufen wird.Da wird natürlich free aufgerufen, aber ... du hast nie init() aufgerufen und somit zeigt dein float *elements keine Ahnung wo hin.
Dein init sollte lieber nen Konstrukor sein, womit alle Elemente erstmals initialisert werden...
Edit: Sehe gerade das dein init() false oder true zurückgibt, das kannst du natürlich im Konstruktor nicht machen. Würde dir dann empfehlen dein *element im Konstruktor auf 0 zu setzen und dein init() zu behalten. Wenn du niemals init() aufrufen solltest, ist das nicht schlimm. Ein delete auf ein Nullzeiger macht nichts, wie das bei free ist weiß ich nicht ...
-
Erstmal Danke.
Ich hab jetzt alles geändert und die Klasse funktioniert soweit erst einmal.Jetzt will ich aber für jedes Element ein Editfenster erzeugen und hab auch wieder einen Pointer auf das Handle gelegt und versucht mit new zu allokieren.
Allerdings stürzt dann das Programm ab, wenn ich damit arbeite (zumindest nur manchmal, wenn ich grad neugestartet habe nicht). Außerdem stürzt das Programm auch ab, wenn ich es schließe. Hat jemand eine Idee, was ich da falsch gemacht habe.Ich schicke mal meine Main.cpp:
# include <windows.h> # include <iostream.h> # include "matrix.h" TCHAR szAppName[] = TEXT("Matrizen"); LRESULT CALLBACK WndProc (HWND, UINT, WPARAM, LPARAM); int WINAPI WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpszCmdLine, int iCmdShow) { HWND hwnd; WNDCLASS wndclass; MSG msg; wndclass.style = CS_HREDRAW| CS_VREDRAW; wndclass.cbClsExtra = 0; wndclass.cbWndExtra = 0; wndclass.lpfnWndProc = WndProc; wndclass.hInstance = hInstance; wndclass.hCursor = LoadCursor(NULL, IDC_ARROW); wndclass.hIcon = LoadIcon(NULL, IDI_APPLICATION); wndclass.lpszMenuName = (NULL); wndclass.lpszClassName = szAppName; wndclass.hbrBackground = (HBRUSH) GetStockObject (WHITE_BRUSH); if(!RegisterClass(&wndclass)) { MessageBox(NULL, TEXT("Fehler: Programm setzt Unicode voraus."), szAppName, MB_ICONERROR); return 0; }; hwnd = CreateWindow (szAppName, szAppName, WS_CAPTION | WS_THICKFRAME | WS_OVERLAPPED | WS_MINIMIZEBOX | WS_SYSMENU, 100, 100, 500, 500, NULL, NULL, hInstance, NULL); ShowWindow(hwnd, iCmdShow); UpdateWindow(hwnd); while(GetMessage(&msg, NULL, 0, 0)) { TranslateMessage(&msg); DispatchMessage(&msg); }; return msg.wParam; }; LRESULT CALLBACK WndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) { HWND hEditM, hEditN, hButtonCreate, hGroupAdd; HWND *hEditElements; HDC hdc; PAINTSTRUCT ps; //matrix *mat; int ctr=0; int m, n, i, j; switch(message){ case WM_PAINT: hdc = BeginPaint(hwnd, &ps); TextOut(hdc, 50, 35, TEXT("Dimension:"),10); TextOut(hdc, 215, 35, TEXT("x"), 1); EndPaint(hwnd, &ps); return 0; case WM_CREATE: hButtonCreate = CreateWindow (TEXT("button"), TEXT("Matrix erstellen"), WS_CHILD | WS_VISIBLE | BS_PUSHBUTTON, 330, 30, 130, 30, hwnd, NULL, ((LPCREATESTRUCT) lParam)->hInstance, NULL); hGroupAdd = CreateWindow (TEXT("button"), TEXT("Neue Matrix hinzufügen"), WS_CHILD | WS_VISIBLE | BS_GROUPBOX, 20, 10, 460, 60, hwnd, NULL, ((LPCREATESTRUCT) lParam)->hInstance, NULL); hEditM = CreateWindow (TEXT("edit"), NULL, WS_CHILD | WS_BORDER | WS_VISIBLE | ES_CENTER, 150, 35, 40, 20, hwnd, NULL, ((LPCREATESTRUCT) lParam)->hInstance, NULL); hEditN = CreateWindow (TEXT("edit"), NULL, WS_CHILD | WS_BORDER | WS_VISIBLE | ES_CENTER, 250, 35, 40, 20, hwnd, NULL, ((LPCREATESTRUCT) lParam)->hInstance, NULL); return 0; case WM_DESTROY: delete[] hEditElements; PostQuitMessage (0); return 0; case WM_COMMAND: if(LOWORD(wParam)==GetWindowLong (hButtonCreate, GWL_ID) && HIWORD(wParam)==BN_CLICKED) { //Hier kommt der Fehler ctr++; m=3;//hEditM n=3;//hEditN hEditElements = new HWND[m*n]; MessageBox(hwnd, TEXT("Bis hierhin geht das noch"), szAppName, NULL); for(i=0;i<=m-1;i++){ for(j=0;j<=n-1;j++) { hEditElements[i*n+j] = CreateWindow ("edit", NULL, WS_CHILD | WS_BORDER | ES_CENTER | WS_VISIBLE, 20+80*i, 180+30*j, 70, 20, hwnd, NULL, ((LPCREATESTRUCT) lParam)->hInstance, NULL); }; }; }; return 0; case WM_CLOSE: delete []hEditElements; return 0; }; return DefWindowProc(hwnd, message, wParam, lParam); };Geht sowas mit dem Datentyp HWND nicht?
Ist es eine Fehlerbedingung wenn ich ein Feld deallokiere, wenn er nicht einmal allokiert ist?Bitte helft mir.
Gruß
Max