1. Prog. zu Funktionen
-
Lerne frühzeitig, mit dem Debugger umzugehen. Dann findest du solche Fehler in < 1 Minute (mit anschließendem *kopfklatsch*
).
-
NekoHiTsuna schrieb:
thihihi, dankeschön, jetzt geht es

Wusste nicht dass man die Funktion erst zu einem gewissen Zeitpunkt aufrufen darf
Dein Programm läuft sequentiell. Eine Zeile nach der anderen wird abgearbeitet. Wenn du eine Funktion aufrufst und ihr Werte übergibst, arbeitet sie selbstverständlich mit diesen Werten. Nicht mit Werten, die du eventuell irgendwann später im Programm noch erzeugst. In deinem Fall übergibst du der Funktion ermitteln ausschließich Nullen. Und damit rechnet sie dann nun mal.
-
NekoHiTsuna schrieb:
thihihi, dankeschön, jetzt geht es

Wusste nicht dass man die Funktion erst zu einem gewissen Zeitpunkt aufrufen darf
Welche Werte soll er denn für die Funktionsparameter annehemen?
Die Namen der Variablen sind Schall und Rauch.
Der Prototyp braucht die Namen noch nicht einmal:int ermitteln (int, int, int, int); //Geht auch // Nur dann weißt du nicht mehr wofür die Parameter stehen :-(Da kannst du auch direkt Zahlenwerte einsetzten.
-
hm, ja ok Danke

ja hatte halt gedacht dass das bei Funktionen übertragen anders ist... naja hinterher ist mal immer schlauer, aus Fehlern lernt man

-
DirkB schrieb:
NekoHiTsuna schrieb:
thihihi, dankeschön, jetzt geht es

Wusste nicht dass man die Funktion erst zu einem gewissen Zeitpunkt aufrufen darf
Welche Werte soll er denn für die Funktionsparameter annehemen?
Die Namen der Variablen sind Schall und Rauch.
Der Prototyp braucht die Namen noch nicht einmal:int ermitteln (int, int, int, int); //Geht auch // Nur dann weißt du nicht mehr wofür die Parameter stehen :-(Da kannst du auch direkt Zahlenwerte einsetzten.
hmmm? meinst du also dass ich nach int gleich die zahl setzen könnte?

aber dann ist dass doch gar nicht für die variable definiert... oder? *verwirrt sei*
-
Nee, beim Funktionsaufruf kannst du Zahlenwerte einsetzen:
//z.B.Rest = ermitteln (Schaden, HP, 0, Hits); // den 3. Parameter nutzt du in der Funktion eh nicht.oder
Rest = ermitteln (100, 100000, 0, 2);War schlecht formuliert

-
DirkB schrieb:
Nee, beim Funktionsaufruf kannst du Zahlenwerte einsetzen:
//z.B.Rest = ermitteln (Schaden, HP, 0, Hits); // den 3. Parameter nutzt du in der Funktion eh nicht.oder
Rest = ermitteln (100, 100000, 0, 2);War schlecht formuliert

hm, ist mir noch ein klein wenig unklar (klingt für mich noch unlogisch)
aber trotzdem danke für deine antwort
ich werde dann mal mein buch weiterlesen, mal schauen was da jetzt noch alles zu diesem thema kommt
-
NekoHiTsuna schrieb:
DirkB schrieb:
Nee, beim Funktionsaufruf kannst du Zahlenwerte einsetzen:
//z.B.Rest = ermitteln (Schaden, HP, 0, Hits); // den 3. Parameter nutzt du in der Funktion eh nicht.oder
Rest = ermitteln (100, 100000, 0, 2);War schlecht formuliert

hm, ist mir noch ein klein wenig unklar (klingt für mich noch unlogisch)
aber trotzdem danke für deine antwort
ich werde dann mal mein buch weiterlesen, mal schauen was da jetzt noch alles zu diesem thema kommt
jetzt verstehe ich was du meinst nachdem ich weitergelesen habe

... es wird dann erklärt dass es genügt den datentyp reinzuschreiben aber die reihenfolge sollte man einhalten (die reihenfolge der datentypen vor dem aufrufen der funktion)deswegen ist es übersichtlicher dann noch einen name dazuzuschreiben, aber nötig ist es nicht
wenn ich das so richtig verstanden habe

