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
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?
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?
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.
@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.
Du brauchst das offsetof Makro, um den Offset eines Members in Bezug auf den Strukturanfang festzustellen. Der kommt dann in deine Lookup Tabelle.
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.
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.
Thomas schrieb: > ich in C++ programmiere. Dann eine Map nehmen, die den Namen ("WERT1") auf den Rest (Typ, Wert) mappt.
@ Klaus: Kannst du mir bitte deinen Lösungsansatz näher beschreiben? Vielen Dank.
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
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.