Forum: Mikrocontroller und Digitale Elektronik 2 funktionen vereinen


von Mike (Gast)


Lesenswert?

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;
}

von Mike (Gast)


Lesenswert?

Ich meine eigentlich:

Ich möchte eigentlich eine Funktion, bei der ich SUM

UND

eines der beiden folgenden (Median oder Val) eingeben kann.

von jemand (Gast)


Lesenswert?

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?

von Mike (Gast)


Lesenswert?

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

von Rufus Τ. F. (rufus) Benutzerseite


Lesenswert?

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.

von Sven B. (scummos)


Lesenswert?

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 
...

von Mike (Gast)


Lesenswert?

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.

von Dergute W. (derguteweka)


Lesenswert?

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

von S. R. (svenska)


Lesenswert?

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.

von jemand (Gast)


Lesenswert?

"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...

von Framulestigo (Gast)


Lesenswert?

Oder wechsel auf C++ und überlade den + Operator.

von Sven B. (scummos)


Lesenswert?

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?

von Mike (Gast)


Lesenswert?

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)

1
uint16_t testzahl = 0;
2
typedef struct sum
3
{
4
uint16_t a;
5
uint8_t  b;  
6
}aaa_t;
7
8
typedef struct combine
9
{
10
MEDIAN median;
11
CURRENTVALUE Val;
12
}values_t;
13
14
aaa_t sum;
15
values_t Val;
16
17
void teste(void* sum, values_t* var);
18
19
void teste(void* sum, values_t* var)
20
{
21
aaa_t* p;
22
    
23
if(p->a == (uint16_t) sum)
24
{
25
Sum->S1 += var->median->S1;
26
Sum->S2 += var->median->S2;
27
Sum->S3 += var->median->S3;
28
}else
29
{
30
Sum->S1 += var->Val->S1;
31
Sum->S2 += var->Val->S2;
32
Sum->S3 += var->Val->S3;
33
}
34
  
35
}
36
37
int main(void)
38
{
39
40
sum.a = 100;
41
sum.b = 200;
42
teste((void*)&sum.a);
43
44
C-Code

von Dergute W. (derguteweka)


Lesenswert?

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

von A. S. (Gast)


Lesenswert?

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

von Mike (Gast)


Lesenswert?

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?

von Stefan F. (Gast)


Lesenswert?

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
void calculateSum(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.

von Alex G. (dragongamer)


Lesenswert?

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.

von zitter_ned_aso (Gast)


Lesenswert?

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:
1
//Definition
2
3
struct math_object{
4
  uint32_t x,
5
           y,
6
           z;
7
};
8
9
struct math_object sum={...};
10
struct math_object median={...};
11
struct math_object current_values={...};
12
13
void calculate_sum( struct math_object* p_sum, struct math_object* p_med_or_val)
14
{
15
   p_sum->x += p_med_or_val->x;
16
   p_sum->y += p_med_or_val->y;
17
   p_sum->z += p_med_or_val->z;
18
}
19
20
...
21
22
//Aufruf
23
24
calculate_sum(&sum, &median);
25
calculate_sum(&sum, &current_values);

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?

von zitter_ned_aso (Gast)


Lesenswert?

zitter_ned_aso schrieb:
> Anscheind wird hier nur eine der beiden Strukturen gleichzeitig
> verwendet

Ähm, also nicht beide gleichzeitig ;-)

von A. S. (Gast)


Lesenswert?

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?

von S. R. (svenska)


Lesenswert?

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
void do_sum(int cmd, 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
  } else if (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
struct MyStruct {
2
  int type;
3
  union {
4
    struct AvgStruct as;
5
    struct MedianStruct ms;
6
  };
7
};
8
9
void do_sum(struct MyStruct data) {
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
  } else if (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.

von P. S. (namnyef)


Lesenswert?

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?

von Stefan F. (Gast)


Lesenswert?

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).

von Einer K. (Gast)


Lesenswert?

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...

von gdfgsdgsg (Gast)


Lesenswert?

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
1
struct median{
2
uint16_t S1,
3
         S2,
4
         S3;
5
};
6
7
8
struct sum{
9
uint32_t S1,
10
         S2,
11
         S3;
12
};
13
14
#define CalcMemberSum( x ,  y )    do{ \
15
                    x->S1 += y->S1; \
16
                    x->S2 += y->S2; \
17
                    x->S3 += y->S3; \
18
                  }while(0);
19
20
/**/
21
   struct median t1 ;
22
    struct sum    t2 ;    
23
    CalcMemberSum( t2  , t1) ;
24
25
/* Makro expansion 
26
do{ \
27
                    t2->S1 += t1->S1; \
28
                    t2->S2 += t1->S2; \
29
                    t2->S3 += t1->S3; \
30
                  }while(0);
31
*/
32
33
34
//oder auch:
35
#define CalcMember_uint( x ,  y )    do{ \
36
                    x  = y->S1; \
37
                    x += y->S2; \
38
                    x += y->S3; \
39
                  }while(0);
40
41
    uint64_t qsum;
42
    CalcMember_uint( qsum , t2 );
43
/* Makro expansion
44
do{ \
45
                    qsum  = t2->S1; \
46
                    qsum += t2->S2; \
47
                    qsum += t2->S3; \
48
                  }while(0);
49
*/

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.