Go Down

Topic: Funktion mit Wertrückgabe ? (Read 2 times) previous topic - next topic

Doc_Arduino

Hallo,

oh Mann, ich Idiot. Jetzt wo Du das sagst, klar, wofür habe denn globale Variablen verwendet. Na dann brauche ich keine Rückgabewerte, logisch.  ;)

Ich denke mal es hätte niemanden daran gehindert die Funktion so zu programmieren das man auch mehrere Rückgabewerte verwenden kann. Ich meine, übergeben kann man soviel man braucht an die Funktion. Nur beim rausrücken wird gespart. Das könnte vieles vereinfachen. Die Einschränkung verstehe ich nicht.

Tschau
Doc Arduino

jurs


Wer hat denn das verzapft das man nur eine Variable zurückbekommt.   :(


Als sogenannten "Rückgabewert" kannst Du nur einen einzigen Wert zurückbekommen. Das ist der Wert, der vor der Funktionsdeklaration steht, also das "int" vor dem Funktionsnamen "summe":

int summe(int a, int b)
{
  return a+b;
}

Der return-Wert. Dieser Wert ist direkt Zuweisungskompatibel. Und so wie ein Gleichheitszeichen nur eine einzige Zuweisung macht, macht eine Funktion auch nur einen einzigen zuweisungsfähigen Rückgabewert:

int i=summe(2,4);

Trotzdem kann eine Funktion auch mehrere Werte "zurückgeben", und zwar wenn Du diese Werte auch vorher auch an die Funktion "übergeben" hast, und zwar als Parameter mit spezieller Aufrufkonvention.

Bei der Parameterübergabe an Funktionen gibt es zwei Möglichkeiten:
1. Call by Value ==> Parameter als Wert an die Funktion übergeben
2. Call by Reference ==> Parameter als Referenz an die Funktion übergeben

Die "by Value" übergebenen Parameter können Konstanten sein, oder Variablen, die nach der Rückkehr aus der Funktion unverändert sind.

Die "by Reference" übergebenen Parameter werden als Adressreferenz an die Funktion übergeben, und wenn die Funktion diese Parameter in der Funktion verändert und die Funktion kehrt zurück, dann haben diese Parameter ihren veränderten Wert!

Eventuell kennst Du die Parameterübergabe "by Reference" noch nicht.

Eine Parameterübergabe "by Reference" wird so deklariert, dass bei der Funktionsdeklaration ein "&"-Zeichen (Adressoperator) vor den so zu übergebenden Parameter geschrieben wird.

Ich habe mal ein Beispielprogramm mit zwei Funktionen gemacht, bei denen ein oder mehrere Parameter "by Reference" übergeben werden.

Code: [Select]

void setup() {
  // put your setup code here, to run once:
  Serial.begin(9600);
}


void zumQuadrat(float &x){
   x = x*x;
}


void testParamsByReference(int a, int b, int c, int &ret1, int &ret2, int &ret3)
{
  ret1=a+b+c;
  ret2=a*b*c;
  ret3=ret1+ret2;
}


void loop() {
  // put your main code here, to run repeatedly:
  float x=1.5; 
  Serial.print("x= ");
  Serial.println(x);
  zumQuadrat(x);
  Serial.println("Zum Quadrat nehmen");
  Serial.print("x= ");
  Serial.println(x);
  Serial.println();

  int var1, var2, var3, var4, var5, var6;
  var1=4;
  var2=5;
  var3=6;
  testParamsByReference(var1, var2, var3, var4, var5, var6);
  Serial.print("Var1= ");
  Serial.println(var1);
  Serial.print("Var2= ");
  Serial.println(var2);
  Serial.print("Var3= ");
  Serial.println(var3);
  Serial.print("Summe: ");
  Serial.println(var4);
  Serial.print("Produkt: ");
  Serial.println(var5);
  Serial.print("Summe plus Produkt: ");
  Serial.println(var6);
  while (true==true);
}


Probier's aus: Eine Parameterliste einer Funktion kann praktisch beliebig lang sein, und darunter können beliebig viele "by Reference" Parameter sein, deren "Rückgabewert" Du nach dem Aufrufen der Funktion auswerten kannst.

Du kannst einen, mehrere oder alle Parameter "by Reference" an eine Funktion übergeben.
Bei Bedarf einfach den "&"-Adressoperator mit in die Funktionsdeklaration des Parameters schreiben.

Ist es eventuell das, was Du gesucht hast?

voithian

#7
Mar 15, 2013, 09:03 pm Last Edit: Mar 15, 2013, 09:05 pm by voithian Reason: 1

Hallo,

oh Mann, ich Idiot. Jetzt wo Du das sagst, klar, wofür habe denn globale Variablen verwendet. Na dann brauche ich keine Rückgabewerte, logisch.  ;)

Ich denke mal es hätte niemanden daran gehindert die Funktion so zu programmieren das man auch mehrere Rückgabewerte verwenden kann. Ich meine, übergeben kann man soviel man braucht an die Funktion. Nur beim rausrücken wird gespart. Das könnte vieles vereinfachen. Die Einschränkung verstehe ich nicht.



Hallo,,
wenn du noch was lernen möchtest, dann schau doch mal in google oder einen C++-Lehrbuch zu dem Thema "Referenzen" nach. damit kannst du die Verwendung von Pointern bei der Rückgabe von mehreren Werten vermeiden. Z.B. hier
http://de.wikipedia.org/wiki/Referenzparameter unter dem Stichwort "Referenzparameter in Form von Referenzen".

Manche Leute sehen die Verwendung von globalen Variablen zur Parameterübergabe (oder überhaupt) als ganz schön "bah, bah" an ;)
Man kann damit bei größeren Programmen nämlich ganz schnell den Überblick verlieren, wer wo etwas verändert.

Gruß
Wolfgang

[Edit]Mist,  da war jurs wohl schneller als ich und sogar noch ausführlicher

Doc_Arduino

Hallo,

klingt erstmal für mich sehr kompliziert.  :~  Werde mir das in Ruhe anschauen und mehrfach lesen müssen. Danke Euch.

Hier mein Kometenschweif, der erstmal soweit funktioniert. Verwendete Pins sind 2 bis 9. Das soll ein zusätzlicher Lichteffekt werden außen herum für meinen Würfel, wenn er würfelt bei Tastendruck.

Code: [Select]

// Arduino Mega 2560

// Geschwindigkeitssteigerung des Kometenschweifs bzw. abbremsen
int PAUSE [41] = {48,52,56,60,64,68,72,77,82,86,91,96,101,107,112,118,123,129,135,141,147,154,160,167,174,180,188,195,202,209,217,225,233,240,249,257,265,274,282,291,300 };
int SPEED = 40;       

int LEDPOS_1 = 5;                      // auf sicheren Anfangswert gesetzt für ersten Durchlauf
int LEDPOS_2 = 4;                      // auf sicheren Anfangswert gesetzt für ersten Durchlauf
int LEDPOS_3 = 3;                      // auf sicheren Anfangswert gesetzt für ersten Durchlauf
int LEDPOS_4 = 2;                      // erster Pin der LED Reihe
int LAST_LED = 9;                      // letzter Pin der LED Reihe

int LED_1, LED_2, LED_3, LED_4;        // zum Zwischen speichern der LED Position zum umdrehen

int LED_H1 = 255;        // 255, Helligkeiten der LEDs     
int LED_H2 = 96;         //  96
int LED_H3 = 32;      //  32
int LED_H4 = 8;           //   8

void setup()
{     
//   Serial.begin(9600);

  // set pins 2 through 9 as outputs:
  for (int thisPin =2; thisPin <= 9; thisPin++)
   {
    pinMode(thisPin, OUTPUT);
   }

//  Serial.println("\n[memCheck]");
//  Serial.println(freeRAM(), DEC); 
   
}

void loop()
{

  for (int i=0; i < 60; i++)
    {
     Kometenschweif_Rechts ();
    }

  Schweif_nach_links_drehen ();
     
  for (int i=0; i < 47; i++)
    {
     Kometenschweif_Links ();
    }

  Schweif_nach_rechts_drehen ();   

}




/* ***  Funktionen  *** */

void Kometenschweif_Rechts ()
{
     if (LEDPOS_1 > 9) { LEDPOS_1 = 2; }             // wenn "letzte" LED erreicht, auf Anfangsposition setzen
     
     analogWrite(LEDPOS_1, LED_H1);                  // 8, Schweifspitze ganz hell                                   
     analogWrite(LEDPOS_2, LED_H2);                  // 7, LED dahinter etwas dunkler   
     analogWrite(LEDPOS_3, LED_H3);                  // 6, nächste LED noch dunkler                 
     analogWrite(LEDPOS_4, LED_H4);                  // 5, letzte LED noch dunkler       
     analogWrite(LAST_LED, LOW);                     // letzte alte LED ausschalten
             
     LAST_LED = LEDPOS_4;                            // 5

     LEDPOS_4 = LEDPOS_3;                            // 6
     LEDPOS_3 = LEDPOS_2;                            // 7
     LEDPOS_2 = LEDPOS_1;                            // 8
     LEDPOS_1++;                                     // 9

     delay(PAUSE[SPEED]);                            // Kometenschweif beschleunigen
     SPEED--;
     if (SPEED < 1) { SPEED = 0; }                   // schnellsten Wert beibehalten
                           
}


void Kometenschweif_Links ()
{
     if (LEDPOS_1 < 2) { LEDPOS_1 = 9; }             // wenn "letzte" LED erreicht, auf Anfangsposition setzen

     analogWrite(LEDPOS_1, LED_H1);                  // Schweifspitze ganz hell                 
     analogWrite(LEDPOS_2, LED_H2);                  // LED dahinter etwas dunkler       
     analogWrite(LEDPOS_3, LED_H3);                  // nächste LED noch dunkler                     
     analogWrite(LEDPOS_4, LED_H4);                  // letzte LED noch dunkler           
     analogWrite(LAST_LED, LOW);                     // letzte alte LED ausschalten
             
     LAST_LED = LEDPOS_4;

     LEDPOS_4 = LEDPOS_3;
     LEDPOS_3 = LEDPOS_2;
     LEDPOS_2 = LEDPOS_1;
     LEDPOS_1--;
         
     delay(PAUSE[SPEED]);                            // Kometenschweif abbremsen
     SPEED++;
     if (SPEED > 40) { SPEED = 40; }                 // langsamsten Wert beibehalten
}


void Schweif_nach_links_drehen ()
{
     LED_1 = LAST_LED;             //5,  LED Positionen zwischen speichern
     LED_2 = LEDPOS_4;             //6
     LED_3 = LEDPOS_3;             //7
     LED_4 = LEDPOS_2;             //8

     LEDPOS_1 = LED_1;             //5,  LED Positionen umdrehen
     LEDPOS_2 = LED_2;             //6
     LEDPOS_3 = LED_3;             //7
     LEDPOS_4 = LED_4;             //8

     if (LEDPOS_4 >= 9) { LAST_LED = 2;}
       else { LAST_LED = LEDPOS_4 + 1; }
}


void Schweif_nach_rechts_drehen ()
{
     LED_1 = LAST_LED;              //  LED Positionen zwischen speichern
     LED_2 = LEDPOS_4;             
     LED_3 = LEDPOS_3;       
     LED_4 = LEDPOS_2;         

     LEDPOS_1 = LED_1;              //  LED Positionen umdrehen
     LEDPOS_2 = LED_2;           
     LEDPOS_3 = LED_3;           
     LEDPOS_4 = LED_4;           

     if (LEDPOS_4 <= 2) { LAST_LED = 9;}
       else { LAST_LED = LEDPOS_4 - 1; }
}


int freeRAM()                                     //  Funktion im WWW gefunden, zeigt freien Speicher an
  {
  extern int __heap_start, *__brkval; 
  int v; 
  return (int) &v - (__brkval == 0 ? (int) &__heap_start : (int) __brkval);
  }

Tschau
Doc Arduino

MaFu

verzapft ist gut ;) in welcher anderen sprache geht sowas?

Mehrere Rückgabewerte gehen z.B. schon immer in Python und seit einiger Zeit auch in .NET. Stichwort: Tupel
Da kann man dann z.B. solche Konstrukte machen: a,b,c = mach_irgendwas()
Ist eine nette Sache. Wenn man sich daran mal gewöhnt hat, vermisst man es bei anderen Sprachen schon etwas.
_______
Manfred

Go Up