Hallo
Ich habe 2 ähnliche Funktionen, die ich versuche zu einer Funktion zu
machen. Leider fällt mir keine gescheite Lösung ein.
Ich möchte eigentlich eine Funktion, bei der ich entweder SUM oder eines
der beiden folgenden (Median oder Val) eingeben kann. Dann berechnet mir
die Funktion anhand des eingegebenen Parameters die Summe.
Ist das irgendwie zu bewerkstelligen?
void calculateSum(SUM *Sum, MEDIAN *Median)
{
Sum->S1 += Median->S1;
Sum->S2 += Median->S2;
Sum->S3 += Median->S3;
}
void calculateSumhigh(SUM *Sum, CURRENTVAL *Val)
{
Sum->S1 += Val->S1;
Sum->S2 += Val->S2;
Sum->S3 += Val->S3;
}
Kompiliert das so? Was sind SUM, MEDIAN und CURRENTVAL denn für
Datentypen? Die müssen ja irgendwo definiert sein.
Um welche Sprache geht's überhaupt?
Optionale Parameter?
jemand schrieb:> Kompiliert das so? Was sind SUM, MEDIAN und CURRENTVAL denn für> Datentypen? Die müssen ja irgendwo definiert sein.>
Das sind structs mit Inhalten
zB
struct median{
uint16_t S1,
S2,
S3;
};
struct sum{
uint32_t S1,
S2,
S3;
};
typedef struct median MEDIAN;
typedef struct sum SUM;
die anderen sehen Gleich aus
> Um welche Sprache geht's überhaupt?
es geht um C
> Optionale Parameter?
Ja
Auch wenn die Strukturelemente den gleichen Namen haben, haben sie doch
einen unterschiedlichen Typ, und damit lässt sich nicht eine Funktion
schreiben, die beide Strukturen auf gleiche Weise behandelt.
Deine structs sind auch komisch. Was tut eine struct mit Namen "median"?
Warum nicht "Vector3" oder so?
Kann schon sein dass das so Sinn macht, aussehen tut es aber nicht so
...
Ich glaube ihr seht das Problem einfach zu spezifisch.
Ich möchte einfach wissen, wie ich es machen kann, dass es funktioniert
oder was ich abändern muss.
Es ist doch im Moment egal, wie meine structs aussehen.
Meinetwegen nehmt ihr halt ein anderes Beispiel und zeigt mir bitte wie
es funktioniert.
Moin,
Mike schrieb:> Ich möchte einfach wissen, wie ich es machen kann, dass es funktioniert> oder was ich abändern muss.
Nimm den selben Typ fuer MEDIAN und CURRENTVAL. Eine 32 bit Addition ist
halt was anderes als eine 16 bit Addition; hilft nix, das laesst sich
nicht "schoen" in eine einzelne Funktion quetschen.
Gruss
WK
Gib deiner Funktion einen Parameter "void* data" und einen Parameter
"int type" und caste innerhalb der Funktion auf den korrekten Typen.
Das ist zwar ein Zeichen von besonders qualitativ auffälligem Code, aber
es funktioniert.
"es, es, es" Was ist denn "es".
Mike schrieb:> Ich glaube ihr seht das Problem einfach zu spezifisch.
Na wir sehen eben nur, was du postest. Und aus dem wird nicht klar, was
"es" eigentlich ist...
Mike schrieb:> Ich glaube ihr seht das Problem einfach zu spezifisch.
Ne, du siehst das Problem zu allgemein. Diese "angenommen ich habe
Klasse X mit Memberfunktionen Foo und Bar und will Y"-Diskussionen
führen zu nichts beim programmieren. Jeder Leser vermutet einen anderen
Kontext und dann wird ewig gezankt, welche Lösung die tollste ist,
obwohl das ohne den (unbekannten) Kontext nicht sinnvoll beurteilt
werden kann.
Was ist konkret das Problem, was du lösen willst?
Sven B. schrieb:> Mike schrieb:>> Ich glaube ihr seht das Problem einfach zu spezifisch.>> Ne, du siehst das Problem zu allgemein. Diese "angenommen ich habe> Klasse X mit Memberfunktionen Foo und Bar und will Y"-Diskussionen> führen zu nichts beim programmieren. Jeder Leser vermutet einen anderen> Kontext und dann wird ewig gezankt, welche Lösung die tollste ist,> obwohl das ohne den (unbekannten) Kontext nicht sinnvoll beurteilt> werden kann.>> Was ist konkret das Problem, was du lösen willst?
Ich möchte so etwas erreichen wie unten angedeutet im Programm.
abhängig von sum.a oder sum.b möchte ich unterschiedliche Berechnungen
durchführen, indem ich verschiedene Parameter nutze.
Wie ich verschiedene Parameter in einer Funktion nutzen kann, habe ich
schon gelöst, indem ich die Parameter in einen separaten struct vereine.
Ich habe das Problem auch fast gelöst, aber
aber der compiler meckert mir hier:
if(p->a == (uint16_t) sum)
Moin,
Aber wozu soll der ganze Affenzirkus gut sein? Das wird doch dadurch
weder schneller noch uebersichtlicher. Klar, mit Gewalt kann man 2
unterschiedliche Funktionen auch in C so zusammenmanschen, dass der
compiler nicht mehr mosert. Aber das bringt doch nix.
Bei "hoeheren" Programmiersprachen als C kann man das auch prima
verschleiern, so dass der unbedarfte Codeleser evtl. garnicht merkt,
dass das verschiedene Variablentypen mit verschiedener Groesse sind, die
dann von verschiedenen Funktionen verwurstet werden - wenn man das
unbedingt als Vorteil sehen muss.
Mir waer's aber lieber, dass ich als unbedarfter Codeleser das auch
mitkrieg', dass das unterschiedliche Typen sind.
Das ist doch so, wie wenn ich eine einzige Funktion namens
lese(irgendwas)
baue, die als Argument dann Buch, MuellAuf, und Weintrauben frisst.
Das ist Quatsch sowas zusammenzulegen.
Gruss
WK
Dein Code gibt keinen Sinn. Kompilieren kann er auch sonst nicht.
Entweder Du übergibt der Funktion einfach den Pointer, den sie braucht
Oder Du übergibst ihr die Obermenge + eine Art Kommando (wenn 1, dann
diesen, wenn 2, dann jenen, ...)
Oder Du postest einen kompilierbaren Code und beschreibst, was Du machen
möchtest
A. S. schrieb:>> Oder Du postest einen kompilierbaren Code
wenn ich das könnte waere ich nicht hier
>und beschreibst, was Du machen> möchtest
Ich habe es nun schon 2 mal formuliert was ich machen möchte.
Ist das jetzt wirklich so schwer zu verstehen?
Wieso sagt hier niemand wie es geht anstatt zu sagen wie es nicht geht?
Mike schrieb:> Ich habe es nun schon 2 mal formuliert was ich machen möchte.> Ist das jetzt wirklich so schwer zu verstehen?> Wieso sagt hier niemand wie es geht anstatt zu sagen wie es nicht geht?
Weil es in C nicht geht. Dein "ich will aber" bringt nichts.
Wenn deine beiden Strukturen gleich sind, kannst du einen Zeiger casten:
1
voidcalculateSum(SUM*Sum,void*foo)
2
{
3
Sum->S1+=(Median*)foo->S1;
4
Sum->S2+=(Median*)foo->S2;
5
Sum->S3+=(Median*)foo->S3;
6
}
Diese Funktion kannst du sowohl mit Median als auch mit Val aufrufen.
Schön ist das aber nicht, und wehe, die beiden Strukturen sind nicht
gleich, dann kommt dabei Müll heraus.
Framulestigo schrieb:> Oder wechsel auf C++ und überlade den + Operator.
Oder in C++ dann Vererbung, falls das Sinn macht.
Trauben und Bücher zusammen zu legen ist dann noch immer sinnlos,
aber Trauben und Orangen mit "Früchte" als "parent" macht Sinn.
Die Funktion akzeptiert dann alle Früchte.
In C geht das aber wie schon erwähnt wurde nicht.
Dergute W. schrieb:> Nimm den selben Typ fuer MEDIAN und CURRENTVAL.
Das war doch eine gute Idee. Oder gar für alle drei Variablen eine
einzige Struktur als Datentyp.
So etwas:
Mike schrieb:> typedef struct combine> {> MEDIAN median;> CURRENTVALUE Val;> }values_t;
Anscheind wird hier nur eine der beiden Strukturen gleichzeitig
verwendet (if- else-Test in der test()-Funktion) - "union" statt
"struct" sinnvol?
Mike schrieb:> wenn ich das könnte waere ich nicht hier
Wenn du überhaupt nicht in der Lage bist, einen compilierbaren Code als
Ausgangspunkt für deine Wünsche zu Posten, .... heißt das, Du
beschäftigst Dich nur theoretisch und programmierst gar nicht?
Es gibt zwei Möglichkeiten:
Du kannst der Funktion beliebige Strukturen geben und castest innerhalb
der Funktion auf die jeweils korrekte Struktur. Aber du übergibst einen
Zeiger.
1
voiddo_sum(intcmd,void*data){
2
if(cmd==0){
3
AvgStruct*as=(AverageStruct*)data;
4
as->sum+=as->a;
5
as->sum+=as->b;
6
as->sum+=as->c;
7
}elseif(cmd==1){
8
MedianStruct*ms=(MedianStruct*)data;
9
ms->sum+=ms->a;
10
ms->sum+=ms->b;
11
ms->sum+=ms->c;
12
}else{
13
abort();
14
}
15
}
Du kannst eine Struktur benutzen, die beide Varianten enthält. Die
Funktion kriegt keinen Zeiger, ist also langsamer.
1
structMyStruct{
2
inttype;
3
union{
4
structAvgStructas;
5
structMedianStructms;
6
};
7
};
8
9
voiddo_sum(structMyStructdata){
10
if(data.type==0){
11
data.as.sum+=data.as.a;
12
data.as.sum+=data.as.b;
13
data.as.sum+=data.as.c;
14
}elseif(data.type==1){
15
data.ms.sum+=data.ms.a;
16
data.ms.sum+=data.ms.b;
17
data.ms.sum+=data.ms.c;
18
}else{
19
abort();
20
}
21
}
Es ist definitiv nicht sinnvoll möglich, einer Funktion zwei
unterschiedliche Datentypen geben zu wollen. Zeiger auf unterschiedliche
Datentypen geht.
Mike schrieb:> Wieso sagt hier niemand wie es geht anstatt zu sagen wie es nicht geht?
Weil das, was du willst nicht geht.
Dein Ansatz ist schlicht bescheuert.
Du hast jetzt aber genug Möglichkeiten bekommen, wie du etwas fast
ähnliches machen kannst, dir also selbstständig gründlich in den Fuß
schießen kannst.
Läuft hier wieder ein Wettbewerb wer den unleserlichsten und
unwartbarsten Code fabriziert?
Warum nicht einfach verschiedene Dinge auch von verschiedenen Funktionen
- am besten möglichst atomar und ohne Seiteneffekte - erledigen lassen?
P. S. schrieb:> Warum nicht einfach verschiedene Dinge auch von verschiedenen Funktionen
Das sehe ich auch so. Selbst bei C++ handhabe ich das weitgehend so.
Anstatt Operatoren zu überladen, schreibe ich lieber Methoden mit
eindeutigen Namen. Das macht den Code besser lesbar.
Der einzige Operator, den ich oft zwangsläufig überladen muss, ist der
Copy-Konstruktor (falls man den als Operator bezeichnen möchte).
Mike schrieb:> Ich habe es nun schon 2 mal formuliert was ich machen möchte.> Ist das jetzt wirklich so schwer zu verstehen?
Ja!
Du bist auf deinem Weg falsch abgebogen und stehst jetzt vor einer
Schlucht.
Also 1km zurück, und das Problem nochmal beschreiben, vielleicht gibt es
alternative Wege.
Mike schrieb:> Wieso sagt hier niemand wie es geht anstatt zu sagen wie es nicht geht?
Weil das Problem schon falsch ist.
Tief im Kern.
Mike schrieb:> struct median{> uint16_t S1,> S2,> S3;> };
Sowas verursacht bei mir Pickel.
Hier wird eine Struktur für etwas verwendet, wo doch eher ein Array das
richtige wäre.
Die Marotte, Dinge durch zu nummerieren, gehört ausgemerzt, bevor sie
sich noch in den Hirnwindungen fest frisst.
Stefanus F. schrieb:> Das sehe ich auch so. Selbst bei C++ handhabe ich das weitgehend so.> Anstatt Operatoren zu überladen, schreibe ich lieber Methoden mit> eindeutigen Namen. Das macht den Code besser lesbar.
Templates....
Wenn sich Funktionen nur in den Datentypen unterscheiden...
Mike schrieb:> void calculateSum(SUM *Sum, MEDIAN *Median)> {> Sum->S1 += Median->S1;> Sum->S2 += Median->S2;> Sum->S3 += Median->S3;> }>> void calculateSumhigh(SUM *Sum, CURRENTVAL *Val)> {> Sum->S1 += Val->S1;> Sum->S2 += Val->S2;> Sum->S3 += Val->S3;> }
wenn die funktionen nur das tun ...
mach ein makro draus.
Wenn der compiler das nicht schon selbst tut.
Dem Makro ist es egal welcher typ