Fehler in Angabe zur A1

Disclaimer: Dieser Thread wurde aus dem alten Forum importiert. Daher werden eventuell nicht alle Formatierungen richtig angezeigt. Der ursprüngliche Thread beginnt im zweiten Post dieses Threads.

Fehler in Angabe zur A1
Das mit dem Makefile für die Aufgabe 1 war wohl nix… :-p
A1 hängt garnicht von den *.o ab sondern direkt von den *.cpp, dadurch werden die CXXFLAGS garnicht benutzt. Hmm, die src files haben windows zeilenenden… :wink:
Patch:

Index: Makefile
===================================================================
--- Makefile	(Revision 199)
+++ Makefile	(Arbeitskopie)
@@ -1,10 +1,12 @@
 ## Flags
 LD = g++
 CXXFLAGS = -Wall -g -DLINUX
+CXXFLAGS+= -Werror -pedantic
 LFLAGS = 
 
 HEADERS = complex.h matrix.h 
 CPPFILES = main.cpp complex.cpp matrix.cpp 
+OBJECTS = $(CPPFILES:.cpp=.o)
 
 all : A1
 
@@ -14,6 +16,6 @@
 %.o: %.cpp $(HEADERS)
 	g++ $(CXXFLAGS) -c $< -o $@
 
-A1 : ${CPPFILES}
+A1 : $(OBJECTS)
 	$(LD) -o $@ $^ ${LFLAGS}

Der Complex::operator-() darf natürlich keine Referenz zurückgeben (complex.h):

class Complex {
 //...
public:
Complex operator-();
/..
}

Sonst müßte man entweder eine Referenz auf eine lokale Variable zurückgeben oder ein neues Objekt auf dem Heap erzeugen… beides keine wirklich gute idee…


Das “return *this” beim Multiplikationsoperator der Matrix ist wohl auch ein Fehler.


Stimmt, das ist in der Tat ein Fehler. Danke fuer den Hinweis!

        Complex operator-();

Bitte aendert das entsprechend in der Complex.h und Complex.cpp ab. Bei neuen Handins habe ich das ganze angepasst.

Es ist Absicht, dass keine *.o gebildet werden. Dadurch wird naemlich erzwungen, dass matrix.cpp immer mit kompiliert wird. Dein Makefile hat genau das Probelem was dadurch verhindert wird: Wenn du (mit deinem Makefile) in der matrix.cpp eine Aenderung machst wird es nicht neu kompiliert!!!
Die CXXFLAGS werden in der Tat nicht benutzt, was allerdings nicht weiter tragisch ist; wenn ihr Flags verwenden wollt koennt ihr das Makefile natuerlich gerne anpassen. Prinzipell soll das Makefile nur eine kleine Hilfe sein (ich habe das Default Makefile aber geaendert, sodass die Flags mit benutzt werden):

## Flags
LD = g++
CXXFLAGS = -Wall -g -DLINUX
LFLAGS =

HEADERS = complex.h matrix.h
CPPFILES = main.cpp complex.cpp matrix.cpp

all : A1

clean :
        rm -rf A1 *.o

A1 : ${CPPFILES}
        $(LD) $(CXXFLAGS) -o $@ $^ ${LFLAGS}

Die richtige Implementierung muesst ihr natuerlich selbst machen; In der Angabe wird nur „irgendwas“ returned.


Ach ist das so?

$make clean
rm -rf A1 *.o
$ make
g++ -Wall -g -DLINUX -Werror -pedantic -c main.cpp -o main.o
g++ -Wall -g -DLINUX -Werror -pedantic -c complex.cpp -o complex.o
g++ -Wall -g -DLINUX -Werror -pedantic -c matrix.cpp -o matrix.o
g++ -o A1 main.o complex.o matrix.o 
$ touch matrix.cpp 
$ make
g++ -Wall -g -DLINUX -Werror -pedantic -c matrix.cpp -o matrix.o
g++ -o A1 main.o complex.o matrix.o 

A1 hängt ab von matrix.o hängt ab von matrix.cpp. Also wird natürlich matrix.cpp neu kompiliert wenn es verändert wurde.


Bei der Übung lernt man ja dann wenigstens wie man ein gutes Makefile schreibt: man macht einfach alles von allem abhängig. Way to go! :wink: SCNR


Jap es ist so… auch wenn es nicht so aussieht, matrix.cpp wird nicht neu kompiliert…

Die Zeile
g++ -Wall -g -DLINUX -Werror -pedantic -c matrix.cpp -o matrix.o
kompiliert effektiv nichts

Es wird zwar eine .o Datei erstellt, aber die ganzen Funktionen kann er nicht kompilieren, weil er die konkreten Templates noch nicht kennt. Ausfuehrbarer Code wird erst bei Instanziierung erstellt (hier mit der main.cpp).

