2 Variablen zurückgeben aus Rekursiver Funktion

Schnelle objektorientierte, kompilierende Programmiersprache.
DANrulz81
Beiträge: 53
Registriert: Fr Dez 23, 2011 9:40 pm

2 Variablen zurückgeben aus Rekursiver Funktion

Beitrag von DANrulz81 » Di Jan 10, 2012 4:30 pm

Hallo zusammen,

ich hab ein bisschen im Algorythmusforum gestöbert und bin dabei auf das Collatz - Problem gestoßen. Ich hab den Code von einem C++ - Schnipsel umgebaut auf C:

Code: Alles auswählen

#include <stdio.h>

int collatz(int start, int zaehler)
{
        if ( (start == 1) || (start == -1) ) {
                return 1;
        }
        printf("\n%i",start);
        if (start%2)
        {
                return collatz(3*start + 1, zaehler++);
        }
        else
        {
                return collatz(start / 2, zaehler++);
        }
}

int main(void)
{
    int start=0,zaehler=0;

    printf("\nBitte geben sie eine Startzahl ein: ");
    scanf("%i",&start);

    collatz(start,zaehler);
    printf("\n1");
    printf("\n\nAnzahl der Durchg\x84nge: %i",zaehler);

    return 0;
}
Dabei wollt ich noch einen Zähler einbauen, der mir sagt, wieviel Durchgänge stattgefunden haben. So wie ich das eingebaut habe, bekomm ich immer eine "0". Woran liegt das?

Benutzeravatar
cloidnerux
Moderator
Beiträge: 3125
Registriert: Fr Sep 26, 2008 4:37 pm
Wohnort: Ram (Gibts wirklich)

Re: 2 Variablen zurückgeben aus Rekursiver Funktion

Beitrag von cloidnerux » Di Jan 10, 2012 4:56 pm

Woran liegt das?
Das deine Variable Zähler nie erhöht wird. Vlt solltest du sie als Pointer übergeben?
Redundanz macht wiederholen unnötig.
quod erat expectandum

DANrulz81
Beiträge: 53
Registriert: Fr Dez 23, 2011 9:40 pm

Re: 2 Variablen zurückgeben aus Rekursiver Funktion

Beitrag von DANrulz81 » Di Jan 10, 2012 8:20 pm

Wieso wird diese nicht erhöht? Ich dachte, dass die Funktion sich selbst aufruft und somit

Code: Alles auswählen

return collatz(3*start + 1, zaehler++);
zaehler erhöht wird.

Benutzeravatar
cloidnerux
Moderator
Beiträge: 3125
Registriert: Fr Sep 26, 2008 4:37 pm
Wohnort: Ram (Gibts wirklich)

Re: 2 Variablen zurückgeben aus Rekursiver Funktion

Beitrag von cloidnerux » Di Jan 10, 2012 8:42 pm

Wieso wird diese nicht erhöht? Ich dachte, dass die Funktion sich selbst aufruft und somit
Weil du hier etwas hast, was sich "Call by Value" nennt.
Dabei werden Variablen, die du übergibst, kopiert.
Daher übergibst du zwar jeweils einen Wert, aber deine Orginalvariable wird nicht verändert.
Wenn du dies ändern willst, musst du einen Pointer übergeben. So wird zwar auch der Pointer kopiert, aber da er auf eine bestimmte Variable zeigt, nämlich die in der main, wird auch eben diese inkrementiert.
Redundanz macht wiederholen unnötig.
quod erat expectandum

DANrulz81
Beiträge: 53
Registriert: Fr Dez 23, 2011 9:40 pm

Re: 2 Variablen zurückgeben aus Rekursiver Funktion

Beitrag von DANrulz81 » Di Jan 10, 2012 10:01 pm

O.k. Das hab ich mal versucht, so wie ich es verstanden habe, leider ohne Erfolg:

Code: Alles auswählen

#include <stdio.h>

int collatz(int start, int *zeiger)
{
        if ( (start == 1) || (start == -1) ) {
                return 1;
        }
        printf("\n%i",start);
        if (start%2)
        {
                return collatz(3*start + 1,zeiger++);
        }
        else
        {
                return collatz(start / 2,zeiger++);
        }
}

