Hallo community,
ich hab da mal eine ganz einfache Frage, bin aber absoluter Anfänger.
ich habe ein struct:
struct Parameter
{
int Belichtungszeit
int Empfindlichkeit
int Blende
int Ausloesezeit
bool Blitz
}
nur mal als Beispiel
Jetzt habe ich in einem Array verschiedene Voreinstellungen gespeichert
und möchte mittels einer einheitlichen Set-Funktion einzelne Parameter
verstellen können.
void SetParameter(int ArrayIndex, #Eintrag aus dem struct# , int Wert)
kann ich das irgendwie mittels einer Funktion realisieren, oder
zumindest für einen Typ der Struct Parameter, z.B. für alle Ints oder
muss ich für jeden Struct-Eintrag eine eigene Set-Funktion haben.
Ich suche also das, was zwischen den Rauten stehen müsste.
Vielleicht kann mir ja jemand helfen, vielen Dank
Viele Grüße, Klaus
Klaus schrieb:> muss ich für jeden Struct-Eintrag eine eigene Set-Funktion haben.
Muss nicht, ist aber so die übliche Variante. Das nennt sich dann
Setter-Funktion. Eine Funktion für alles zu haben ist eher kompliziert,
denn es braucht eine Fallunterscheidung und Fehlerbehandlung.
foobar schrieb:> Normalerweise schreibt man einfach:array[i].Belichtungszeit = wert;
Das ist aber nicht sehr objektorientiert :-)
Wenn schon C++, dann richtig:
Dr. Sommer schrieb:> Das ist aber nicht sehr objektorientiert :-)
Zum Glück muss nicht alles objektorientiert sein ;-)
Dr. Sommer schrieb:> Natürlich sollte man Zahlen, die nie negativ sein dürfen, direkt als> "unsigned int" o.ä. definieren, dann kann man es gar nicht mehr falsch> machen.
Und natürlich sollte man dann auch die richtigen Warnungen anschalten,
weil
1
unsignedintfoo(unsignedintbaa)
2
{
3
returnbaa+2.0;
4
}
5
6
intmain()
7
{
8
returnfoo(-2);
9
}
ist legal in c/c++. gcc liefert 3 Warnungen mit -Wconversion oder 2 mit
-Wsign-conversion.
>struct Parameter>{> int Belichtungszeit> int Empfindlichkeit> int Blende> int Ausloesezeit> bool Blitz
---> std::string EinBeispiel <----
>}>>nur mal als Beispiel>>Jetzt habe ich in einem Array verschiedene Voreinstellungen gespeichert>und möchte mittels einer einheitlichen Set-Funktion einzelne Parameter>verstellen können.
und dann kommt plötzlich noch ein String als Parameter mit rein und dann
ist Ende mit deiner Einheits-Set-mit-int-Funktion, ab da fängt du dann
an zu basteln - solche Sachen sollte man immer bleiben lassen - deine
Funktion löst ein Problem das gar nicht exisitiert und schafft (falls
mal ein String dazu kommen) unlösbare Probleme
Erkläre doch erstmal WARUM du unbedingt eine einheitliche Set-Funktion
brauchst - falls es um direkt Anwendung im Code geht MUSST du sauber mit
deinen Settern/Gettern auf die einzelnen Elemente (typsicher) arbeiten -
das ist Pflicht
wenn die Daten aus einer Konfiguration oder sowas kommen - dann brauchst
du eben einen "Konverter" dazwischen der genau versteht wie A nach B
kommt - und der darf und muss sogar spezialisiert sein
Also warum willst du das machen? was denkst du bringt es dir?
ihr habt mich überzeugt.
Ich werde es mit einzelnen Set-Funktionen machen.
Ich dachte nur ich könnte irgendwie Code sparen damit, weil es ja
irgendwie immer das gleiche ist.
Ohne Reflection
(https://en.wikipedia.org/wiki/Reflection_(computer_programming)) kann
man aktuell um eine komplett generische Lösung nur herum arbeiten. Was
aber Beispielsweise möglich wäre, wäre compile-time Strings zur
Identifizierung zu übergeben. Das hätte zumindest keinen Runtime
Overhead:
Empfehlen würde ich trotzdem eher den klassischen Ansatz, vielleicht
durch verkettete Funktionsaufrufe etwas verschönert. Im Normalfall nimmt
einem eine vernünftige IDE die Arbeit fürs erzeugen von gettern und
settern ab.
Dein Ansatz scheint mir sehr datengetrieben zu sein:
Array mit Structen die Ints enthalten...
Wenn du C++ programmierst, wäre ein objektorientierter Ansatz
vielleicht besser, weil nach 1 Jahr liest sich dieser Code
@Klaus:
Bewertung der Lösungen von:
"Vincent H.: Perfekte Beispiele das es unsagbar viele Möglichkeiten gibt
um in C++ ein Problem zu lösen - oder auf die dunkle Seite der Macht zu
rutschen - das 1. Beispiel ist "nice" - was zum zeigen für C++03
Anhänger und das mit der Verkettung ist auch nur "sieht anders aus" ist
aber nicht wirklich Standard um dein einfaches Problem so zu lösen - ich
würde dir auf die Finger hauen wenn du mir so was kommst :)
"Dirk K.": Klar kannst du deine Parameter-Sätze in eine Map stecken und
per String addressieren - aber du kannst auch einfach nur die
Parameter(s?) Klasse ohne die Map verwenden
Bert3 schrieb:> @Klaus:>> Bewertung der Lösungen von:>> "Vincent H.: Perfekte Beispiele das es unsagbar viele Möglichkeiten gibt> um in C++ ein Problem zu lösen - oder auf die dunkle Seite der Macht zu> rutschen - das 1. Beispiel ist "nice" - was zum zeigen für C++03> Anhänger und das mit der Verkettung ist auch nur "sieht anders aus" ist> aber nicht wirklich Standard um dein einfaches Problem so zu lösen - ich> würde dir auf die Finger hauen wenn du mir so was kommst :)
Und was genau is da jetzt schlechter als an
Bert3 schrieb:> "Dirk K.": Klar kannst du deine Parameter-Sätze in eine Map stecken und> per String addressieren - aber du kannst auch einfach nur die> Parameter(s?) Klasse ohne die Map verwenden
Der TO hat davon gesprochen, mehrere Parametersätze
(Strukte) in einem Array vorzuhalten. Ich wollte nur
deutlich machen, dass ich eine std::map für den geeigneteren
Container halte.
merciless
Vincent H. schrieb:> Vincent H.Vincent H. schrieb:> Und was genau is da jetzt schlechter als an> void setXYZ(int);>> ?
ich würde nicht sagen das ein Fluent-Interface in diesem Fall typisch
ist d.h. viele Entwickler machen das nicht so und es hat auch absolut 0
Benefit - oder? eher die Lesbarkeit wird erschwert
Dirk K. schrieb:> Ich wollte nur> deutlich machen, dass ich eine std::map für den geeigneteren> Container halte.
das ist eben abhängig davon warum es bei ihm in einem Array steckt - ich
hab einfach schon zu viel map<string> code gesehen wo das einfach nur
aus Gewohnheit gemacht wurde, oftmals zu lasten der Performanz oder weil
jemand unbedingt einen Container haben wollte mit "lesbaren" Keys - ist
schön aber selten notwendig
Klaus schrieb:> void SetParameter(int ArrayIndex, #Eintrag aus dem struct# , int Wert)
du musst nicht für jeden struct-Element eine set-Funktion schreiben. Was
mir vorschwebt ist:
void SetParameter(int * Element, int Wert)
{
*Element = Wert;
}
Aufruf wäre dann:
SetParameter(&array[i].Belichtungszeit, 10);
wenn du in c++ programmierst, kannst du diese Funktion überladen und
auch den bool beschreiben:
void SetParameter(bool * Element, bool Wert)
{
*Element = Wert;
}
Der Aufruf wäre derselbe. also, fas derselbe:
SetParameter(&array[i].Blitz, TRUE);
Was soll den bitte (fuer seinen Fall) der Sinn hinter einer Funktion
sein die nichts anderes ist als eine Zuweisung - null unterschied dazu -
nur mehr schreibarbeit - gilt hier im forum fast nur noch die regel:
wenn es kompiliert und laeuft ist es gut und sollte praesentiert werden?
So ist das Programm gut strukturiert und bleibt trotzdem sehr flexibel,
weil man für neu hinzugekommene struct-Elemente mit anderem Datentyp
einfach eine neue Überladung der GetParameter() Funktion hinzufügen
kann.
Und was ist der Vorteil der Nutzung deiner Funktion gegenüber einer
trivialen Zuweisungen? Läuft hier gerade ein mit
Laserkannonen-auf-Spatzen-schiessen -Kontest und ich habe den
Startschuss verpasst :-)
Experte schrieb:> Konstantin G. schrieb:>> void SetParameter>> Zusätzlich kann man aus Symmetriegründen eine überladene Auslesefunktion> ...
Der Beitrag soll ironisch gemeinet sein oder? Anders kann ich mir
1
bool*i_pbTheParameterToCheck
oder
1
if(true==(*i_pbTheParameterToCheck==true)){
2
}
und vor allem
Experte schrieb:> So ist das Programm gut strukturiert und bleibt trotzdem sehr flexibel,
nicht erklären.
Bert3 schrieb:> Was soll den bitte (fuer seinen Fall) der Sinn hinter einer Funktion> sein die nichts anderes ist als eine Zuweisung - null unterschied dazu -> nur mehr schreibarbeit - gilt hier im forum fast nur noch die regel:> wenn es kompiliert und laeuft ist es gut und sollte praesentiert werden?
vielleicht geht es hier dem fragenden ums Prinzip, um die
Funktionsweise. Er ist ja Anfänger...
Sein Fall ist vielleicht gar nicht mal so simpel. Das wissen wir nicht.
Er hat vielleicht sein Problem aufs wesentliche runtergebrochen und eine
konkrete Frage daraus gemacht.
Wie dem auch sei, er kennt jetzt sowohl Ihren Standpunkt, als auch
einige Lösungsmöglichkeiten bei solchen Problemstellungen...
Konstantin G. schrieb:> vielleicht geht es hier dem fragenden ums Prinzip, um die> Funktionsweise. Er ist ja Anfänger...>> Sein Fall ist vielleicht gar nicht mal so simpel. Das wissen wir nicht.> Er hat vielleicht sein Problem aufs wesentliche runtergebrochen und eine> konkrete Frage daraus gemacht.
Assumptions is the mother of all screw ups.
>vielleicht geht es hier dem fragenden ums Prinzip, um die>Funktionsweise. Er ist ja Anfänger...
Das von dir gezeigte Beispiel erfüllt 1. keinen Zweck, ist 2. sogar für
den Nicht-Zweck zu kompliziert geschrieben - was soll das helfen?
Klar gibt es hier viel Noobs - aber die Antworten und Tips die teilweise
hier zu lesen sind vermitteln mir das Gefühl das DER schlechte
Prof/Berufsschullehrer nach dem Unterricht noch als Hobby weiter seine
"Weisheiten" im Internet verbreitet
Er braucht einfache Set und Gets - thats it, alles andere hier gezeigte
ist "DER schlechte Prof/Berufsschullehrer"-Stil, egal was eure Intension
war
Bert3 schrieb:> Das von dir gezeigte Beispiel erfüllt 1. keinen Zweck
Der Zweck ist: Einen Wert einem Element eines struct aus einem array
zuzuweisen. Und das tut es. Man kann den Aufruf einzeln anwenden, oder
in eine Schleife packen.
Bert3 schrieb:> ist 2. sogar für> den Nicht-Zweck zu kompliziert geschrieben
noch einfacher geht's hier gar nicht, nur noch direkt, ohne eine
Unterfunktion daraus zu basteln, was du vorschlägst.
noch mal, ich bin nicht gegen das direkte Schreiben. Nur wenn es
unbedingt sein muss (Unterfunktion), z.b. wenn das Schreiben aus einem
anderen Modul passieren soll und die Schnittstelle eben nur aus
Funktionen zu bestehen hat. Dann ist mein Beispiel die erste Wahl,
zumindest für mich. Wer mir noch bessere/elegantere/schönere/... Lösung
zeigen möchte - ich lerne gerne was dazu!
>Der Zweck ist: Einen Wert einem Element eines struct aus einem array>zuzuweisen. Und das tut es. Man kann den Aufruf einzeln anwenden, oder>in eine Schleife packen.
ich bin mir ja nicht sicher ob du deinen eigenen Code liesst:
1
voidSetParameter(bool*Element,boolWert)
2
{
3
*Element=Wert;
4
}
deine GetParameter Funktion lass ich mal weg weil die sich in
Sinnlosigkeit nicht mehr übertreffen lässt
1
SetParameter(&array[i].Blitz,true);
ist zu 100% das gleiche wie
1
array[i].Blitz=true;
nur "komplizierter"
dein Setter verbirgt nichts, abstrahiert nicht den Zugriff oder macht
sonst irgend etwas was die Existenz der Funktion rechtfertigt - ausser:
Das es eine Funktion ist
Dem Thread-Starter war schon nach dem 3. Post klar das er wohl in die
falsche Richtung denkt und einfach simple Setter/Getter braucht (weil
ehr von C++ spricht) - wo ich ihm zustimme, was du hier postest sind
nicht mehr als kompilierbare Beispiele die irgendwas setten/getten -
irgendwie...
Bert3 schrieb:> deine GetParameter Funktion lass ich mal weg weil die sich in> Sinnlosigkeit nicht mehr übertreffen lässt
welche GetParameter Funktion? du verwechselst mich mit jemanden!
sinnvoll wäre es
die Information wie die Blende und Zeit als int abgebildet wird auch in
die Struktur zu packen und bei ein und Ausgabe zu berücksichtigen.
Bert3 schrieb:> Dem Thread-Starter war schon nach dem 3. Post klar das er wohl in die> falsche Richtung denkt und einfach simple Setter/Getter braucht (weil> ehr von C++ spricht) - wo ich ihm zustimme
und dennoch macht er die Unterfunktionen. Und du stimmst im auch zu.
Also macht er eine Set-Funktion pro Element des structes. Mein Vorschlag
ist EINE (evtl überladene) Set-Funktion für alle Elemente des structes.
Experte schrieb:> GetParam
Sorry, ja mit "Experte (Gast)" Post:
Beitrag "Re: C++ Anfängerfrage struct">und dennoch macht er die Unterfunktionen. Und du stimmst im auch zu.>Also macht er eine Set-Funktion pro Element des structes. Mein Vorschlag>ist EINE (evtl überladene) Set-Funktion für alle Elemente des structes.
Weil er dachte er müsste das irgendwie schöner/besser machen
class Parameter
{
int p1;
bool p2;
float p3;
//jetzt noch die setter/getter
SetP1
GetP1
...
}
SetParameter(Parameter p)
Parameter GetParameter()
oder
Parameter p;
p.setBlitz(10);
selbst die einzelenen Parameter als Objekte/Template-Properties etc. zu
formulieren (mit Zuweisungsoperator usw.) ist einfach viel zu viel für
den Anwendungsfall
mh schrieb:> Der Beitrag soll ironisch gemeinet sein oder?
Natürlich karikiert der Beitrag den anderen mit SetParameter.
Wahrscheinlich ist jener eine noch besser getarnte Trollierung, auf die
ich auch reingefallen bin.
Konstantin G. schrieb:> Bert3 schrieb:>> Das von dir gezeigte Beispiel erfüllt 1. keinen Zweck>> Der Zweck ist: Einen Wert einem Element eines struct aus einem array> zuzuweisen. Und das tut es.
Das tut eine einfache Zuweisung ohne diese Funktion genauso gut. Die
Funktion macht es nur umständlicher, ohne jeglichen Nutzen.
Setter und Getter sind normalerweise dazu da, dass ich z.B. darin
Vorbedingungen prüfen kann oder nötige Aktionen auslösen, und damit ich
die interne Struktur der Daten auch ändern kann, ohne das Interface mit
ändern zu müssen. Naturgemäß ist das nicht für jedes Element eines
bestimmten Typs gleich, daher braucht man für jedes einen eigenen Setter
und Getter.
Deine Funktion erfüllt daher keinen dieser Zwecke und ist somit
vollkommen überflüssig.
> Bert3 schrieb:>> ist 2. sogar für den Nicht-Zweck zu kompliziert geschrieben>> noch einfacher geht's hier gar nicht, nur noch direkt, ohne eine> Unterfunktion daraus zu basteln, was du vorschlägst.
Richtig.
> noch mal, ich bin nicht gegen das direkte Schreiben. Nur wenn es> unbedingt sein muss (Unterfunktion), z.b. wenn das Schreiben aus einem> anderen Modul passieren soll und die Schnittstelle eben nur aus> Funktionen zu bestehen hat.
Sie besteht aber leider nicht nur aus Funktionen, denn du musst ja die
Adresse der internen Variablen, die du beschreiben willst, als Parameter
übergeben. Soll die Schnittstelle unbedingt nur aus der Funktion
bestehen, und man will wirklich nur eine Funktion pro Typ, dann wäre
eher die Variante mit einem enum und in der Funktion dann mit
switch/case zu bevorzugen. So braucht der Aufrufer dann wenigstens keine
Interna der Struktur zu kennen.
Rolf M. schrieb:> Sie besteht aber leider nicht nur aus Funktionen, denn du musst ja die> Adresse der internen Variablen, die du beschreiben willst, als Parameter> übergeben.
stimmt
Rolf M. schrieb:> So braucht der Aufrufer dann wenigstens keine> Interna der Struktur zu kennen.
stimmt, der muss den Aufbau der Struktur kennen...
Also als reiner Setter eignet sich das nicht, habt ja Recht. Aber
vielleicht wenn er da noch etwas code mit rein packt, irgendwelche
Umrechnungen oder so.
Ich habe mich einfach nur auf die Fragestellung konzentriert. Er wollte
ja eine allgemeine Unterfunktion, wie man's machen kann..
Dr. Sommer schrieb:> Was ist denn der Unterschied zwischen einer Funktion und einer> Unterfunktion?
Eigentlich keiner, nur dass die Unterfunktion von der Funktion
aufgerufen wird.
Bei Personenhierarchien ist es ähnlich:
https://www.youtube.com/watch?v=KFXcUr8jEsw
Johnny B. schrieb:> Eigentlich keiner, nur dass die Unterfunktion von der Funktion> aufgerufen wird.
Dann sind eigentlich alles Unterfunktionen bis auf den Reset-Handler des
(ROM-)Boot-Codes, da der von der Hardware statt einer anderen Funktion
"aufgerufen" wird?
Dr. Sommer schrieb:> Johnny B. schrieb:>> Eigentlich keiner, nur dass die Unterfunktion von der Funktion>> aufgerufen wird.>> Dann sind eigentlich alles Unterfunktionen bis auf den Reset-Handler des> (ROM-)Boot-Codes, da der von der Hardware statt einer anderen Funktion> "aufgerufen" wird?
Absolute Sichtweise, nicht gerade praktikabel, oder?
Hallo,
ich lehne mich mal aus dem Fenster und behaupte, dass es das Wort
„Unterfunktion” nicht gibt. Ich denke, das ist ein verdödelter
Anglizismus.
Damals (TM) gab es ja GOSUB in Basic oder subroutine in Fortran, was ja
auf ein "unter" hindeutet.
Diese ausführbaren Untereinheiten hießen zum Beispiel Unterprogramm, ein
Wort, dass aber in meiner Erinnerung recht schnell unmodern wurde,
Prozedur oder Funktion kamen in Mode, auch wenn zB in Fortran subroutine
nicht das selbe wie function ist.
So oder so bezeichnete Funktion beim Programmieren schon immer eine
ausführbare Untereinheit. Unter-Funktion ist also doppelt gemoppelt und
einfach eine gedanklich schlampige Reminiszenz an Dinge wie subroutine
oder Unterprogramm.
Wenn überhaupt würde das Wort Sinn ergeben für ein Lambda im Lambda oder
für nested functions in Python oder Swift oder so ...
So sehe ich das.
Vlg
Timm
Timm R. schrieb:> ich lehne mich mal aus dem Fenster und behaupte, dass es das Wort> „Unterfunktion” nicht gibt. Ich denke, das ist ein verdödelter> Anglizismus.
Vermutlich ist es eine Mischung aus "Funktion" und dem bei manchen
Programmieranfängern der "alten Schule" beliebten "Unterprogramm".
Der Begriff wurde vor etlichen Jahrzehnten gelehrt, damals, als die
Sprache mit dem "GOSUB" der dernier cri war.