Der Inhalt von matrix.cpp kompiliert wenn du
g++ -Wall -g -DLINUX -Werror -pedantic -c main.cpp -o main.o
ausfuehrst.

Das wird bei dir beim zweiten mal naemlich nicht mehr gemacht, daher ist dein Makefile schlecht :wink:

Du kannst das Phaenomaen ganz einfach mal testen indem du irgendwas in dein print() in matrix.cpp reinschreibst und dann erneut make machst. Du wirst fesstellen, dass deine Aenderungen nicht realisiert werden.


das scheint dann wohl auch der grund zu sein, warum ich im visual studio nie änderungen, die ich in der matrix.cpp gemacht hab, angezeigt bekommen hab, ausser ich hab was an der main.cpp geändert…


Schätze mal das ist so gewollt, du sollst da schließlich deine eigene Return-Matrix zurückgeben… Und sonst hätten sie gleich einen Fehler im File :wink:

Aber mal was anderes: die main müssen wir ja nicht abgeben… Dürfen wir die dann in „Zusammenarbeit“ erstellen? :smiley:
Hat jemand ein main.cpp? *gggg


Hier haste meine main.cpp (kleiner Test-Case)

Die spielt ein wenig mit der Matrix und vergleicht die Ergebnisse

Der Härtetest mit komplexen Zahlen wurde nicht überprüft, aber müsste so passen…

Attachment:
main.cpp: https://fsi.cs.fau.de/unb-attachments/post_77154/main.cpp


thx, aber bei mir will er nicht downloaden :confused:


Pro-Tipp: man kann im Forum Dateien anhängen.


Habs angehängt^^

//Und aktualisiert


Mal eine kurze Frage: T *data soll ja die Matrix intern repräsentieren.

Hat es einen Grund, dass man da nicht einfach straight forward einen T** nimmt, um damit ein 2D-Array zu bauen?


Beim 2-Dim-Ansatz brauchst du eine for-Schleife, um alle Elemente korrekt mit delete [] freizugeben.


Du hast dich da vertippt :smiley:

Dann würde ziemlich viel rumgebastel entfallen, aber das wäre ja langweilig und viel zu einfach!

PS: danke für die main :wink: hab dadurch entdeckt, dass meine Complex-Multiplikation falsch war xD


2D-Arrays koennen ineffizient werden, daher ist es wohl im Allgemeinen besser 1D Arrays zu verwenden :wink:

Man muesste ja etwas in der Art dann machen:

T** array = new T*[size_x];
for (unsigned int i = 0; i < size_x; i++) {
    array[i] = new T[size_y];
}

Zum einen waeren es dann size_x + 1 Speicherallociierungen (im Gegensatz zu einer einzigen) und zum anderen kann es passieren die ganzen Subarrays wild verstreut im Speicher liegen. Das waere wiederrum fuer Cachingeffekte schlecht.


Ah, OK, ich war erst bei der Complex-Klasse und mir war nicht klar, dass Matrix eine Template-Klasse ist.
Aber man kann es „richtig“ machen, in dem man Abhängigkeiten angibt oder sie vom gcc generieren läßt (GNU make Manual: 4.14 Generating Prerequisites Automatically).

Index: Makefile
===================================================================
--- Makefile	(Revision 199)
+++ Makefile	(Arbeitskopie)
@@ -1,10 +1,12 @@
 ## Flags
 LD = g++
 CXXFLAGS = -Wall -g -DLINUX
+CXXFLAGS+= -Werror -pedantic
 LFLAGS = 
 
 HEADERS = complex.h matrix.h 
 CPPFILES = main.cpp complex.cpp matrix.cpp 
+OBJECTS = $(CPPFILES:.cpp=.o)
 
 all : A1
 
@@ -14,6 +16,10 @@
 %.o: %.cpp $(HEADERS)
 	g++ $(CXXFLAGS) -c $< -o $@
 
-A1 : ${CPPFILES}
+A1 : $(OBJECTS)
 	$(LD) -o $@ $^ ${LFLAGS}
 
+main.o: main.cpp complex.h matrix.cpp matrix.h
+matrix.o: matrix.h matrix.cpp
+complex.o: complex.h complex.cpp

Test:

$ make
make: Für das Ziel »all« ist nichts zu tun.
$ touch matrix.cpp 
$ make
g++ -Wall -g -DLINUX -Werror -pedantic -c main.cpp -o main.o
g++ -Wall -g -DLINUX -Werror -pedantic -c matrix.cpp -o matrix.o
g++ -o A1 main.o complex.o matrix.o 
$

Das matrix.o Target braucht man dann eigentlich garnicht… sollte matrix.cpp dann nicht eingentlich ein Header sein? z.B. matrix_cpp.h


Als ob die Realisierung mit einem 1dim Array schwer wäre :wink:


Danke fuer die ausfuehrliche Antwort :wink: