Mehrere Werte wie zurückgeben ?



  • Hallo alle zusammen,

    ich lern grad auf meine Klausur in Praktische Informatik und da müssen wir c++ programmieren. Und ganz so gut bin ich noch nicht in dem Fach. Habe Hier ein programm geschrieben des die Quersumme, durschnitt usw.( Siehe Code) die es von einer ascii zeichenkette bekommt berechnen soll. Also zum programm habe ich nur eine frage und zwar wie kann ich mehrere werte aus dem Unterprogramm der Main funktion geben , der die dann ausgibt ? Ich bin irgendwie am Verzweifeln, könntet ihr mir helfen. Wenn ihr am programm fehler bemerkt könnt hier hindeuten doch das was ich lernen will ist wie ich mehrere werte zurückgeben kann, dabei gehts mir am meisten. Ich danke euch schon im voraus =).

    Grüße Yasar.

    #include <iostream>
    
    using namespace std;
    
    long crossfoot(char *str, unsigned long Odd, unsigned long even, unsigned long midval, unsigned long minval,unsigned long maxval);
    long retval;
    unsigned long oddcount, evencount;
    unsigned long minval=9,maxval,midval;
    
    int main()
    {
    
    crossfoot("1234", oddcount, evencount, midval, minval, maxval);
    
    cout<< "Ergebnis: " << endl;
    cout<< "Quersumme :                 "<<retval<<endl;
    cout<< "Anzahl gerader Ziffern:     "<<evencount << endl;
    cout<< "Anzahl ungerader Ziffern:   "<<oddcount<<endl;
    cout<< "Durchschnittswert Ziffern:  "<<midval<<endl;
    cout<< "Kleinste vorgk. Ziffer:     "<<minval<<endl;
    cout<< "Groste vorgk. Ziffern:      "<<maxval<<endl;
    
    return 0;
    }
    
    long crossfoot(char *str,unsigned long odd, unsigned long even, unsigned long midval, unsigned long minval, unsigned long maxval)
    {
    
        int i=0,a=0;
    
        while(str[i])
        {
            retval += (str[i]-48);
    
            if(str[i] %2 == 0)
                evencount++;
    
            else
                oddcount++;
    
            i++;
        }
    
        midval = retval / i;
    
        for(a=0;a<i;a++)
        {
            if (str[a] > maxval)
                maxval = str[a];
    
        }
        maxval= maxval-48 ;
    
        for(a=0;a<i;a++)
        {
            if (str[a] < minval)
                minval = str[a];
    
        }
    
    }
    


  • Ich denke, das ist eher so gedacht, daß Du für die verschiedenen Aufgaben auch jeweils eine eigenständige Funktion schreiben sollst...



  • Das macht man mit einer call by reference

    z.b.:

    void swap(void*_ptr_1 , int & k)
    {
    int iNt=0;
    
    iNt=*((int*)(_ptr_1));
    memcpy(_ptr_1,(void*)&k,sizeof(int));
    k=iNt;
    }
    
    int _tmain(int argc, _TCHAR* argv[])
    {
    int a=1;
    int b=2;
    swap((void*)&a,b);
    
    __debugbreak();
    
    	return 0;
    }
    

    grüße



  • zu deiner eigentlichen frage: das kann man über referenzen oder (genutzt, wenn die parameter optional sind) mit pointern.

    fangen wir doch noch einmal von vorn an:

    der einfach halber mal schritt für schritt.
    und da du sicherlich die standard-lib(abgesehen von ein- und ausgabe) nicht nutzen darfst auch ohne diese:

    int quersumme(int value)
    {
      int ret_val = 0;
      /* ... */
      return ret_val;
    }
    
    float durchschnitt(int* first, int size)
    {
      float sum = 0;
      /* ... */;
      return sum/static_cast<float>(size); //zu static_cast bemühst du mal google
    }
    
    int to_int(const char* str)
    {
      int ret_val = 0;
      /* ... */
      return ret_val;
    }
    
    #include <iostream>
    
    //gibt der die länge eines arrays aus, dessen länge zur compilezeit fest steht.
    //musst du nciht verstehen, du kannst auch konstante zahlen nehmen.
    template <typename T, int S>
    int arraylaenge(T (&)[S])
    {
      return S;
    }
    
    int main()
    {
      { /* 1. */
        const char* number_string = "1234";
    
        int number = to_int(number_string);
        std::cout << quersumme(number) << std::endl;
      }
    
      { /* 2. */
        numbers[] = { 3, 2, 5, 6, 1, 9 };
        std::cout << durchschnitt( numbers, arraylaenge(numbers) ) << std::endl;
      }
    }
    

    jetzt bauen wir noch die funktionen:

    int quersumme(int value)
    {
      int ret_val = 0;
      while(value > 0)
      {
        int letzte_stelle = value%10;
        int value_minus_letzte_stelle = value/10;
    
        value = value_minus_letzte_stelle;
    
        ret_val += letzte_stelle;
      }
      return ret_val;
    }
    

    oder kürzer:

    int quersumme(int value)
    {
      int ret_val = 0;
      while(value > 0)
      {
        ret_val += value%10;
        value /= 10;
      }
      return ret_val;
    }
    

    und

    float durchschnitt(int* first, int size)
    {
      float sum = 0;
    
      for(int i = 0; i != size; i++)
      {
        sum += static_cast<float> (*first);
        int* next = first+1;
        first = next;
      }
    
      return sum/static_cast<float>(size);
    }
    

    oder kürzer:

    float durchschnitt(int* first, int size)
    {
      float sum = 0;
    
      for(int i = 0; i != size; ++i, ++first)
      {
        sum += static_cast<float> (*first);
      }
    
      return sum/static_cast<float>(size);
    }
    

    bleibt nur noch:

    int to_int(const char* str)
    {
      int ret_val = 0;
    
      while(*str != '\0') //strings werden mit einem '\0' terminiert -> wir hätten das ende erreicht
      {
        ret_val = ret_val * 10; //es kommt noch eine stelle -> eine null mehr an die zahl und dann die letzte ziffer einlesen:
        //ggf. überprüfung, ob *str eine ziffer ist
        ret_val += *str-'0';
    
        ++str; //pointer auf das nächste zeichen vorrücken
      }
      return ret_val;
    }
    

    kürzer:

    int to_int(const char* str)
    {
      int ret_val = 0;
    
      while(*str != '\0')
      {
        ret_val *= 10;
        ret_val += *str-'0';
    
        ++str;
      }
      return ret_val;
    }
    

    an manchen stellen gibt es bessere typen(längenangaben mit signed werten etc., aber das soll erst mal nicht stören)
    mit der standard-lib kann man vieles einfacher, eleganter, lesbarer usw. machen. vor allem aber auch sicherer. bei uns gibt es keine einzige abfrage, ob die zahl/das zeichen/... das ist, was wir erwarten. das müsstest du selbst noch ergänzen.

    bb

    edit: @zeusosc: genau. das sollte seine frage beantworten. immerhin hast du ja daran gedacht, dass er ein anfänger ist und leicht verständlichen quellcode ohne irgendwelchen zusätzlichen schnick-schnack gepostet 👍



  • grml; ich seh gerad, dass du ja was anderes willst - hab mich von der ersten antwort ablenken lassen und hatte deinen post nur überflogen. nicht ganz so ausführlich, aber der vollständigkeit halber:

    void xyz(const char* str, int& ungerade_ziffern, int& gerad_ziffern, float& durchschnitt, int& min, int& max)
    {
      ungerade_ziffern = gerade_ziffern = 0;
      durchschnitt = 0.f;
      min = 9;
      max = 0;
    
      if(*str == '\0')
      {
        min = 0;
        return;
      }
    
      do
      {
        int ziffer = *str-'0';
        ++str;
    
        if(ziffer%2 != 0) ++ungerade_ziffern;
        else              ++  gerade_ziffern;
    
        if(ziffer < min) min = ziffer;
        if(ziffer > max) max = ziffer;
    
        durchschnitt += static_cast<float>(ziffer);
      } while(*str != '\0');
    
      durchschnitt /= static_cast<float>(ungerade_ziffern+gerade_ziffern);
    }
    
    #include <iostream>
    int main()
    {
      int ungerade_ziffern, gerade_ziffern;
      float durchschnitt;
      int min, max;
    
      xyz("1234", ungerade_ziffern, gerade_ziffern, durchscnitt, min, max);
    
      std::cout << "..." << std::endl;
    }
    

    bb



  • Output-Parameter hatten wir ja schon.
    Zusätzlich gibt es dann noch Dinge wie std::pair<> und boost::tuple<>, und natürlich kann man ne eigene struct dafür definieren.

    struct BlahValues
    {
        int blubb;
        float blobber;
        long long bubblesBubblesBubbles;
    };
    
    BlahValues Foo()
    {
        BlahValues result = { 1, 2, 3 };
        return result;
    }
    

    @unskilled
    Von const hältst du nicht sehr viel, oder? 🤡



  • hustbaer schrieb:

    ...natürlich kann man ne eigene struct dafür definieren...

    👍



  • unskilled schrieb:

    edit: @zeusosc: genau. das sollte seine frage beantworten.
    Immerhin hast du ja daran gedacht, dass er ein anfänger ist und leicht
    verständlichen quellcode ohne irgendwelchen zusätzlichen schnick-schnack gepostet 👍

    Naja 🙂 ,
    ich ging davon aus das er
    a) weiß was eine main fkt ist
    b) das er sieht das aus dieser eine Funktion "swap" aufgerufen wird welche
    zwei Argumente bearbeitet.
    c) Das die Funktion void als Rückgabe hat
    d) Das darauffolgend die Art der Zeiger- und Referenzübergabe
    dann etwas mit dem Titel des Threads zu tun hat: "Mehrere Werte zurückgeben".
    e) Das er den Begriff "swap" schon einmal gehört hat und dessen Funktion
    versteht..

    Ich weiß viele Annahmen, ich wollte aber nicht zu viel overhead produzieren..

    Entschuldigt bitte...



  • hustbaer schrieb:

    Output-Parameter hatten wir ja schon.
    Zusätzlich gibt es dann noch Dinge wie std::pair<> und boost::tuple<>

    Und neuerdings auch std::tuple



  • hustbaer schrieb:

    @unskilled
    Von const hältst du nicht sehr viel, oder? 🤡

    normalerweise schon, aber wollte ihn im ersten post nicht durch x mal const verwirren.

    im 2. hab ich auf die schnelle nix gesehen 😛



  • Nene, eh im ersten.
    float durchschnitt(int* first, int size) und so Sachen, *schüttel*.

    Und mal ne doofe Frage: wieso die ganzen expliziten einFloatWert (operator) static_cast<float>(einIntegerWert) ?
    Die Konvertierung nach float ist in dem Fall doch sowieso implizit.
    Schmeisst dir der Compiler "conversion loses precision" Warnings oder ... 😕



  • hustbaer schrieb:

    Schmeisst dir der Compiler "conversion loses precision" Warnings oder ... 😕

    ich nehms mal an; habs nicht compiliert.



  • zeusosc schrieb:

    Das macht man mit einer call by reference

    krass. Ich bin zuversichtlich, dass das ist das langsamste Swap für ints war, das jemals in diesem Forum gepostet wurde.

    Und ich dachte, ich hätte alles gesehen...definition ein Kandidat für tdwtf



  • Nicht nur das langsamste, auch das hässlichste. Wenn, dann schon so:

    template <typename T>
    void swap(T& a, T& b)
    {
        T tmp(std::move(a));
        a = std::move(b);
        b = std::move(tmp);
    }
    

    Oder eben gleich std::swap benutzen.



  • unskilled schrieb:

    hustbaer schrieb:

    Schmeisst dir der Compiler "conversion loses precision" Warnings oder ... 😕

    ich nehms mal an; habs nicht compiliert.

    Dann aber erst recht die Frage: wozu die Casts?



  • weil ich es nicht mag, eine warning zu bekommen, obwohl ich weiß, was ich dort tue.
    hab aber gerad keinen compiler zur hand. wenn ich mich recht entsinne, schmeißt der msvc aber ne warning:

    int main()
    {
     int a = 0, float b = 1.f;
    
     float c = a/b;
    }
    

    vll mags ma jmd mit /W4 compilieren?!

    bb



  • Ah, OK. Ja, mach ich auch so, wenn beim Compilieren grundsätzlich Warnings bekommt, ist das Feature für die Katz.
    War mir jetzt nur nicht ob das "ich nehms mal an; habs nicht compiliert." heissen sollte "ja, das war mein Grund".



  • zeusosc schrieb:

    Das macht man mit einer call by reference

    z.b.:

    void swap(void*_ptr_1 , int & k)
    {
    int iNt=0;
    
    iNt=*((int*)(_ptr_1));
    memcpy(_ptr_1,(void*)&k,sizeof(int));
    k=iNt;
    }
    
    int _tmain(int argc, _TCHAR* argv[])
    {
    int a=1;
    int b=2;
    swap((void*)&a,b);
    
    __debugbreak();
    
    	return 0;
    }
    

    grüße

    Was'n Quatsch.

    Das taugt höchstens für sowas: http://www.ioccc.org/
    ist aber mit Sicherheit in keinster Weise eine Hilfe für iso89.


Log in to reply