[C++] Strukturen in einem Array initialisieren

mh1001

Lt. Commander
Registriert
Nov. 2003
Beiträge
2.039
Hallo zusammen,

ich habe folgende Struktur:

Code:
struct schluessel
{
  string schluessel;
  int minimalwert;
  int maximalwert;
};
Nun möchte ich ein Array vom Typ dieser Struktur mit Daten füllen.
Allerdings gelingt es mir nur, wenn ich jeden Wert einzeln zuweise -sprich folgendermaßen:

Code:
schluessel schluesselsammlung[40];

t_schluessel[0].schluessel = "programm";
t_schluessel[0].minimalwert = 1;
t_schluessel[0].maximalwert = 4;
...
Da allerdings größere Datenmengen in dem "struktur-Array" abgelegt werden müssen, würde ich jedoch gerne mehrere Elemente gleichzeitig initialisieren, da dies sonst recht schnell recht unübersichtlich werden würde. ;)
Meine bisherigen versuche sahen folgendermaßen aus:

Code:
schluessel t_schluessel[40];

t_schluessel[0] = { "programm", 1, 4 };

//bzw.

schluessel t_schluessel[40] = { { "programm", 1, 4 },
                                           { "beispiel", 7, 18 } .... }
Allerdings schlagen beide Varianten fehl.
Kennt vielleicht jemand von euch eine Möglichkeit, wie ich dieses Array initialisieren kann, ohne gleich so einen Haufen Code vor mir zu haben?



Vielen Dank schon einmal

mh1001
 
mh1001 schrieb:
Meine bisherigen versuche sahen folgendermaßen aus:

Code:
schluessel t_schluessel[40];

t_schluessel[0] = { "programm", 1, 4 };

//bzw.

schluessel t_schluessel[40] = { { "programm", 1, 4 },
                                           { "beispiel", 7, 18 } .... }
Allerdings schlagen beide Varianten fehl.

Das Erste funktioniert nicht, weil ein Initialisierungsausdruck ( { ... } ) nur bei der Definition einer Variable erlaubt ist.

Das Zweite ist nicht zulässig, weil { "programm", 1, 4 } ein Initialisierer für ein struct A { const char* a; int b; int c; } ist und nicht für ein struct B { string a; int b; int c; }. struct A lässt sich aber nicht implizit in ein struct B umwandeln, deshalb ist die Syntax nicht zulässig.

Ich weiß nicht ob das zulässig ist, aber versuch mal { string( "programm"), 1, 4 } . Reicht dir alternativ, wenn du nur struct { const char* a; int b; int c; } hast?


Edit:
Davon abgesehen sieht deine Datenhaltung ziemlich statisch und unflexibel aus. Kann man das nicht z.B. in eine Datei auslagern?
 
Zuletzt bearbeitet:
das kann man ein bisschen sauberer so schreiben:
Code:
class schluessel
{
public:
  schluessel(string _schluessel,int _minimalwert, int _maximalwert):schluessel(_schluessel),minimalwert(_minimalwert),maximalwert(_maximalwert){};
  string schluessel;
  int minimalwert;
  int maximalwert;
};
keine angst, das ist kein performanceverlust, denn class und struct wird in den meisten c++-compilern eh gleich behandelt. damit müßte es eigentlich möglich seien, deine initialisierung etwa abgewandelt zu nutzen:

schluessel t_schluessel[40] ={schluessel(...), schluessel(...),....};

afaik gibt es keine zulässige methode structs in einem array zu initialisieren, aber da kann ich mich auch irren.
 
Hallo,

die Variante von Georg (habe ich das richtig in Erinnerung :-)?), ist zwar schön.
Ich habe das teilweise auch schon so gemacht, nur stören mich dabei die vielen Aufrufe der Konstruktoren.
Die Frage ist ob überhaupt ein string benötigt wird und ob nicht ein const char* auch ausreichen würde.

MfG

Arnd
 
Hallo,

zuerst einmal vielen Dank für die vielen Antworten. ;)

Ich habe mich gleich einmal daran gemacht, die einzelnen Vorschläge durchzugenen.


@7H3 N4C3R

Dass die erste Variante nicht möglich ist, leuchtet mir nun auch ein. ;)
Jedoch klappt es mit der zweiten, von dir abgeänderten Variante leider auch nicht.
Dies scheint jedoch nicht ein Problem zu sein, was mit dem "string" zusammenhängt, da es ebensowenig klappt, wenn ich nun testweise den Typ "int" oder "const char*" verwende.

Code:
 Davon abgesehen sieht deine Datenhaltung ziemlich statisch und unflexibel aus. Kann man das nicht z.B. in eine Datei auslagern?
