erste funtion geht nicht



  • warum geht das nicht?

    #include<iostream>
    using namespace std;
    
    int main()
    
    {
    	int fak(int);
    }
    
    	int fak(int zahl)
    	{
    		cout<<"Bitte Zahl die zu \"fakultieren\" ist eingeben: "<<endl;
    		int zahl;
    		cin>>zahl;
    		if (zahl <= 1) return 1;
    		zahl = zahl * fak(zahl-1);
    		cout<<"ergebnis: "<<fak(zahl)<<endl
    	}
    

    so würde doch in main die funktion fak aufgerufen...in der dann alles gemacht wird (mit ein und ausgabe)

    fehler ist aber:
    :14: error: declaration of ‘int zahl’ shadows a parameter
    :19: error: expected `;' before ‘}’ token
    🙂

    klasse das das hier so schnell und nett ist mit den antworten... ich wuerde sonst bei dan anfängen echt verzweifeln.



  • Weil du dein Programm falsch aufgeteilt hast - und damit den praktischen Nutzen der Funktion aus den Angeln hebst. Schau dir doch mal die Codes an, die wir schon als Antwort gepostet haben, und vergleich sie mit deinem Code.



  • Das liegt ganz einfach daran das wenn der Compiler in Zeile 7 ankommt, er noch nicht was weiß fak ist.



  • latenite schrieb:

    so würde doch in main die funktion fak aufgerufen...in der dann alles gemacht wird (mit ein und ausgabe)

    Nein, nicht aufgerufen. Das ist eine Deklaration der Funktion fak. Und selbst wenn du sie aufrufen würdest, würde das ganze nicht viel Sinn ergeben.

    Ohne dir zu nahe treten zu wollen, aber es hat nicht viel Sinn ohne jedes Verständnis irgendwelche fremden Funktionen in das Programm reinzufrickeln und solange zu fummeln bis es compiliert. Schon gar keine rekursiven Funktionen.

    Mein Vorschlag sind ungefähr folgende Schritte:

    1. Benutze Funktionen aus der Standardbibliothek, beispielsweise Ein/Ausgabe- oder mathematische Funktionen.
    2. Schreibe eine einfache Funktion, die z.B. einfach den übergebenen Wert quadriert und zurückgibt.
    3. irgendwas komplexeres


  • hmm irgendwie sehe ich den fehler nicht.

    ich möchte in der main einfach eine funktion aufrufen, die ich dann vielleciht noch in eine headerdatei auslagere.
    Also es sollen alle ein und ausgaben in der funktion stattfinden, nicht in der main.

    wie mache ich das?



  • latenite schrieb:

    hmm irgendwie sehe ich den fehler nicht.

    ich möchte in der main einfach eine funktion aufrufen, die ich dann vielleciht noch in eine headerdatei auslagere.
    Also es sollen alle ein und ausgaben in der funktion stattfinden, nicht in der main.

    wie mache ich das?

    Schau Dir das Beispiel von CStoll an. Bei Dir ist der Code völlig anders angeordnet. Ansonsten schließe ich mich dem Rat von Bashar an.



  • So wie die beiden oberen Codebeispiele zeigen.

    Deines geht nicht weil die Deklaration der Funktion NACH dem Aufruf im Code steht. Sie muss davor stehen (oder eben in einer Header-Datei bzw dessen Source-Datei etc.). Nur weiß der Compiler eben nicht was fak ist, wenn du sie "zuerst" aufrufst und die Deklaration dahinter ist. Er schaut nicht weiter, ist ja nicht Java. 😉



  • Fellhuhn schrieb:

    So wie die beiden oberen Codebeispiele zeigen.

    Deines geht nicht weil die Deklaration der Funktion NACH dem Aufruf im Code steht. Sie muss davor stehen (oder eben in einer Header-Datei bzw dessen Source-Datei etc.). Nur weiß der Compiler eben nicht was fak ist, wenn du sie "zuerst" aufrufst und die Deklaration dahinter ist. Er schaut nicht weiter, ist ja nicht Java. 😉

    erm, meines Erachtens nach, gibt es in diesem Progrämmchen keinen Funktionsaufruf von fak() ^^



  • ok habwegs verstanden...
    aber was wenn ich nun die funktion fakultaet(sammt ein uns ausgabe) in einen header packe? Und dann in der main nur noch aufrufe..also so:

    #include<iostream>
    #include"./fakultaet.h"
    using namespace std;
    
    int main()
    {
    	int fakultaet(int);
    }
    

    und als header

    #include<iostream>
    using namespace std;
    
    int fakultaet(int)
    {
    	cout<<"Bitte Zahl die zu \"fakultieren\" ist eingeben: "<<endl;
    	int zahl;
    	cin>>zahl;
    	if (zahl <= 1)
    	{
    		cout<<"ergebnis: "<<zahl<<endl;
    	}
    	zahl = zahl * fakultaet(zahl-1);
    }
    

    warum geht das dann nicht?wie muss es richtig aussehen als header?



  • latenite schrieb:

    ok habwegs verstanden...

    Aber leider auch nur halbwegs...

    latenite schrieb:

    aber was wenn ich nun die funktion fakultaet(sammt ein uns ausgabe) in einen header packe? Und dann in der main nur noch aufrufe..also so:

    Ich würde Berechnungen immer von der Eingabe trennen (nehmen wir einmal an, du steigst von der Konsolenprogrammierung irgendwann auf die Windowsprogrammierung um, dann kannst du deine Funktion weiterhin nutzen ohne Änderung - Deine Funktion ist aber an die Konsole "verdrahtet").

    latenite schrieb:

    #include<iostream>
    #include"./fakultaet.h"
    using namespace std;
    
    int main()
    {
    	int fakultaet(int);
    }
    

    Hier die ersten Fehler / Anmerkungen:
    a) Man includiert nur das was man in der entsprechenden Datei braucht. Du benutzt in der main aber nicht <iostream>.
    b) #include"./fakultaet.h" - Ich würde das "./" weglassen...
    c) "int fakultaet(int);" ist eine Funktionsdeklaration, kein Aufruf.
    d) Da du die Ein- und Ausgabe in der "fakultaet"-Funktion machst, wäre aber auch schon die Signatur der Deklaration verkehrt:

    Deklaration:
    1. Du gibst nichts zurück, also Rückgabetyp "void"
    2. Du übergibst nichts an fakultaet, also kein Parameter (das drückt man entweder durch eine leere Parameterliste "()" oder durch "(void)" aus)

    Die richtige Deklaration wie du es gemacht hast wäre also "void fakultaet()".
    Dies ist aber wie gesagt kein Aufruf sondern eine Deklaration. In deinen Fall mit Beachtung dessen, was erwähnt wurde, sieht deine main.cpp (oder wie die bei dir heißt) so aus:

    #include"fakultaet.h"
    
    int main()
    {
      fakultaet(); // <-- Aufruf, keine Deklaration
    }
    

    Besser wäre es aber die Eingabe und Logik zu trennen, und tatsächlich mit Rückgabewerten und Parametern zu arbeiten. Daher wäre deine erste Deklaration besser. Wir wollen einen int zurückgeben und einen int übergeben. Da man den Parameter auch lesbar halten sollte (und später unter einem Namen verwenden möchste, geben wir ihn auch mal einen Namen):

    Neue Deklaration, wenn getrennt von der Ein-/Ausgabe:
    int fakultaet(int zahl);

    So... nun nehmen wir die Eingabe mal aus deiner Funktion und tuen sie in deine main.cpp:

    #include<iostream>
    #include"fakultaet.h"
    
    using namespace std;
    
    int main()
    {
      cout << "Bitte Zahl die zu \"fakultieren\" ist eingeben: " << endl;
      int zahl;
      cin >> zahl;
    
      int ergebnis = fakultaet(zahl);
      cout << "ergebnis: " << ergebnis << endl;
    }
    

    So nun nehmen wir uns wegen Kritikpunkten aber nochmal deinen ursprünglichen Header vor:

    latenite schrieb:

    #include<iostream>
    using namespace std;
    
    int fakultaet(int)
    {
    	cout<<"Bitte Zahl die zu \"fakultieren\" ist eingeben: "<<endl;
    	int zahl;
    	cin>>zahl;
    	if (zahl <= 1)
    	{
    		cout<<"ergebnis: "<<zahl<<endl;
    	}
    	zahl = zahl * fakultaet(zahl-1);
    }
    

    1. Die Deklaration erwartet eine Rückgabe (per return), das machst du aber nicht.
    2. Die Deklaration verwendet einen unbenannten Parameter vom Typ int der auch nichts tut.

    ==> Dies Ändern wir aber gleich

    3. Du machst einen Handstand um die Ausgabe erst bei einen Wert gleich oder niedriger als 1 zu machen.
    4. Du rufst die Methode rekursiv mit einem Parameter auf, der nie verwendet wird (da er keinen Namen hat), und musst jedesmal auf neue die Eingabe machen (steht nunmal so in der Funktion.

    ==> Durch Trennung Ein/Ausgabe vom Code sind diese Probleme teilweise gelöst...

    Geben wir dir mal einen Anfang:

    int fakultaet(int zahl)
    {
      if(zahl <= 1)
        return 1;
      return zahl * fakultaet(zahl-1);
    }
    

    Die Berechnung habe ich jetzt mal von einer anderen Lösung übernommen, aber ungeprüft.

    Nun kannst du es einfach mal durchspielen:

    a) Du gibst eine Zahl ein (sagen wir 3)
    b) Du rufst fakultaet mit dieser Zahl als Parameter auf (daher ist in der Funktion zahl also 3)
    c) Die if-Bedingung tritt nicht ein, also zur Rückgabe:
    Du gibst 3 * fakultaet(3-1) zurück. Da fakultaet eine Funktion ist, wird diese erstmal aufgelöst:

    b2) Du rufst fakultaet mit 2 als Parameter auf (Funktion zahl also 2)
    c2) Die if-Bedingung tritt nicht ein, also zur Rückgabe:
    Du gibst 2 * fakultaet(2-1) zurück. Da fakultaet eine Funktion ist, wird diese erstmal aufgelöst:

    b3) Du rufst fakultaet mit 1 als Parameter auf (Funktion zahl also 2)
    c3) Die if-Bedingung tritt ein, also wird 1 zurückgegeben.

    c2/b) Die Rückgabe ist also: 2 * 1 [Rückgabe von fakultaet(2-1), Siehe c3]
    c1/b) Die Rückgabe ist also: 3 * 2 [Rückgabe von fakultaet(3-1), Siehe c2/b]

    d) Eine Variable die ich ergebnis genannt habe bekommt das Ergebnis geliefert (6). Diese wird ausgegeben...

    Ich hoffe ich konnte nun alle Klarheiten beseitigen 😉

    cu André



  • nur mal so?? wieso is das SO nicht in einem der vielem Tutorials erklärt?
    Danke das hat mir nen guten Durchblick gebracht! Echt danke danke für die mühe.

    Das funktionsfähige Programm (mit IO ausserhalb des headers) sieht jetzt so aus:

    #include<iostream>
    #include"fakultaet.h"
    using namespace std;

    int main()
    {
    cout<<"Bitte Zahl die zu \"fakultieren\" ist eingeben: "<<endl;
    int zahl;
    cin>>zahl;

    fakultaet(zahl);

    cout<<"Ergebnis: "fakultaet(zahl);
    }

    #include<iostream>
    using namespace std;

    int fakultaet(int zahl)
    {
    if (zahl <= 1)
    {
    return 1;
    }
    return zahl * fakultaet(zahl-1);
    }

    ist da jetzt noch was zu verbessern? (den tip mit der IO bei der GUI-programmierung z.B fand ich echt sinnvoll)

    thx asc :p



  • Erstmal zum Thema:
    a) Du solltest dir die cpp-Tags für den Code angewöhnen. So kann man den Code deutlich besser lesen. (Und Einrückungen helfen ebenso ;p)
    b) In Headern (Begründung kannst du sicherlich hier im Forum finden, gab es mehrfach) sollte man "using namespace" grundsätzlich vermeiden. Auch wenn es bedeutet das z.B. statt cin ein std::cin stehen muss.
    c) Im Header brauchst du das Include und das using namespace eh nicht (wird da nicht verwendet).

    latenite schrieb:

    nur mal so?? wieso is das SO nicht in einem der vielem Tutorials erklärt?

    Vielleicht liegt das daran, das viele Entwickler irgendwann Scheuklappen davor bekommen was man erklären muss und was nicht (ich schließe mich davor auch nicht gänzlich aus). Man kann es einem Tutorial auch nicht unbedingt immer vorwerfen. Wenn es wie hier sehr ausführlich ist, mag es für die puren Anfänger die noch keinerlei Vorerfahrungen haben gut sein. Aber jeder andere fühlt sich dabei zu sehr "verhätschelt".

    Versuch mal ein Tutorial zu schreiben das wirklich allen passt (okay, mittels html könnte man das vielleicht machen, in dem man hinter jede Seite noch eine weitere alternative Seite tut und den Leser die auswahl lässt ob ihn die kurze oder lange Variante besser liegt...).

    Und zu guter letzt: In der Regel sind alle Entwickler schreibfaule Leute.

    Ich selbst brauche die Muse dazu (Aus Langweile und wegen Vorkenntnissen hatte ich z.B. in einem 2 wöchigen Datenbankkurs so eine etwa 100 Seitige Mitschrift erstellt... War soviel ich mich erinnere in unseren SAP-Lehrgang das am häufigsten kopierte Dokument xD)

    latenite schrieb:

    thx asc :p

    Gern geschehen...



  • Kleine Verbesserung noch 😉

    int main() 
    { 
        cout<<"Bitte Zahl die zu "fakultieren" ist eingeben: "<<endl; 
        int zahl; 
        cin>>zahl; 
    
        fakultaet(zahl); // <-- Das ist hier unnötig.
    
        cout<<"Ergebnis: " << fakultaet(zahl); 
    }
    

    Der erste Aufruf von fakultaet ist unnötig, da der Rückgabewert dort einfach ignoriert wird.

    Gruß
    Don06



  • Und um ehrlich zu sein, kann ich mir nicht vorstellen, dass Du damit:

    cout<<"Bitte Zahl die zu "fakultieren" ist eingeben: "<<endl;
    

    keine Probleme hast... 😃


Anmelden zum Antworten