Forum: PC-Programmierung unterschiedliche Datentyp über einer Variable auslesen


von Kaiser K. (kingkong_18)


Lesenswert?

Hallo Zusammen,
ich habe gerade ein problem und hoffe, dass ich bei euch eine Lösung 
finden könnte.
und Zwar ich arbeite momentan auf ein Projekt, bei dem ich eine 
Kommunikation per Rs232 zwischen ein messgerät und ein computer aufbauen 
soll. Während der ausführung des Programms sollte das Messgerät bei 
Abfrage eines Parameters (Tastatur eingabe) den Wert des abgefragten 
Parameters ausgeben. Mein Problem jetzt besteht darin, dass die 
parameter von unterschiedlichen Typen (float, int, char, uzw...)sind und 
ich weiß nicht wie ich die über eine Variable (auf dem beigefügten 
programm heißt diese variable "value") auf die rs232 schicken bzw. 
auslesen kann. wie könnte ich die variable "value" definieren damit sie, 
je nachdem was gefragt wwird, alles parametertypen schickt bzw ausließt.


PS: das ist nur ein beispielprogramm um meine Frage ein bischen zu 
verdeutlichen.

#include <stdlib.h>
#include <stdio.h>
#include <time.h>



#define VALEUR_PAIN             2.55
#define VALEUR_CHOCOLATINE      3.90
#define VALEUR_BEURRE           5

union Boutique
{
    float pain;
    int chocolatine;
    long beurre;
} valeur;

int main()
{
    int value;
    char Command[20];

    while(1)
    {

        fgets(Command, sizeof(Command), stdin);

        if (0 == strcmp(Command, "pain\n"))
        {
                valeur.pain = VALEUR_PAIN;
                value = valeur.pain;
        }
        else if (0 == strcmp(Command, "chocolatine\n"))
        {
            valeur.chocolatine = VALEUR_CHOCOLATINE;
            value = valeur.chocolatine;
        }
        else if (0 == strcmp(Command, "beurre\n"))
        {
               valeur.beurre = VALEUR_BEURRE;
               value = valeur.beurre;
        }
        else
        {
            printf("invalid\n");
        }

        printf("%i\n", value);
    }
    return 0;
}

von foobar (Gast)


Lesenswert?

> wie könnte ich die variable "value" definieren damit sie,je nachdem
> was gefragt wwird, alles parametertypen schickt bzw ausließt.

Die einfachste Variante: die nimmst einen Typ, der alle Bereiche 
abdeckt. In deinem Fall böte sich ein float oder double an[1]. Notfalls 
ein String.

Alternativ nimmst du einen zusammengesetzten Typ[2], der zusätzlich ein 
Feld enthält, das Auskunft über den Typ gibt. In deiner Ausgaberoutine 
fragst du den Typ ab und behandelst den Wert entsprechend.

[1] evtl wird bei int/long gerundet - aufpassen.
[2]
1
   struct tval { int typ; union { float f; int i; char c; } val; };

von Zeno (Gast)


Lesenswert?

Kommunikation via RS232 geht doch i.d.R über Zeichen bzw. Zeichenketten 
die von einem Endezeichen begrenzt werden, letztendlich also 
Zeichenarrays (Strings). Wo liegt da jetzt das Problem? Du kannst doch 
jeden Deiner Datentypen problemlos in einen String konvertieren bzw. 
zurückkonvertieren. Du muß Dir jetzt eigentlich nur ein geeignetes 
Protokoll einfallen welches es ermöglicht die Daten zu unterscheiden. 
Dazu könnte man den eigentlichen Daten Präfix von einer definierten 
Anzahl von Zeichen voran stellen. Im einfachsten Fall ein 1 Zeichen, 
z.B. F für float, I für Integer usw.. Wie gesagt das können auch mehr 
Zeichen sein. Beim Senden mußt Du die Zeichen halt nur als Präfix 
einfügen und beim Empfang genau die Anzahl der als Präfix verwendeten 
Zeichen separieren. Je nach Präfix kannst Du dann die Folgedaten weiter 
verarbeiten und die Zeichenkette in einen Float oder was auch immer 
zurück verwandeln.

Das Messgerät - ist das was Fertiges oder eine Eigenkonstruktion. Bei 
ersterem kannst Du davon ausgehen, das da einfache Zeichenketten 
übertragen werden.

von Kaiser K. (kingkong_18)


Lesenswert?

> Das Messgerät - ist das was Fertiges oder eine Eigenkonstruktion. Bei
> ersterem kannst Du davon ausgehen, das da einfache Zeichenketten
> übertragen werden.

Das Messgerät ist ein fertiges.

von Kaiser K. (kingkong_18)


Lesenswert?

>    struct tval { int typ; union { float f; int i; char c; } val; };

bis hier komme ich klar. Danke.
Aber ich ich noch nicht verstehe ich halt die main-Funktion. also wie es 
dort weiter gehen sollte

von Niklas G. (erlkoenig) Benutzerseite


Lesenswert?

Siehe Serialisierung. Die Variante mit "union" ist in C 
implementation-defined und damit unportabel; in C++ ganz verboten.

von Dirk (Gast)


Lesenswert?

Zeig doch mal das RS232 Protokoll von deinem Multimeter.

von DPA (Gast)


Lesenswert?

Niklas G. schrieb:
> Siehe Serialisierung. Die Variante mit "union" ist in C
> implementation-defined und damit unportabel; in C++ ganz verboten.