Gerade dazu ist die Struktur da. ;)
Die entsprechenden Daten werden in Textdateien abgelegt.
Das "Strukturen-Array" soll dabei beim Einlesen dieser dazu dienen, zu überprüfen, ob der entsprechende Schlüssel vorhanden ist und dessen Wert sich innerhalb eines gewissen Gültigkeitsbereichs befindet.


@ghorst

Deine Idee klingt interessant. Wahrscheinliche werde ich diese auch so übernehmen um wieder etwas Ordnung in das Durcheinander zu bringen. ;)


@Arnd

Naja, eigentlich hatte ich meinen Code schon auf Strings ausgreichtet, somit käme es mir doch recht entgegen, wenn ich bei den Strings bleiben könnte. ;)


Daneben wurde mir noch die Idee vorgeschlagen, die Strukturen über eine entsprechende Funktion zu füllen, was dann zum Beispiel ungefähr so aussehen würde:

Code:
void fuelle_strukturen(int i, string schluessel, int min, int max)
{
  t_schluessel[i].schluessel = schluessel;
  t_schluessel[i].minimalwert = min;
  t_schluessel[i].maximalwert = max;
}
Was haltet ihr von dieser Lösung und wie sollte sich dies performancemäßig auswirken?


Nochmals vielen Dank für alle Antworten und einen guten Rutsch ins neue Jahr,

mh1001
 
Zuletzt bearbeitet:
Hmm also das hier kompiliert bei mir:

Code:
#include <string>

struct Test
{
	const char* a;
	int b;
	int c;
};

struct Test2
{
	std::string a;
	int b;
	int c;
};

int main(int argc, char* argv[])
{
	Test  a[]   = { {"Test", 1, 2}, {"Klaus", 2, 3} };
	Test2 b[]   = { {"Test", 1, 2}, {"Klaus", 2, 3} };
	Test2 c[40] = { {"Test", 1, 2}, {"Klaus", 2, 3} };
	Test2 d[40] = { {std::string("Test"), 1, 2}, {std::string("Klaus"), 2, 3} };

	return 0;
}

Sogar zweitere Variante geht (was ich erst nicht erwartet hätte). Wenn dein Compiler das nicht mitmacht (welcher ist das?), liegt der Fehler dort begraben.

Ansonsten geht auch die Variante mit deiner Funktion. Die Performance ist hier absolut irrelevant. Ob nun 40 Konstruktoraufrufe oder nicht ist absolut Banane und würde nicht mal auf einem 80686er eine messbare Zeit brauchen. Zudem wird die Initialisierung nur einmal gemacht und ist linear Komplex - ein weiterer Grund hier nichtmal ansatzweise an die Performance zu denken (weil es überflüssig ist).
 
Zuletzt bearbeitet:
Also ich bekomme das ganze absolut nicht kompiliert - auch wenn ich den Code 1:1 übernehme.
Dazu verwende ich Dev-C++ 4.9.9.2 mit GCC in der Version 3.4.2.

Aber da du sagst, dass die andere Variante auch keine nennenswerten Auswirkungen auf die Performance hätte, dann werde ich einfach bei dieser verbleiben.

Dennoch vielen Dank für die ganzen Anregung. Diese werden sicher noch an der ein oder anderen Stelle irgendwo Einsatz finden. ;)

MfG mh1001
 
Arnd schrieb:
Hallo,

die Variante von Georg (habe ich das richtig in Erinnerung :-)?), ist zwar schön.
Ich habe das teilweise auch schon so gemacht, nur stören mich dabei die vielen Aufrufe der Konstruktoren.
Die Frage ist ob überhaupt ein string benötigt wird und ob nicht ein const char* auch ausreichen würde.

MfG

Arnd
nein, ich heiße gregor.
die performance ist da völlig rille. da ich hübsch brav die initialisierung der internen werte mittels ":wert(zuweisung)" gemacht habe, ist der code eigentlich äquivalent mit dem aufruf über die initialisierung, die 7H3 N4C3R geschrieben hat. wenn der compiler intelligent ist, gehen da 8 takte (call (sind etwa 4), retf (auch 4) beides auf einem pI. mein assembler buch ist nicht ganz auf den neusten stand...)mehr bei flöhten, aber das ist nun wirklich ziemlich egal. wenn der compiler richtig intelligent ist, wird er den fkt. aufruf ganz unter den tisch fallen lassen.
die verwendung von const char* bringt auch nicht wirklich einen performace vorteil. da man die wirkliche zeit bei der verarbeitung verliert und dabei dürften die vergleichsoperatoren der string-klasse sogar schneller sein als die der c-lib, da hier nicht ständig die länge verglichen werden muss.
 
mh1001 schrieb:
Also ich bekomme das ganze absolut nicht kompiliert - auch wenn ich den Code 1:1 übernehme.
Dazu verwende ich Dev-C++ 4.9.9.2 mit GCC in der Version 3.4.2.

