Forum: PC-Programmierung gefundenen Wert in Struktur ablegen (nur wie?)


von Thomas (Gast)


Lesenswert?

Hallo Gemeinde.

Hintergrund: Ich lese eine Datei mit Werten ein. Die Datei sieht z.B. so 
aus:

WERT1: 3
WERT2: 5
WERT3: 10
WERT4: 3.1415

Diese Werte aus eben dieser Datei sollen nun an die entsprechende Stelle 
innerhalb der aktuellen Struktur abgelegt werden:

struct meineZahlen
{
   UINT32 zahl1;
   UINT32 zahl2;
   UINT32 zahl3;
   float  zahl4;
}

Soll bedeuten: Wenn ich die Datei nach WERT4 durchsuche, soll mir der 
Wert 3.1415 an die Stelle .zahl4 innerhalb meiner aktuell gültigen 
Strukur, dessen Adresse ich an eine Unterfunktion übergeben habe, 
abgelegt werden.

Ein Funktionsaufruf sieht z.B. so aus:
main(void)
{
   meineZahlen *aktZahlen;
   search("WERT4", &aktZahlen);

   meineZahlen *neueZahlen;
   search("WERT2", &neueZahlen);
}

Ziel:
aktZahlen.zahl4 = 3.1415;
neueZahlen.zahl2 = 5;

Wie muss die Fkt search() aussehen, damit mir dies gelingt?

Die Zuordnung soll hierbei allerdings nicht über eine riesige Switch- 
oder if-Verschachtelung a la

Struktur.zahl1 = Wert;
Struktur.zahl2 = Wert;
...

erfolgen, da die Struktur ziemlich riesig wird.

Kann ich die Strukturelemente irgendwie über eine Lookup-Table 
ansprechen, in der die Information über das "mapping" hinterlegt sind?
Darin würde stehen, dass z.B. immer

WERT2 --> .zahl2
WERT4 --> .zahl4

innerhalb der aktuellen Struktur, abgelegt werden soll.

Ich brauche dringend Hilfe hierbei.

Vielen Dank erst einmal.
Thomas

von Klaus W. (mfgkw)


Lesenswert?

1. Hausaufgabe? Oder wozu das Ganze?

2. main() funktioniert icht; die struct existieren gar nicht.

3. Soll immer dieselbe Datei durchsucht werden?
Dann ist es doch schlauer, einmal am Anfang alle Werte zu lesen und bei 
Bedarf nur noch aus dem Speicher zu holen.
Wenn nicht: woher soll die Funktion wissen, aus welcher Datei sie lesen 
soll?

von Klaus W. (mfgkw)


Lesenswert?

Thomas schrieb:
> Die Zuordnung soll hierbei allerdings nicht über eine riesige Switch-
> oder if-Verschachtelung a la
>
> Struktur.zahl1 = Wert;
> Struktur.zahl2 = Wert;
> ...
>
> erfolgen, da die Struktur ziemlich riesig wird.
>
> Kann ich die Strukturelemente irgendwie über eine Lookup-Table
> ansprechen, in der die Information über das "mapping" hinterlegt sind?
> Darin würde stehen, dass z.B. immer
>
> WERT2 --> .zahl2
> WERT4 --> .zahl4
>
> innerhalb der aktuellen Struktur, abgelegt werden soll.

Machen kann man das schon, aber ich kann mir nicht vorstellen, daß es in 
diesem Fall Sinn macht.
Neben der Lage, wo etwas abgelegt werden soll, fehlt ja auch noch die 
Info, welcher Typ es ist.

Kannst du etwas C?

von Karl H. (kbuchegg)


Lesenswert?

Thomas schrieb:

