C/C++ zwei Werte zurückliefern

PCIT

Freizeitschrauber(in)
C/C++ zwei Werte zurückliefern

Hallo, ich soll eine Funktion schreiben, welche ein Argument übergeben bekommt (int M, so dass eine Schleife von 1 bis M durchlaufen wird) und dann sollen in dieser Funktion Berechnung durchgeführt werden und schließlich sollen zwei int Werte A und B von der Funktion zurückgegeben werden. Wie macht man sowas?
 
AW: C/C++ zwei Werte zurückliefern

Am einfachsten, indem du dir eine entsprechende Datenstruktur definierst und der Rückgabetyp der Funktion ebenfalls dieser Datentyp ist. Beispiel:

struct my_struct {
int A;
int B;
}

my_struct my_function(int M) {
my_struct daten;
daten.A = 0; daten.B = 0;
for(int i=0;i<M;i++) { daten.A += i; daten.B += i*i; }
return daten;
}

int main() {
int M = 10;
my_struct daten = my_function(M);
printf("Summe: %d, Quadratsumme: %d",daten.A,daten.B);
return 0;
}
 
AW: C/C++ zwei Werte zurückliefern

Oder du übergibst den Zeiger auf die Variablen und schreibst direkt drin rum.
Dann kannst du return ohne Wert benutzen.

Aber vermutlich wird euch der Lehrer / Ausbilder dafür ohrfeigen, das ist fehleranfällig, wenn man nicht weiß, was man treibt.
Außerdem erfüllt es nicht ganz die Vorgabe, dass das Ergebnis zurückgegeben werden soll.
 
AW: C/C++ zwei Werte zurückliefern

In guter, alter C Manier, würde ich auch einfach 2 Referenzen übergeben.
Wobei eine vernünftige Funktion nur einen Wert zurückgibt, da man designtechnisch sonst der Gefahr läuft, riesige Funktionen zu bauen und die Wiederverwertbarkeit zu reduzieren. Auch wenn GO und Python zulassen, dass man mehrere Variablen zurückgibt, würde ich es in C nicht machen.
 
AW: C/C++ zwei Werte zurückliefern

Die idiomatische Variante für modernes C++ (11/14) und für moderne Sprachen im Allgemeinen ist: std::pair

Code:
#include <utility>

use namespace std;

pair<int, int> func(int M) {
    // ...
    return make_pair(3, 27);
}

int main() {
    auto r = func(3);
    cout << r.first << endl;      // 3
    cout << r.second << endl;     // 27
}

Klingt doch auch logischer als alle anderen Varianten ;)
Zwei Dinge sind halt ein Paar :P
 
AW: C/C++ zwei Werte zurückliefern

Naja wenn man es pragmatisch sieht, wäre eine Struct besser, wenn man weiß das es bald 3 Zahlen sein könnten. Da müsste man bei deiner Variante mehr ändern, als wenn man eine simple Struktur oder Klasse hat (Auch wenn sich die Zahlen durch ganze Programm ziehen wäre es meiner Meinung nach ziemlich naiv immer ein Pair mitzuschleppen anstatt eine Struktur mit beschreibendem Namen).

Natürlich ist deine Variante erstmal lesbarer und erfordert weniger Code.




Just my 2 Cents
 
AW: C/C++ zwei Werte zurückliefern

Naja wenn man es pragmatisch sieht, wäre eine Struct besser, wenn man weiß das es bald 3 Zahlen sein könnten.
Da hast du recht, aber glücklicherweise gibt es ja auch den Typ std::tuple, in dem man beliebig viele Elemente speichern kann:

Code:
std::tuple<int, float, char, Banana> func(int M) { ... }

[...]Struktur mit beschreibendem Namen.
Beschreibende Namen sind tatsächlich wichtig. Es kommt wirklich auf den Anwendungsfall drauf an. Wenn man schon weiß, dass der Rückgabewert viele unterschiedliche Daten enthält, sollte man von Anfang an ein struct benutzten, ja. Aber in vielen Situationen weiß man tatsächlich auch, dass man nur exakt 2 Werte zurück geben will. Dort ist dann pair oder tuple besser.
 
AW: C/C++ zwei Werte zurückliefern