-
Kennst du Funktionen aus dem Mathe-Unterricht? So f(x)=y und so? Unsere Funktionen sind gar nicht unähnlich. Die wollen irgendwelche Werte übergeben bekommen (x) und spucken dafür einen Rückgabewert aus (y). Woher der Übergabewert x kommt, ist egal. Ob du jetzt direkt eine 3 übergibst, oder ob du eine Variable übergibst, die den Wert 3 hat, kommt für die Funktion aufs Gleiche raus.
-
hm, achso.
mal was anderes nebenbei: habe gerade ein beispiel gehabt wo es um Stack geht...
naja schaut auch am besten mal das programm an, dann wisst ihr was ich meine, ich verstehe halt nicht wieso es gleich bleibt://Funktion intern: Der Stack #include <iostream> using namespace std; void erhoehePunkte (int Punkte); //Hauptprogramm int main () { //Variablen int Punkte = 1000; //Punkte cout << "Punkte vor Funktionsaufruf :" << Punkte << endl; erhoehePunkte (Punkte); cout << "Punkte nach Funktionsaufruf: " << Punkte << endl; system ("PAUSE"); return 0; } //erhoehe Punkte void erhoehePunkte (int Punkte) { Punkte+=100; }
-
_matze schrieb:
Kennst du Funktionen aus dem Mathe-Unterricht? So f(x)=y und so? Unsere Funktionen sind gar nicht unähnlich. Die wollen irgendwelche Werte übergeben bekommen (x) und spucken dafür einen Rückgabewert aus (y). Woher der Übergabewert x kommt, ist egal. Ob du jetzt direkt eine 3 übergibst, oder ob du eine Variable übergibst, die den Wert 3 hat, kommt für die Funktion aufs Gleiche raus.
Naja, die andere Auffassung ist im Matheunterricht aber auch nicht unverbreitet. Es geht hier um den Unterschied zwischen strict evaluation und non-strict evaluation. Beides sind berechtige Ansichten zum Nutzen von Funktionen und beides findet man sowohl im Alltagsgebrauch als auch in verschiedenen Programmiersprachen. C++ nutzt strict evaluation, der Threadersteller geht von lazy evaluation aus. Das geht natürlich nicht gut.
Ein typisches Beispiel für eine Sprache mit lazy evaluation ist der C-Präprozessor:
#define X 1 #define Y 2 #define foo X + Y #undef X #undef Y #define X 4 #define Y 6 foo // 4 + 6edit: Zumindest die Ursprungfrage hatte dieses Problem. Weiteres Lesen des Threads lässt mich vermuten, dass da noch mehr falsche Vorstellungen sind.
-
Die Variable "Punkte" in "erhoehePunkte" ist eine andere Variable als "Punkte" in "main" - die beiden heißen nur gleich.
Vergleich: Du hast zwei Mülleimer. Einen in der Küche und einen im Keller. Wenn du etwas in den Mülleiner in der Küche reinwirfst, verändert sich der Mülleimer im Keller nicht.
Das Zauberwort heißt hier "Call-by-value" vs. "Call-by-reference". Danach kannst du ja mal googlen...
-
die zahl 1000 von Punkte wurde ja dennoch an die funktion übertragen...und... hmmm...

*jumping out the basement-window*
edit: sehe gerade bei http://blog.gungfu.de/archives/2005/07/05/der-unterschied-zwischen-call-by-value-und-call-by-reference/ dass dort steht dass eine kopie übertragen wird aber x nicht verändert wird. also Punkte=Punkte*100, "die veränderung ist nicht sichtbar innerhalb einer methode" so stand es da ca.. und Punkte bleibt? oder wie ist das zu verstehen... ~bei int & punkte ist es ja sichtbar~ (seid geduldig mit mir, ich brauche immer meine zeit bis ich was verstehe
)
-
#include <iostream> void func1(int i) { i=2; //i ist eine lokale Kopie des übergebenen Wertes. } void func2(int& i) { i=2; //i ist eine Referenz auf die übergebene Variable } int main() { int test=1; func1(test); //Übergabe by-value std::cout << test; //test ist immer noch 1 func2(test); //Übergabe by-reference std::cout << test; //test ist nun 2 }
-
wann kommen diese 2 varianten denn zum einsatz?
-
NekoHiTsuna schrieb:
wann kommen diese 2 varianten denn zum einsatz?
Na ja, call-by-value ist quasi der Standard. call-by-reference nimmst du immer dann, wenn du einen Grund dazu hast. Beispiel: du willst eine Funktion schreiben, die die Werte zweier int-Variablen vertauscht. Hier bietet sich call-by-reference an:
void swap(int& a, int& b) { int temp=a; a=b; b=temp; }
-
Sobald du Abstrakte Datentypen (ADT) benutzt (kommt später denke ich mal) möchtest du nicht jedesmal das komplette Objekt kopieren, deshalb ist es dort auch in etwa 95% der Fälle ein Call-Per-Referenz.
Zum lazy-Evaluation: Haskell ist auch ein typisches Beispiel. Streng genommen benutzt der Präprozessor nicht lazy-Evaluation, weil das ist definiert durch leftmost-outermost-Graphreduction, und letzteres ist dabei nicht erfüllt

-
_matze schrieb:
Na ja, call-by-value ist quasi der Standard.
Bei den eingebauten Datentypen vielleicht. Größere Objekte sollen standardmäßig als const Referenz übergeben werden.
-
ich sag jetzt einfach mal ok xD
naja, erstmal vielen dank für die ganzen antworten

-
Hast du dich denn entscheiden können?