int main(void)
{
    int start=0,zaehler=0;
    int *zeiger;

    zeiger=&zaehler;

    printf("\nBitte geben sie eine Startzahl ein: ");
    scanf("%i",&start);

    collatz(start,zeiger);
    printf("\n1");
    printf("\n\nAnzahl der Durchg\x84nge: %i",*zeiger);

    return 0;
}
:(

Benutzeravatar
cloidnerux
Moderator
Beiträge: 3125
Registriert: Fr Sep 26, 2008 4:37 pm
Wohnort: Ram (Gibts wirklich)

Re: 2 Variablen zurückgeben aus Rekursiver Funktion

Beitrag von cloidnerux » Di Jan 10, 2012 10:14 pm

Es müsste (*zeiger)++ heißen
Redundanz macht wiederholen unnötig.
quod erat expectandum

DANrulz81
Beiträge: 53
Registriert: Fr Dez 23, 2011 9:40 pm

Re: 2 Variablen zurückgeben aus Rekursiver Funktion

Beitrag von DANrulz81 » Di Jan 10, 2012 10:24 pm

Es müsste (*zeiger)++ heißen
So klappt das leider auch nicht.

Ich bekomme folgende Compilerausgabe:

Code: Alles auswählen

C:\Users\dennis\Programme\C-Prgrammierung\Collatz1.c||In function 'collatz':|
C:\Users\dennis\Programme\C-Prgrammierung\Collatz1.c|11|warning: passing argument 2 of 'collatz' makes pointer from integer without a cast|
C:\Users\dennis\Programme\C-Prgrammierung\Collatz1.c|3|note: expected 'int *' but argument is of type 'int'|
C:\Users\dennis\Programme\C-Prgrammierung\Collatz1.c|15|warning: passing argument 2 of 'collatz' makes pointer from integer without a cast|
C:\Users\dennis\Programme\C-Prgrammierung\Collatz1.c|3|note: expected 'int *' but argument is of type 'int'|
||=== Build finished: 0 errors, 2 warnings ===|

Benutzeravatar
cloidnerux
Moderator
Beiträge: 3125
Registriert: Fr Sep 26, 2008 4:37 pm
Wohnort: Ram (Gibts wirklich)

Re: 2 Variablen zurückgeben aus Rekursiver Funktion

Beitrag von cloidnerux » Di Jan 10, 2012 10:28 pm

Ok, nochmal in vollständig:
return collatz(3*start + 1,zeiger++);
Musst du erweitern auf:

Code: Alles auswählen

(*zeiger)++;
return collatz(3*start + 1,zeiger);
Mit dem * greifst du auf das ziel des Zeigers zu und erhöhst es dann.
Dann kannst du den Pointer übergeben.
In einer Zeile geht das meines Wissens nach nicht.
Redundanz macht wiederholen unnötig.
quod erat expectandum

DANrulz81
Beiträge: 53
Registriert: Fr Dez 23, 2011 9:40 pm

Re: 2 Variablen zurückgeben aus Rekursiver Funktion

Beitrag von DANrulz81 » Di Jan 10, 2012 10:32 pm

Du bist der Beste :o

Wie steht der Zeiger in Klammern beim Inkrement? Das versteh ich nicht ganz.

Benutzeravatar
cloidnerux
Moderator
Beiträge: 3125
Registriert: Fr Sep 26, 2008 4:37 pm
Wohnort: Ram (Gibts wirklich)

Re: 2 Variablen zurückgeben aus Rekursiver Funktion

Beitrag von cloidnerux » Di Jan 10, 2012 10:58 pm

Wie steht der Zeiger in Klammern beim Inkrement? Das versteh ich nicht ganz.
Klammern bedeuten in C und C++ nur "Kapselung", daher der Inhalt IN den Klammern wird vor dem außen herum bearbeitet(dies ist aber nicht überall möglich).
So versuche ich mögliche Unklarheiten sofort zu umgehen, denn der Ausdruck kann auf 2 Arten Interpretiert werden:

Code: Alles auswählen

*zeiger++;  //Ohne klammern
*(zeiger++); Variante A
(*zeiger)++;  //Variante B
Beim ersten wird der Die Speicheradresse des Zeigers erhöht, beim zweiten den Inhalt der Variable auf die gezeigt wird. Wahrscheinlich wird der Compiler Variante B wählen, da ich mir aber nicht sicher war, hab ich eben die Klammern genutzt um es zu verdeutlichen.
Redundanz macht wiederholen unnötig.
quod erat expectandum

Antworten