Hallo zusammen, ich möchte in einer Schleife neue Variablen vom Typ Struct erstellen und deren Namen durchnummerieren. z.B. soll im ersten Schleifendurchlauf var1 erstellt werden, im zweiten Durchlauf dann var2... Wie kann ich eine in der Schleife inkrementierte Zahl einem Variablennamen anfügen? Gruß Daniel
In welcher Sprache? Allerdings: in den meisten Sprachen geht sowas überhaupt nicht. Was du willst ist, du willst ein Array (ein Feld) von einem bestimmten Typ anlegen und dann aus diesem Array einzelne Elemente benutzen. Arrays gibt es, je nach Programmiersprache, in verschiedenen Ausführungen. Bei manchen ist die Größe, also die Anzahl der Elemente, bereits zur Compilierzeit fix. Andere Arrays können zur Laufzeit selbsttätig wachsen und schrumpfen. Näheres dazu findest du in deinem Lehrbuch, das auf deine Programmiersprache abgestimmt ist.
Also Variablennamen einfach durchnummerieren lassen wird wohl schwer. Aber schreib am besten mal bissl mehr über dein Vorhaben. In welcher Sprache? Ist die Anzahl der zu erzeugenden Variablen fix? oder kann diese vom Benutzer geändert werden? Warum unbedingt durchnummerierte Variablennamen? Was mir da spontan einfallen würde, wäre ne Liste mit dienen structs zu machen und einfach zu viele Elemente einfügen lassen wie du willst. Dann hast aber keine direkten Variablennamen. Man könnte natürlich in die struct ein Element einfügen das den Namen representiert. char name[10]; dann könntest zB. name[9] mit durchnummerierung belegen bzw. name[8] und name[9] falls du mehr als 10 brauchst.
In LISP kann man Variablennamen inkrementieren. Und noch andere fiese Dinge tun.
Wird LISP überhaupt noch benutzt? Ich kenn das nur von den LISP Maschinen aus den 80ern. Aber kenn jetzt niemand der das könnte.
Ach ja, ich arbeite hier mit dem C++ Compiler des Visual Studio 2008 Ich hab an meinem REchner mehrere Cypress-USB-Chips hängen, und deren Konfigurationen möchte ich nacheinander in einer Schleife abfragen. Und diese Daten sollen in Strukturen übernommen werden. Da eine beliebige Anzahl von Chips ausgelesen werden soll, soll nach Bedarf eine neue Struct-Variable angelegt werden... Und die für Namensgebung dieser Variablen wollte ich halt ein Wort und eine sich erhöhende Zahl nehmen... So, das war die Zusammenfassung meines Problemchens Eure Aussagen klangen bis jetzt ja nicht so vielversprechend, ich hoffe da ändert sich noch was :-) Gruß
Daniel wrote: > Ach ja, ich arbeite hier mit dem C++ Compiler des Visual Studio 2008 > > Ich hab an meinem REchner mehrere Cypress-USB-Chips hängen, und deren > Konfigurationen möchte ich nacheinander in einer Schleife abfragen. Und > diese Daten sollen in Strukturen übernommen werden. Da eine beliebige > Anzahl von Chips ausgelesen werden soll, soll nach Bedarf eine neue > Struct-Variable angelegt werden... Und die für Namensgebung dieser > Variablen wollte ich halt ein Wort und eine sich erhöhende Zahl > nehmen... Ganz klar: Du suchst nach einer Containerklasse. In Standard C++ wäre zb ein std::vector geeignet In MFC wäre ein CArray oder eine CList ein guter Kandidat (mit einer leichten Präferenz zu CList auf meiner Seite) In .Net ... kann ich nicht sagen, das Gerümpel benutz ich nicht > Eure Aussagen klangen bis jetzt ja nicht so vielversprechend, ich hoffe > da ändert sich noch was :-) Da ändert sich gar nichts mehr. Du kannst keine Variablen, also etwas das einen Namen, hat zur Laufzeit erzeugen. Du kannst Objekte erzeugen. Diese Objekte speichern deine Daten. Und natürlich kann man solche Objekte in einem Container speichern. Das einzige was sich noch ändert :-) Hier kommt er, mein üblicher Spruch: Du brauchst Literatur. Ohne ein vernünftiges Buch kann man nicht lernen. Try and Error funktioniert bei Programmiersprachen auf diesem Level nicht.
Ich glaub ich hab mich nur falsch ausgedrückt. Ich möchte in jedem Schleifendurchlauf ein Objekt erzeugen. Und diese Objekte sollen durchnummeriert werden. Und genau da möchte ich wissen wie ich das meinem Compiler beibringe...
> Wird LISP überhaupt noch benutzt? > Ich kenn das nur von den LISP Maschinen aus den 80ern. Aber kenn jetzt niemand der das könnte. hmmm ... emacs?
Wie oben schon erwähnt würd ich da zu ner Liste tendieren. Auch nachdem du nun deine Problemstellung genauer erläutert hast^^ In dem Fall ,wie Karl Heinz ja schon gesagt hat, ne CList. Und eben für jeden Chip ein weiters Element einfügen. http://msdn2.microsoft.com/de-de/library/bxde0zae.aspx
Daniel wrote: > Ich glaub ich hab mich nur falsch ausgedrückt. Ich möchte in jedem > Schleifendurchlauf ein Objekt erzeugen. Und diese Objekte sollen > durchnummeriert werden. Und genau da möchte ich wissen wie ich das > meinem Compiler beibringe... Und nochmal. Du kannst sie nicht durchnummerieren und in Variablen speichern, die erst zur Laufzeit erzeugt werden. Du brauchst einen Container, der die Objekte speichert.
1 | for( .... ) { |
2 | |
3 | USBDevice NewObj; // Objekt mal temporär erzeugen |
4 | NewObj. ...... // mit Daten füllen |
5 | |
6 | // und hier wird das Objekt dann dem Container übergeben
|
7 | // wie das genau funktioniert, hängt davon ab welchen
|
8 | // Container du benutzt.
|
9 | |
10 | // zb. in Standard C++ würde man das so machen
|
11 | // ( eigentlich wird eine Kopie des Objektes erzeugt und im
|
12 | // Container gespeichert. Container die ihre Objekte per
|
13 | // Pointer referenzieren und nur die Pointer speichern, tu
|
14 | // ich dir jetzt nicht an )
|
15 | |
16 | AllDevices.push_back( NewObj ); |
17 | |
18 | // wobei AllDevices ein std::vector<USBDevice> ist
|
19 | |
20 | |
21 | // mit MFC Mitteln würde man sich zb ein
|
22 | // CArray< USBDevice, &USBDevice> AllDevices
|
23 | // anlegen und das neue Objekt (eigentich eine Kopie davon)
|
24 | // so in den Container einfügen
|
25 | AllDevices.Add( NewObj ); |
26 | |
27 | // ähnlich würde das aussehen, wenn man statt einem CArray
|
28 | // ein CList aus der MFC nehmen würde.
|
29 | }
|
und um auf die Objekte im Container zuzugreifen, muss man denn Container mal befragen, wieviele Objekte er denn enthält. Solche Funktionen heissen meist count oder size oder zumindest so ähnlich Std-C++
1 | for( int i = 0; i < AllDevices.size(); ++i ) |
2 | // machwas mit AllDevices[i]
|
Bei einem MFC CArray funktioniert das dann ähnlich
1 | for( int i = 0; i < AllDevices.GetSize(); ++i ) |
2 | // machwas mit AllDevices[i]
|
Es tut mir leid, aber du wirst nich umhin kommen, dich mit Containern im Allgemeinen mal zu beschäftigen.
Ist es so schlimm, statt name17 name[17] zu schreiben? Mehr ist für einen Array-Zugriff nicht zu tun. Und wenn das Ganze dynamisch sein soll, weil die Anzahl der Elemente erst zur Laufzeit bekannt wird, gibt es ja die von Karl heinz beschriebenen Container-Klassen, die den dynamischen Speicherveraltungs-Hickhack komplett verstecken. > Wird LISP überhaupt noch benutzt? LISP ist die Mutter aller Programmiersprachen, d.h. was in irgendeiner anderen Programmiersprache geht, geht auch in LISP, u.a. eben auch dynamisch generierte Symbolnamen. Dass die Sprache heute zu den Exoten zählt, liegt nicht an objektiven Mängeln der Sprache, sondern daran, dass die Welt der Programmiersprachen stark von Modeerscheinungen geprägt ist und die meisten Leute an einer Parenthesophobie zu leiden scheinen ;-) Heute wird LISP hautpsächlich zur Programmierung von Erweiterungen komplexer Anwendungen benutzt (bspw. Scheme, Emacs LISP und AutoLISP), es gibt aber durchaus Firmen, die auch heute noch mit eigenständigen LISP-Systemen und -Anwendungen Geld verdienen. Hier ist eine kleine Übersicht: http://www.pchristensen.com/blog/lisp-companies/
Also ich hab jetzt mal versucht kbucheggs (DANKE!!!) vorschlag umzusetzen, stehe aber immer noch vor dem gleichen Problem... Hier meine Schleife:
1 | vector<struct device> deviceList; |
2 | struct device |
3 | {
|
4 | int deviceEnumNumber; |
5 | char deviceNumber; |
6 | short deviceNoEndpoints; |
7 | };
|
8 | |
9 | int d = 0; |
10 | do
|
11 | {
|
12 | USBDevice->Open(d); |
13 | device device0; |
14 | deviceList.push_back(device0); |
15 | device0.deviceEnumNumber = d; |
16 | device0.deviceNumber = USBDevice->DeviceName[11]; |
17 | device0.deviceNoEndpoints = USBDevice->EndPointCount(); |
18 | d++; |
19 | }
|
20 | while (d < USBDevice->DeviceCount()); |
Es sollen nacheinander alle Devices geöffnet werden. Für jedes Device wird eine Struktur mit Konfigurationsdaten erstellt, diese Strukturen werden im vector deviceList abgelegt. Mein Problem ist nun, dass in jedem Schleifendurchlauf wieder eine Struktur namens device0 erstellt wird. Und dieser Name müsste nun automatisch in jedem Durchlauf geändert werden...
Daniel wrote: > Also ich hab jetzt mal versucht kbucheggs (DANKE!!!) vorschlag > umzusetzen, stehe aber immer noch vor dem gleichen Problem... Hier meine > Schleife: > OK. Wir bewegen uns also im Bereich von Standard C++. Gut > do > { > USBDevice->Open(d); > device device0; > deviceList.push_back(device0); Wieso fügst du hier bereits das Objekt zum Container hinzu. Ich hab extra noch dazugeschrieben, dass sich der Container eine Kopie(!) des übergebenen Objektes speichert. Eine Kopie von einem Objekt welches keine gültigen Werte hat, hat selbst keine gültigen Werte > Mein Problem ist nun, dass in jedem Schleifendurchlauf wieder eine > Struktur namens device0 erstellt wird. Ja. Macht ja nichts. > Und dieser Name müsste nun > automatisch in jedem Durchlauf geändert werden... Wozu? Sobald du push_back machst, wird von deinem device0 Objekt eine Kopie erzeugt und diese im Container gespeichert. (Ich hab ins Beispiel auch noch eine String Klasse mit eingebaut. Nicht das du dann auch noch mit char-Arrays rummachst, denn das würde dann zu Ärger führen)
1 | #include <stdio.h> |
2 | #include <vector> |
3 | #include <string> |
4 | #include <sstream> |
5 | |
6 | struct Device |
7 | {
|
8 | int Id; |
9 | long Vendor; |
10 | std::string Name; |
11 | };
|
12 | |
13 | std::vector< Device > Devices; |
14 | |
15 | int main() |
16 | {
|
17 | int i; |
18 | |
19 | //
|
20 | // container füllen
|
21 | //
|
22 | for( i = 0; i < 10; ++i ) { |
23 | Device dev; |
24 | |
25 | dev.Id = i; |
26 | dev.Vendor = i + 100; |
27 | |
28 | std::stringstream tmp; |
29 | tmp << "USB-" << i; |
30 | dev.Name = tmp.str(); |
31 | |
32 | Devices.push_back( dev ); |
33 | }
|
34 | |
35 | //
|
36 | // und abfragen
|
37 | //
|
38 | for( i = 0; i < Devices.size(); ++i ) { |
39 | printf( "Device %s: %d - Vendor %d\n", Devices[i].Name.c_str(), |
40 | Devices[i].Id, |
41 | Devices[i].Vendor ); |
42 | }
|
43 | |
44 | return 0; |
45 | }
|
Also Karl Hein Vorschlag ist eigentlich der einfachst. Das einzige was nun halt anderst ist also bei deiner durchnummernierung ist das du nun nicht mit device6 sondern mit device[6] zugreifst. Aber das dürfte ja kein Problem darstellen
Jaaa, jetzt läufts. Bist ein Schatz, Karl Heinz ;-) Danke auch an euch andere... Gruß Daniel
> for( int i = 0; i < AllDevices.size(); ++i )
Damit das portabel ist, sollte i besser den Typ std::size_t bekommen.
Chris wrote: >> for( int i = 0; i < AllDevices.size(); ++i ) > > Damit das portabel ist, sollte i besser den Typ std::size_t bekommen. Yep. Damit es noch portabler ist, würde ich in realem Code auf Iteratoren ausweichen, so wie sich die Macher der STL das vorgestellt haben. Allerdings: Ich wollte ihn nicht gleich am Anfang seiner Karriere überfordern, auch wenn der Tip mit size_t ein guter ist.
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.