Als C Hacker eine kleine Zwischenfrage: Was macht tuple dann überhaupt anders als einen struct inline zu definieren?
 
AW: C/C++ zwei Werte zurückliefern

Naja tuples kommen aus der funktionalen Programmierung, wo es häufig vorkommt das man mapping typen braucht für nur eine Funktion. Es wäre lästig für jeden temporären typen eine eigene Klasse / Struktur zu definieren.
 
AW: C/C++ zwei Werte zurückliefern

Ich bestreite ja auch gar nicht, dass es dafür Anwendungsfälle gibt. Wäre trotzdem nicht meine erste Wahl ^^
 
AW: C/C++ zwei Werte zurückliefern

Ich sehe da eher das Problem in C++ das sie meinen alles von anderen Sprachen mit abzudecken und gerade der funktionale Teil ist ihnen imho nicht besonders gut gelungen bzw. hat eine sehr hässliche Syntax.
 
AW: C/C++ zwei Werte zurückliefern

Dafür, dass es eine hässliche Syntax ist, ist es eine geniale Lösung. Ich wundere mich immer wieder über diese Genialität, die diese Informatiker in solche Sachen stecken. Wenn man mal den ganzen Netzwerkkram im Detail betrachtet, gibt es da so viele "Hackfixes", wie man trotzdem noch mit älteren Geräten kompatibel sein kann.

Ich bleibe aber bei meinem Statement, dass es in den meisten Fällen einfach nicht sinnvoll ist, mehr als einen Wert zurückzugeben.
Die Diskussion um zusammengehörige Werte und Objekte aka Pointer erspare ich mir mal. :)
 
AW: C/C++ zwei Werte zurückliefern

Als C Hacker eine kleine Zwischenfrage: Was macht tuple dann überhaupt anders als einen struct inline zu definieren?
Nix. Nur Vorsicht mit dem Wort "inline"... würde lieber "implizit" sagen. Detailliert: Durch die Template-Instanziierung wird aus dem Typ-Konstruktur `tuple` wird ein realer Typ erzeugt.

Die Syntax von dem Kram ist jedenfalls merkwürdig, da würde ich doch lieber bei meinem alten struct bleiben wollen.
Tatsächlich ist das so... `get<0>(myTuple)` ist schon merkwürdig, um das erste Element zu bekommen... Aber wenn man ein Tuple aus einer Funktion bekommt, kann `tie` recht nett sein: tie - C++ Reference

Ich sehe da eher das Problem in C++ das sie meinen alles von anderen Sprachen mit abzudecken und gerade der funktionale Teil ist ihnen imho nicht besonders gut gelungen bzw. hat eine sehr hässliche Syntax.
Leider ja. Andererseits ...

Dafür, dass es eine hässliche Syntax ist, ist es eine geniale Lösung.
... stimme ich hier zu: C++ erlaubt quasi jeden Programmierstil... nicht jeden mit besonders hübscher Syntax, das ist klar. Aber allein, dass es möglich ist so etwas allein durch eine Library zu implementieren, ist beachtlich.
Aber klar, es ist kein Vergleich zu Sprachen, die tuple gleich in das Typsystem eingebaut haben, wie Rust:

Code:
fn func(m: i32) -> (i32, i32) {
    (3, 27)
}

fn main() {
    let (a, b) = func(3);
    println!("{}, {}", a, b);    // 3, 27
}

EDIT: Kurze Erklärung für Interessierte:
  • `i32` ist `int` mit 32 bits
  • `(i32, i32)` ist direkt ein gültiger Typ, nämlich ein tuple mit zwei `i32`
  • Funktionen werden so definiert: `fn function_name(arg_name: arg_type) -> return_type { ... }`
  • Es ist kein `return` in der Funktion, weil das letzte Statement in der Funktion impliziert zurückgegeben wird. Man könnte aber auch `return (3, 27);` schreiben
  • "{}" ist quasi wie "%d" in printf
  • Bei weiteren Fragen, fragt ;)
 
Zuletzt bearbeitet:
AW: C/C++ zwei Werte zurückliefern