Kompletter Blödsinn. Lies den Artikel selbst nochmal. Union ansich ist 
weder implementation defined noch verboten. Nur gewisse Arten, wie 
darauf zugegriffen wird, sind es. So wie es hier verwendet werden soll, 
nämlich Zuweisung und Auslesen immer vom jeweils korrespondierenden 
Member, ist es vollkommen unproblematisch und wohldefiniert.

von Niklas Gürtler (Gast)


Lesenswert?

DPA schrieb:
> Kompletter Blödsinn. Lies den Artikel selbst nochmal

Klar, meine eigenen Artikel les ich immer gerne! Der gezeigte Quelltext 
ist unproblematisch, sendet aber noch nichts an das Messgerät. Ich hatte 
den Verdacht, dass die gezeigte union dann noch zur "Konvertierung" 
genutzt werden soll. Ob man auf einer PC-Software nämlich sonst wirklich 
eine union braucht um die paar Bytes Speicher zu sparen, ist ohnehin 
fraglich.

von Kaiser K. (kingkong_18)


Lesenswert?

Hätte einer noch eine Idee?

von Niklas G. (erlkoenig) Benutzerseite


Lesenswert?

Was gefällt dir an den gezeigten Ideen nicht?

von foobar (Gast)


Lesenswert?

>>    struct tval { int typ; union { float f; int i; char c; } val; };

> bis hier komme ich klar. Danke.
> Aber ich ich noch nicht verstehe ich halt die main-Funktion. also wie es
> dort weiter gehen sollte
1
struct tval { int typ; union { float f; int i; char c; } val; };
2
#define TVAL_FLOAT 0
3
#define TVAL_INT 1
4
#define TVAL_CHAR 2
5
6
static void tval_print(struct tval *tv)
7
{
8
    switch (tv->typ) {
9
        case TVAL_FLOAT: printf("%f\n", tv->val.f); break;
10
        case TVAL_INT:   printf("%d\n", tv->val.i); break;
11
        case TVAL_CHAR:  printf("%c\n", tv->val.c); break;
12
        default:         printf("internal error 42\n");
13
    }
14
}
15
16
int main()
17
{
18
    struct tval tval;
19
    char Command[20];
20
21
    while(1)
22
    {
23
        fgets(Command, sizeof(Command), stdin);
24
25
        if (0 == strcmp(Command, "pain\n"))
26
        {
27
            tval.typ = TVAL_FLOAT;
28
            tval.val.f = VALEUR_PAIN;
29
        }
30
        else if (0 == strcmp(Command, "chocolatine\n"))
31
        {
32
            tval.typ = TVAL_FLOAT;
33
            tval.val.f = VALEUR_CHOCOLATINE;
34
        }
35
        else if (0 == strcmp(Command, "beurre\n"))
36
        {
37
            tval.typ = TVAL_INT;
38
            tval.val.i = VALEUR_BEURRE;
39
        }
40
        else
41
        {
42
            printf("invalid\n");
43
            continue;
44
        }
45
        tval_print(&tval);
46
    }
47
}

Aber irgendwie hab ich den Eindruck, dass das für deinen Fall unnötig 
kompliziert ist.

Mit einem Typ, der alle Werte abdeckt (hier String):
1
int main()
2
{
3
    char value[32];
4
    char Command[20];
5
6
    while(1)
7
    {
8
        fgets(Command, sizeof(Command), stdin);
9
10
        if (0 == strcmp(Command, "pain\n"))
11
        {
12
            sprintf(value, "%.3fkg", VALEUR_PAIN);
13
        }
14
        else if (0 == strcmp(Command, "chocolatine\n"))
15
        {
16
            sprintf(value, "%f", VALEUR_CHOCOLATINE);
17
        }
18
        else if (0 == strcmp(Command, "beurre\n"))
19
        {
20
            sprintf(value, "%d", VALEUR_BEURRE);
21
        }
22
        else
23
        {
24
            printf("invalid\n");
25
            continue;
26
        }
27
        printf("Ok, value is %s\n", value);
28
    }
29
}

von Kaiser K. (kingkong_18)


Lesenswert?

> Aber irgendwie hab ich den Eindruck, dass das für deinen Fall unnötig
> kompliziert ist.
>
> Mit einem Typ, der alle Werte abdeckt (hier String):

würde man das per Rs232 abfragen, das wüde das programm ganz anders 
aussehen oder?

nehmen wir an  wir hätten ein Gerät, das uns die gesuchte werte 
zurückgeben kann.

die Nachricht sollte vllt aus 8 Databits, 1 Stopbits, ohne parity und 
Flow control bestehen.

#define VALEUR_PAIN             0x20
#define VALEUR_CHOCOLATINE      0x21
#define VALEUR_BEURRE           0x22

von Ich (Gast)


Lesenswert?

Kaiser K. schrieb:
> würde man das per Rs232 abfragen, das wüde das programm ganz anders
> aussehen oder?
>
> nehmen wir an  wir hätten ein Gerät, das uns die gesuchte werte
> zurückgeben kann.

Wir müßen es annehmen, du weißt es - immerhin steht das Gerät ja vor 
dir.
Dazu wird es eine Doku geben, wie die RS232 Kommunikation abzulaufen 
hat. An die mußt du dich halten.
Wie du die Daten in deinem Programm nutzt, ist dann deine Sache. 
Persönlich würde ich die Lösung mit union bevorzugen, da die Umwandlung 
von einer Zeichenkette in den entsprechenden Datentyp dann nur einmal 
geschehen muß, ebenso die Umwandlung von deinem Datentypen in eine 
Zeichenkette.

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.