www.mikrocontroller.net

Forum: PC-Programmierung Variablenname inkrementieren

Autor: Daniel (Gast)
Datum: 29.04.2008 13:12

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
Autor: Karl heinz Buchegger (kbuchegg) (Moderator)
Datum: 29.04.2008 13:16

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.
Autor: Sebastian (Gast)
Datum: 29.04.2008 13:25

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.
Autor: LISP (Gast)
Datum: 29.04.2008 13:49

In LISP kann man Variablennamen inkrementieren.
Und noch andere fiese Dinge tun.
Autor: Frank (Gast)
Datum: 29.04.2008 14:05

Wird LISP überhaupt noch benutzt?
Ich kenn das nur von den LISP Maschinen aus den 80ern. Aber kenn jetzt
niemand der das könnte.
Autor: Daniel (Gast)
Datum: 29.04.2008 14:09

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ß
Autor: Karl heinz Buchegger (kbuchegg) (Moderator)
Datum: 29.04.2008 14:12

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.
Autor: Daniel (Gast)
Datum: 29.04.2008 14:22

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...
Autor: Random ... (thorstendb)
Datum: 29.04.2008 14:30

> 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?
Autor: Sebastian (Gast)
Datum: 29.04.2008 14:31

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
Autor: Karl heinz Buchegger (kbuchegg) (Moderator)
Datum: 29.04.2008 14:38

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.
  for( .... ) {

    USBDevice NewObj;    // Objekt mal temporär erzeugen
    NewObj. ......       // mit Daten füllen

    // und hier wird das Objekt dann dem Container übergeben
    // wie das genau funktioniert, hängt davon ab welchen
    // Container du benutzt.
 
    // zb. in Standard C++ würde man das so machen
    // ( eigentlich wird eine Kopie des Objektes erzeugt und im
    // Container gespeichert. Container die ihre Objekte per
    // Pointer referenzieren und nur die Pointer speichern, tu
    // ich dir jetzt nicht an )

    AllDevices.push_back( NewObj );

    // wobei AllDevices ein std::vector<USBDevice> ist


    // mit MFC Mitteln würde man sich zb ein
    // CArray< USBDevice, &USBDevice> AllDevices
    // anlegen und das neue Objekt (eigentich eine Kopie davon)
    // so in den Container einfügen
    AllDevices.Add( NewObj );

    // ähnlich würde das aussehen, wenn man statt einem CArray
    // ein CList aus der MFC nehmen würde.
  }

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++

   for( int i = 0; i < AllDevices.size(); ++i )
     // machwas mit AllDevices[i]

Bei einem MFC CArray funktioniert das dann ähnlich
  for( int i = 0; i < AllDevices.GetSize(); ++i )
    // machwas mit AllDevices[i]

Es tut mir leid, aber du wirst nich umhin kommen, dich mit
Containern im Allgemeinen mal zu beschäftigen.
Autor: yalu (Gast)
Datum: 29.04.2008 15:57

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/
Autor: Daniel (Gast)
Datum: 29.04.2008 16:22

Also ich hab jetzt mal versucht kbucheggs (DANKE!!!) vorschlag
umzusetzen, stehe aber immer noch vor dem gleichen Problem... Hier meine
Schleife:
vector<struct device> deviceList;
struct device 
{
  int deviceEnumNumber;
  char deviceNumber;
  short deviceNoEndpoints;
};

int d = 0; 
do
{
  USBDevice->Open(d);
  device device0;
  deviceList.push_back(device0);
  device0.deviceEnumNumber = d;
  device0.deviceNumber = USBDevice->DeviceName[11];
  device0.deviceNoEndpoints = USBDevice->EndPointCount();
  d++;             
}
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...
Autor: Karl heinz Buchegger (kbuchegg) (Moderator)
Datum: 29.04.2008 16:33

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)

#include <stdio.h>
#include <vector>
#include <string>
#include <sstream>

struct Device
{
  int         Id;
  long        Vendor;
  std::string Name;
};

std::vector< Device > Devices;

int main()
{
  int i;

  //
  // container füllen
  //
  for( i = 0; i < 10; ++i ) {
    Device dev;

    dev.Id = i;
    dev.Vendor = i + 100;

    std::stringstream tmp;
    tmp << "USB-" << i;
    dev.Name = tmp.str();

    Devices.push_back( dev );
  }

  //
  // und abfragen
  //
  for( i = 0; i < Devices.size(); ++i ) {
    printf( "Device %s: %d - Vendor %d\n", Devices[i].Name.c_str(),
                                           Devices[i].Id,
                                           Devices[i].Vendor );
  }

  return 0;
}
Autor: Frank (Gast)
Datum: 29.04.2008 16:43

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
Autor: Daniel (Gast)
Datum: 29.04.2008 17:07

Jaaa, jetzt läufts. Bist ein Schatz, Karl Heinz ;-)

Danke auch an euch andere...

Gruß
Daniel
Autor: Chris (Gast)
Datum: 29.04.2008 17:19

> for( int i = 0; i < AllDevices.size(); ++i )

Damit das portabel ist, sollte i besser den Typ std::size_t bekommen.
Autor: Karl heinz Buchegger (kbuchegg) (Moderator)
Datum: 30.04.2008 07:58

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.

Antwort schreiben

Die Angabe einer Email-Adresse ist freiwillig. Wenn Sie automatisch per Email über Antworten auf Ihren Beitrag informiert werden möchten, melden Sie sich bitte an.

Wichtige Regeln - erst lesen, dann posten!

  • Suchfunktion und Betreffsuche benutzen - vielleicht gibt es schon einen ähnlichen Beitrag
  • Aussagekräftigen Betreff wählen
  • Im Betreff angeben um welchen Controllertyp es geht (AVR, PIC, ...)
  • Groß- und Kleinschreibung verwenden
  • Längeren Sourcecode nicht im Text einfügen, sondern als Dateianhang
  • JPEG-Dateien (.jpg) nur für Fotos verwenden, Schaltpläne, Screenshots usw. als PNG oder GIF anhängen

Formatierung (mehr Informationen...)

  • [c]C-Code[/c]
  • [avrasm]AVR-Assembler-Code[/avrasm]
  • [pre]vorformatierter Text (z.B. Code in anderen Sprachen)[/pre]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] - Link zu Artikel






webmaster@mikrocontroller.netImpressumWerbung auf Mikrocontroller.net