C++ Funktionen/Speicheradressen (&), Anfängerfrage



  • Hallo zusammen,

    ich habe eine Frage zum Folgenden Programm. Warum muss bei der ersten Funktion ( void anzahlEinlesen ) vor dem n das "&"-Zeichen gesetzt werden. Ich weiß, dass damit die Adresse des Parameters übergeben wird, allerdings verstehe ich den Sinn noch nicht ganz bzw. warum es ohne nicht funktioniert.

    #include <iostream>
    using namespace std;
    
    // Funktionsdeklarationen -- zu vervollständigen
    void anzahlEinlesen(int &n);
    void werteEinlesen(double *arr, int n);
    void werteAusgeben(double *arr);
    void werteKopieren(double *quellArray, double *zielArray, int n);
    void werteMultiplizieren(double *arr, int n, double faktor);
    bool istAufsteigendSortiert(int n, double *arr);
    
    // Funktionsdefinitionen -- zu vervollstädigen
    void anzahlEinlesen(int &n)
    {
        cout << "Anzahl Werte? ";
        cin >> n;
    
    }
    
    void werteEinlesen(double *arr, int n)
    {
        for (int i=0; i<n; i++)
        {
    		cout << "Wert " << i << "?" ;
    		cin >> arr[i];
    	}
    
    }
    
    void werteAusgeben(double *arr, int n)
    {
        cout << arr[0];
        for (int i = 1; i < n; ++i)
            cout << ", " << arr[i];
    }
    
    void werteKopieren(double *quellArray, double *zielArray, int n)
    {
    	for ( int i=0; i<n; i++)
    	{
    		zielArray[i] = quellArray[i];
    	}
    }
    
    void werteMultiplizieren(double *arr, int n, double faktor)
    {
        for ( int i=0; i<n; i++)
        {
    		arr[i] = arr[i]*faktor;
    	}
    
    }
    
    bool istAufsteigendSortiert(int n, double *arr )
    {
        double letzterWert = arr[0];
        for (int i = 1; i < n; ++i) {
            if (arr[i] < letzterWert)
                return false;
            letzterWert = arr[i];
        }
        return true;
    }
    
    // main-funktion -- bereits komplett
    int main()
    {
        int anzahl;
        anzahlEinlesen(anzahl);
    
        double *werte = new double[anzahl];
        // Zahlen einlesen und in werte-Array speichern
        werteEinlesen(werte, anzahl);
    
        // werte-Array ausgeben
        cout << "Eingegebene Werte: ";
        werteAusgeben(werte, anzahl);
        cout << endl;
    
        // zweites Array anlegen
        double *doppelteWerte = new double[anzahl];
        // werte-Array in doppelteWerte-Array kopieren
        werteKopieren(werte, doppelteWerte, anzahl);
    
        // alle Zahlen in doppelteWerte-Array mit 2.0 multiplizieren
        werteMultiplizieren(doppelteWerte, anzahl, 2.0);
    
        cout << "Verdoppelte Werte: ";
        werteAusgeben(doppelteWerte, anzahl);
        cout << endl;
    
        delete[] doppelteWerte; // doppelteWerte-Array freigeben
    
        // pruefe ob die Werte sortiert sind
        if (istAufsteigendSortiert(anzahl, werte)) {
            cout << "Werte sind aufsteigend sortiert." << endl;
        } else {
            cout << "Werte sind nicht aufsteigend sortiert." << endl;
        }
        delete[] werte;// werte-Array freigeben
        return 0;
    }
    Code
    

    Ich hoffe es nimmt sicher jemand die Zeit, um mir zu helfen 🙂



  • Ohne & kommt der Wert halt nicht aus der Funktion raus.



  • manni66 schrieb:

    Ohne & kommt der Wert halt nicht aus der Funktion raus.

    Das hatte ich mir auch schon gedacht, allerdings kann ich in den darauffolgenden Funktionen das "n" auch durch andere Variablen ersetzen. Blicke da noch nicht ganz durch...



  • Das ist eine Referenz.
    Das heißt, dass, wenn der Wert von n in der Funktion verändert wird, auch die Variable anzahl in der Main-Funktion mit verändert wird. Konkret hier also die Eingabe in n auf anzahl übertragen wird.



  • Skylac06 schrieb:

    Das ist eine Referenz.
    Das heißt, dass, wenn der Wert von n in der Funktion verändert wird, auch die Variable anzahl in der Main-Funktion mit verändert wird. Konkret hier also die Eingabe in n auf anzahl übertragen wird.

    Sehr gut das hilft mir schonmal weiter. Allerdings bn ich mir noch nicht sicher, ob ich das auf andere Beispiele richtig übertragen kann.
    Inwiefern wird z.B hier das array "arr" in der Funktion "gibAus" verändert?

    #include <iostream>
    using namespace std;
    
    // hier struct IntArray einfuegen...
    struct IntArray 
    {
    	int *werte;
    	int anzahlWerte;
    };
    
    IntArray erzeugeIntArray(int anzahlWerte);
    void gibEin(IntArray &arr);
    void gibAus(IntArray &arr);
    IntArray kopiere(IntArray &arr);
    void multipliziereWerte(IntArray &arr, int faktor);
    void zerstoere(IntArray &arr);
    
    // hier Funktionsdefinitionen einfuegen...
    IntArray erzeugeIntArray (int anzahlWerte)
    {
    	IntArray arr;
    	arr.werte = new int[anzahlWerte];
    	arr.anzahlWerte = anzahlWerte;
    	return arr;
    }
    void gibEin ( IntArray &arr)
    {
    	for ( int i=0; i< arr.anzahlWerte; i++)
    	{
    		cout << " Wert " << (i+1) << " von " << arr.anzahlWerte<<": ";
    		cin >> arr.werte[i];
    	}
    
    }
    void gibAus (IntArray &arr)
    {
    	cout << arr.werte[0];
    	for (int i=1; i<arr.anzahlWerte; i++)
    	{
    		cout << ", "<< arr.werte[i];
    	}
    	cout << endl;
    
    }
    IntArray kopiere(IntArray &arr)
    {
    	IntArray arr2 = erzeugeIntArray ( arr.anzahlWerte);
    	//arr2.werte = new int[arr.anzahlWerte];
    	//arr2.anzahlWerte = arr.anzahlWerte;
    	for (int i=0; i<arr.anzahlWerte; i++)
    	{
    		arr2.werte[i] = arr.werte[i];
    	}
    	return arr2;
    }
    
    void multipliziereWerte ( IntArray &arr, int faktor)
    {
    	for (int i=0; i<arr.anzahlWerte; i++)
    	{
    		arr.werte[i] = arr.werte[i] * faktor;
    	}
    
    }
    void zerstoere(IntArray &arr)
    {
    	delete arr.werte;
    }
    
    int main()
    {
        cout << "Anzahl Werte? ";
        int sovielewerte;
        cin >> sovielewerte;
    
        IntArray arr = erzeugeIntArray(sovielewerte);
        gibEin(arr);
    
        IntArray arr2 = kopiere(arr);
        cout << "Faktor? ";
        int faktor;
        cin >> faktor;
        multipliziereWerte(arr2, faktor);
    
        cout << "Werte: ";
        gibAus(arr);
        cout << endl << "Werte * " << faktor << ": ";
        gibAus(arr2);
        cout << endl;
    
        zerstoere(arr);
        zerstoere(arr2);
        return 0;
    }
    Code
    


  • Skylac06 schrieb:

    ...
    Inwiefern wird z.B hier das array "arr" in der Funktion "gibAus" verändert?
    ...

    Gar nicht, denn du greifst nur lesend zu.

    Und bzgl. Namen: Du erstellst hiermit eine funktionslokale Variable ...

    void funktion(int x)
    {
        // bei Ende der Funktion existiert x nicht mehr
    }
    

    Und mit Referenzen (der Name ist dabei egal):

    void funktion(int& rx)
    {
        rx = 4;
    }
    
    int n = 3;
    funktion(n);
    // n ist nun 4
    


  • Hi schrieb:

    Skylac06 schrieb:

    ...
    Inwiefern wird z.B hier das array "arr" in der Funktion "gibAus" verändert?
    ...

    Gar nicht, denn du greifst nur lesend zu.

    Und bzgl. Namen: Du erstellst hiermit eine funktionslokale Variable ...

    void funktion(int x)
    {
        // bei Ende der Funktion existiert x nicht mehr
    }
    

    Und mit Referenzen (der Name ist dabei egal):

    void funktion(int& rx)
    {
        rx = 4;
    }
    
    int n = 3;
    funktion(n);
    // n ist nun 4
    

    Sehr gut das hat mir sehr weitergeholfen!
    Bei meinem ersten Beispiel kann ich das "&" leicht übergehen indem ich die Funktion mit dem Datentyp int erstelle und die Main Methode dann anpasse.
    Geh das bei meinem 2. Beispiel mit den arrays auch?



  • Weiß nicht was du meinst.



  • cppanfaenger1 schrieb:

    Bei meinem ersten Beispiel kann ich das "&" leicht übergehen indem ich die Funktion mit dem Datentyp int erstelle und die Main Methode dann anpasse.
    Geh das bei meinem 2. Beispiel mit den arrays auch?

    Probieren geht über Studieren, würde ich mal fürs Phrasenschwein sagen.

    (Ja, es geht - allerdings gibst du gar kein Array, sondern ein struct zurück).

    Allerdings würde ich dir empfehlen, NICHT eine Struktor wie Pointer+Länge zu verwenden, sondern stattdessen auf std::vector zurückzugreifen. Und ja, du kannst auch einen std::vector aus einer Funktion zurückgeben. Dann geht das Speichermanagement auch automatisch und du brauchst kein new/delete zu verwenden.


Anmelden zum Antworten