> Ein Funktionsaufruf sieht z.B. so aus:
> main(void)
> {
>    meineZahlen *aktZahlen;

Ähm.
Du hast hier keine Struktur. Du hast nur einen Pointer auf eine Struktur 
vereinbart. Aber ein Pointer ist ja nicht die Daten selber.

Du brauchst schon ein Strukturobjekt selber, damit du in ihm Werte 
ablegen kannst.

    meineZahlen aktZahlen;

>    search("WERT4", &aktZahlen);

OK. search kriegt also einen Pointer auf das Objekt. Soweit so gut


> aktZahlen.zahl4 = 3.1415;
> neueZahlen.zahl2 = 5;

Diese SChreibweise könntest du benutzen, wenn neueZahlen ein 
STrukturobjekt wäre.
Aber in der Funktion hast du ja kein Objekt. Du hast einen Pointer 
darauf.

void search( const char* Label, meineZahlen* neueZahlen )
{
  ...
}

Also musst du den Pointer dereferenzieren, damit du auf das Objekt 
selber kommst und kannst dann auf den Member zugreifen

    (*neueZahlen).zahl2 = 5;

die Klammern sind notwendig, weil die Operatoren-Reihenfolge sonst 
falsch wäre.
Da aber diese Operation so häufig vorkommt und die Sache mit den 
Klammern Tippaufwand bedeutet, hat man dafür eine andere Schreibweise 
eingeführt, die genau das gleiche macht

    neueZahlen->zahl2 = 5;


Komisch das dein C-Buch dazu nichts zusagen hat. Normalerweise ist das 
ziemlich ausführlich und mit vielen Beispielen und Übungen beschrieben 
und zieht sich über entsprechend viele Seiten hin, eben weil es wichtige 
Grundlagen sind.

von Thomas (Gast)


Lesenswert?

@Klaus:

Genau, ich habe bereits eine LookUp-Tabelle definiert, die auch den 
Datentype umfasst, da der Wert später noch (ausgehend von std::string) 
konvertiert werden muss.
1
// LookUp-Table fürs Mapping
2
// (z.B. der gefunden Wert WERT3 soll immer an .zahl3 
3
// innerhalb der aktuellen Struktur geschrieben werden)
4
struct sKeyDesc keyDescriptions[] = 
5
{
6
  //name,            -->       type,            ptr on struct element?
7
  { "WERT1",              TYPE_INT8},        // meineZahlen.zahl1
8
  { "WERT2",              TYPE_INT16},       // meineZahlen.zahl2
9
  { "WERT3",              TYPE_INT32},       // meineZahlen.zahl3
10
  { "WERT4",              TYPE_FLOAT}        // meineZahlen.zahl4
11
};

Als 3. Argument müsste nun eine Angabe folgen, die sich auf das Ziel/das 
Strukturelement bezieht. Nur wie sieht diese Angabe aus? (siehe oben)

Danke.

von Karl H. (kbuchegg)


Lesenswert?

Du brauchst das offsetof Makro, um den Offset eines Members in Bezug auf 
den Strukturanfang festzustellen. Der kommt dann in deine Lookup 
Tabelle.

von Karl H. (kbuchegg)


Lesenswert?

1
struct sKeyDesc keyDescriptions[] = 
2
{
3
  //name,            -->       type,            ptr on struct element?
4
  { "WERT1",   TYPE_INT8,    offsetof( struct meineZahlen, zahl1 )},        // meineZahlen.zahl1
5
  { "WERT2",   TYPE_INT16,   offsetof( struct meineZahlen, zahl2 )},       // meineZahlen.zahl2
6
  { "WERT3",   TYPE_INT32,   offsetof( struct meineZahlen, zahl3 )},       // meineZahlen.zahl3
7
  { "WERT4",   TYPE_FLOAT,   offsetof( struct meineZahlen, zahl4 )}        // meineZahlen.zahl4
8
};


und dann in der Funktion

....
1
bool search( const std::string& label, struct meineZahlen* pZahlen )
2
{
3
  ...
4
5
  for( i = 0; i < sizeof(keyDescriptions)/sizeof(*keyDescriptions); ++i ) {
6
    if( Label == keyDescriptions[i].name ) {
7
      if( keyDescriptions[i].type == TYPE_INT8 ) {
8
        ....
9
        uint8_t* pTarget = (uint8_t)( (unsigned char*)pZahlen + keyDescriptions[i].offset );
10
        *pTarget = gelesener_Wert;
11
      }
12
13
      else if( keyDescriptions[i].type == TYPE_INT16 ) {
14
        ...
15
        uint16_t* pTarget = (uint16_t)( (unsigned char*)pZahlen + keyDescriptions[i].offset );
16
      }
17
    }
18
  }
19
}

Schön ist das nicht gerade. Da müsste es in C++ eine bessere Lösung 
geben.

von Thomas (Gast)


Lesenswert?

Danke. Vielleicht hat ja tatsächlich noch jemand eine bessere Lösung -> 
da wirklich unschön und ich in C++ programmiere.

Ich habe letzte Woche bereits mit dem MACRO offsetof gearbeitet.
Mein Problem war dort, dass die angegeben Beispiel-Struktur auch 
geschachtelt sein kann, also Elemente wiederum Strukturen sein können.

Dann ist die Lösung mit dem MACRO kaum handelbar.

Danke.

von Klaus W. (mfgkw)


Lesenswert?

Thomas schrieb:
> ich in C++ programmiere.

Dann eine Map nehmen, die den Namen ("WERT1") auf den Rest (Typ, Wert) 
mappt.

von Thomas (Gast)


Lesenswert?

@ Klaus:

Kannst du mir bitte deinen Lösungsansatz näher beschreiben?
Vielen Dank.

von Klaus W. (mfgkw)


Lesenswert?

1
#include <iostream>
2
#include <map>
3
#include <utility>
4
5
6
class Wert
7
{
8
public:
9
  enum eWert
10
    {
11
      eWertInt,
12
      eWertFloat,
13
      eWertInvalid,
14
    };
15
16
  Wert()
17
    : m_typ(eWertInvalid)
18
  {
19
  }
20
21
  Wert( long l )
22
    : m_typ(eWertInt)
23
  {
24
    m_wert.l = l;
25
  }
26
27
  Wert( int l )
28
    : m_typ(eWertInt)
29
  {
30
    m_wert.l = l;
31
  }
32
33
  Wert( double d )
34
    : m_typ(eWertFloat)
35
  {
36
    m_wert.d = d;
37
  }
38
39
  Wert( const Wert &w )
40
    : m_wert( w.m_wert ),
41
      m_typ( w.m_typ )
42
  {
43
  }
44
45
  // virtual nur nötig, wenn davon etwas abgeleitet wird, dann auch virtual ~Wert()!
46
  virtual void toStream( std::ostream &os ) const
47
  {
48
    switch( m_typ )
49
    {
50
      case eWertInt:
51
        os << m_wert.l;
52
        break;
53
54
      case eWertFloat:
55
        os << m_wert.d;
56
        break;
57
58
      default :
59
        os << "<häh?>";
60
        break;
61
    }
62
  }
63
64
private:
65
66
  union
67
  {
68
    long    l;
69
    double  d;
70
  } m_wert;
71
72
  eWert  m_typ;
73
74
};
75
76
std::ostream &operator<<( std::ostream &os, const Wert &w )
77
{
78
  w.toStream( os );
79
  return os;
80
}
81
82
int main( int nargs, char **args )
83
{
84
  std::map< const char *, Wert>  werte;
85
86
  // Einfügen so:
87
  werte["WERT1"] =  3;
88
  werte["WERT2"] =  5;
89
  // oder so:
90
  werte.insert( std::pair<const char*,Wert>( "WERT3", Wert( 10 ) ) );
91
  werte.insert( std::pair<const char*,Wert>( "WERT4", Wert( 3.141592365 ) ) );
92
93
  // Testausgabe:
94
  std::cout << werte["WERT1"] << std::endl;
95
  std::cout << werte["WERT2"] << std::endl;
96
  std::cout << werte["WERT3"] << std::endl;
97
  std::cout << werte["WERT4"] << std::endl;
98
}

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.