Ich würde bei festen Bezeichnern für diesen Zweck ebenfalls Strukturen vorziehen, wobei es dadurch allerdings dazu führen kann, das die Funktionen zu spezifisch werden und die Wiederverwendbarkeit leidet. Die Frage ist nur, ob es in einer funktionalen/prozeduralen Sprache überhaupt anders geht. Bei OOP ist klar, das die Methoden mit den Eigenschaften eines Objekts arbeiten und somit ein einfacher Rückgabewert einer Methode ausreicht. Aber bei funktionaler/prozeduraler Programmierung geht das ja so nicht.

Ich finde, das die Wiederverwendbarbeit einer Funktion/Prozedur gerade heute sehr schwer zu definieren ist. Früher (anno 2000) durfte ich in alten Büchern von Anfang der 90er (z.B alte BASIC-Bücher) lesen, das Funktionen/Prozeduren immer mit einem Datentyp wiederverwendbar sein sollten. Ist meiner Meinung nach für die heutige Zeit völliger Quatsch und ich habe auch kein Buch mehr gelesen, in dem das so kommuniziert wurde. Ich sehe es eher so, das Funktionen/Prozeduren wegen der steigenden Komplexität Redundanz aus dem Quellcode nehmen sollen und dem Programmierer die Möglichkeit geben, diese Aufgaben zentraler zu verwalten. Ich habe nie ein/-e Informatikstudium/Ausbildung zum Anwendungsentwickler genossen und kenne daher den offiziellen Standpunkt der Industrie zu dem Thema nicht. Aber ich verwende Funktionen/Prozeduren so, wie ich es mir denke. Das führt natürlich dazu, das man sehr viele Funktionen/Prozeduren hat, die alle nur eine Aufgabe auf nur einen bestimmten Typ durchführen, dafür wird diese Funktionalität während der Laufzeit einer Anwednung aber unbestimmt oft verwendet. Das kann am Ende aber durchaus dazu führen, das es Funktionen/Prozeduren gibt, die alle statt nur einem Wert ganze Strukturen oder verschachtelte Listen/Maps zurückliefern können.

Ich denke genau wegen dieser Entwicklung ist die Objektorientierung heutzutage nicht mehr wegzudenken. OOP ist zwar nicht mein Fall. Aber ich betreibe programmieren sowieso nur als Hobby. Da kann ich meine Bastelprojekte auch so umsetzen, wie ich es möchte bzw. für richtig halte ;)

Aber als Tabuthema würde ich persönlich Funktionen mit mehreren Rückgabewerten nicht ansehen.
 
AW: C/C++ zwei Werte zurückliefern

Gerade bei OOP gibt es immer mehr recht radikale Meinungen. Z.B wird Vererbung ziemlich stark kritisiert (viele neueren Sprachen haben dieses Konzept auch gar nicht mehr, oder wenn nur sehr bedingt).

Funktionale Sprachen sind sehr stark im kommen, da Probleme (wie es oft in OO) Sprachen üblich ist, nicht in tausend Einzelteile gesplittet werden, sondern wenn Möglich direkt in einer Funktion gelöst werden. Entwickler können so ohne viel Code, viel Lösen was aber auch gleichzeitig ein Kritikpunkt ist, da der Code im Grunde um einiges schwerer Wartbar ist.

In Java finde ich den funktionalen Teil seit jdk 8 recht elegant gelöst.
 
AW: C/C++ zwei Werte zurückliefern

Gerade bei OOP gibt es immer mehr recht radikale Meinungen.
Ich finde es gibt in der Programmierung allgemein sehr viele radikale Meinungen. Eine Zeit lang durfte man nirgends mit prozeduraler/funktionaler Programmierung kommen. Man ist direkt in der Luft zerrissen worden. Eine Mischform aus OOP und funktionaler/prozeduraler Programmierung ging garnicht, was gerade bei Hilfsfunktionen in PHP bei vielen für Unmut sorgen. Wenn ich Datensätze aus einer Datenbank hole, dann finde ich es nicht so prickelnd, wenn die Strukturierung der Daten in jedem Objekt im gleichen Schema implementiert wird und somit für eine unnötige Redundanz sorgt. Statische Klassen waren das Ergebnis. Dann hätte man sich das auch sparen können. :lol:

Aber interessant zu sehen, das der Trend wieder zu den alten Tugenden geht. Und was die Wartbarkeit angeht. Wie gut der Code strukturiert und designed ist, hängt ja immernoch vom Programmierer ab ;)
 
Zurück