Aber da du sagst, dass die andere Variante auch keine nennenswerten Auswirkungen auf die Performance hätte, dann werde ich einfach bei dieser verbleiben.

Dennoch vielen Dank für die ganzen Anregung. Diese werden sicher noch an der ein oder anderen Stelle irgendwo Einsatz finden. ;)

MfG mh1001
ich bin gerade stark am überlegen, ob kaskadierte initialisierungsaufrufe überhaupt im c++-standart auftauchen. zumindest kann ich bei bjarne stroustrup nix dazu finden.
entweder ein feature des mvc++ (wenn ich mich recht entsinne nutzt 7H3 N4C3R den) oder der gcc ist an dieser stelle nicht ganz standardkonform.
 
mh1001 schrieb:
Also ich bekomme das ganze absolut nicht kompiliert - auch wenn ich den Code 1:1 übernehme.

Die Fehlermeldung wäre dann aber mal hilfreich. Sonst können wir nur die Glaskugel bemühen.
Der GCC sollte in der Fassung aber auch recht standardkonform sein. Ich habe es mit dem VC++ 2005 übersetzt (das inzwischen auch weitestgehend standardkonform ist).



@Gregor: Zu deinem Nachtrag. Kaskadierte Initialisierer sind absolut konform. Siehe Auszug aus dem Standard 8.5 Clause 1 :

initializer:
= initializerclause
( expressionlist )

initializerclause:
assignmentexpression
{ initializerlist ,opt }
{ }

initializerlist:
initializerclause
initializerlist , initializerclause


Der initializerclause taucht in der initializerlist wieder auf, ist also rekursiv. Und es heißt Standard :)
 
Zuletzt bearbeitet:
ich hab mich einmal verschrieben und es einmal richtig geschrieben. das muss reichen.

ansonsten gcc4 nimmt es klaglos an.
 
ghorst schrieb:
ich hab mich einmal verschrieben und es einmal richtig geschrieben. das muss reichen.
Ist ja auch nicht böse gemeint :) Bin vielleicht durch das C++-Forum vorgeschädigt ^^ Da wird das böse Wort (mit t ^^) mit einer Wortzensur belegt :D
 
7H3 N4C3R schrieb:
Ist ja auch nicht böse gemeint :) Bin vielleicht durch das C++-Forum vorgeschädigt ^^ Da wird das böse Wort (mit t ^^) mit einer Wortzensur belegt :D
normalerweise gehöre ich auch mit zu den leuten, die sich über standart aufregen. nur bin ich gerade zu müde, als das ich die tastatur richtig festhalten könnte.
btw. hast du einen link zu dem c++-standard im netz?
 
ghorst schrieb:
btw. hast du einen link zu dem c++-standard im netz?

Der Standard ist nicht frei, kann aber beim ANSI gekauft werden (für ca. 18 Dollars).

Alternativ kann man auf den Final Draft zurückgreifen, der bis auf minimale Änderungen mit dem Standard übereinstimmt:
http://www.kuzbass.ru:8086/docs/isocpp/

Der Draft hat sogar den Vorteil, dass da Hyperlinks drin sind, während man diese im Standard im PDF Format nicht hat.
 
Die Fehlermeldung wäre dann aber mal hilfreich. Sonst können wir nur die Glaskugel bemühen. [...]
Stimmt, die hatte ich schon ganz vergessen. ;)
Diese sind bei allen drei Varianten die selben und äußern sich jeweils in folgender Form:

Code:
expected primary-expression before '{' token
expected `;' before '{' token
Ich habe mir jedoch nun eben mal gcc 3.4.2 heruntergeladen und die im Dev-C++-Paket enthaltenen komponenten dagegen ersetzt - und siehe da, es geht; warum auch immer.
Da wollte mich dann doch wohl der Compiler nur etwas ärgern. ;)

MfG mh1001
 
Zuletzt bearbeitet:
Hallo Gregor,

danke für die Korrektur. War doch schon etwas spät :-).

Möglich das der Compiler das optimiert. Ich komme da auch mehr von embedded Systemen, mit begrenztem Speicher wo viele Objekte eher schlecht sind. Auch das debuggen von vielen Konstruktor Aufrufen ist nicht sehr schön.
Mir gefällt der Quellcode einfach besser, bzw. ist für mich lesbarer, wenn nur die Hochzeichen der Strings da stehen.

Die Performance habe ich da gar nicht so sehr im Auge. Auf aktuellen Prozessoren ist das sicher irrelevant. Ich habe aber z.B ein Projekt in dem die Initialisierung aller globalen Variablen ca. 1s benötigt (bei 25MHz CPU).

MfG

Arnd
 

Ähnliche Themen

D
Antworten
16
Aufrufe
12.348
Antworten
5
Aufrufe
1.418
1668mib
1
Zurück
Oben