Struct Array In Funktion Werte zuweisen



  • Halli Hallo,

    als meinen ersten Post in diesem so gut besuchtem Forum, möcht ich sogleich ein kleines Anfängerproblemchen euch mitteilen, welches mich seit gestern nervt:

    Ich muss über eine Funktion eingabe/ausgabe eines Struct-Arrays regeln.
    Bis jetzt habe ich es nur geschafft, eine Ausgabe (mit im Haupprogramm eingegebenen Werten) zu erzeugen. Nun möchte ich zudem eine Eingabe in einer Funktion verschachteln.

    Hier der Code wie ich es bis jetzt gemacht habe:

    #include <stdlib.h>
    
    //Struct erstellen
    struct test
    {
    char dat1[20];
    int dat2;
    
    };
    
    //Prototyp
    void unter (test *,int);
    
    //Hauptprogramm
    void main ()
    {
    int i,f;
    
    cout<<"Wieviele PC's moechten Sie erfassen ?    : "; 
    cin>>f;
    
    test pcs[f];
    
    cout<<"\n"<<endl;
      for (i=0;i<f;i=i+1) //Dies soll als Funktion gesteuert werden 
        {
      cout<<"Bitte geben Sie die HDD Groesse fuer den "<<i+1<<".ten PC an : ";
      cin>>pcs[i].dat1;
            }
    
    cout<<"\nIm Hauptprogramm : "<<endl;
      for (i=0;i<f;i=i+1)
        {
      cout<<pcs[i].dat1<<endl;
           }
    
    //Übergabe an das Unterprogramm
      unter (pcs,f);
    
     system ("pause");
    }
    
    //Funktion (Unterprog)
    void unter ( test  *pcu,int anz)
    {
    int i;
    cout<<"\n"<<endl;
    cout<<"Im Unterprogramm : "<<endl;
    for (i=0;i<anz;i=i+1)
    {
    cout<<pcu[i].dat1<<endl;
    }
    //pcu[1].dat1="b";
    
    }
    

    Ich habe schon alles mögliche versucht, nur leider komm ich nicht drauf. Ich denke mal es hat etwas mit Zeigern zu tun? 🙄

    Würd mich freuen wenn ihr mir weiterhelfen könntet.

    Mit Grüßen

    Flamboy 🙂 😃



  • test pcs[f];
    

    f ist nicht zu kompilezeit bekannt, also musst du es dynamisch anlegen

    test * pcs = new test[f];
    // am Ende dann
    delete[] pcs;
    

    Variablen aussagekräftige Namen zu geben hat noch nie geschadet. 🙂
    Fehlermeldungen mit posten.



  • Flamboyant schrieb:

    cout<<"\n"<<endl;
    

    Ist dir bewust das das immer 2 Zeilenvorschübe gibt?
    endl ist so viel wie ein '\n' und ein flush.
    Ich würde dir '\n' empfehlen, da du flush bestimmt nicht überall benötigst wo du endl verwendest.



  • Hallo,

    du solltest dir angewoehnen statt <stdlib.h> <cstdlib> zu schreiben, da man es
    in Standard-C++ so schreibt. Aeltere C-Header werden mit einem vorangestellten
    'c' (wie o. zu sehen) geschrieben. Dann liegen die Funktionen und Klassen im
    Namensraum 'std'. Wir machen den Namensraum daher in der Implementationsdatei
    bekannt mittels 'using namespace std;' oder wir schreiben den Namensraum vor die
    Funktion (z. B. std::pow()).

    Erstmal zu deinem Problem:

    Du kannst die Ganze Geschichte genauso loesen, wie du es mit der Funktion 'unter'
    gemacht hast. Du machst dir eine Funktion 'eingabe' (oder wie du sie eben nennen
    willst) und baust dort deinen Code ein:

    void eingabe(test *Test, int Anzahl)
    {
       for (i=0;i<Anzahl;++i) //++i entspricht i = i + 1, ist nur kuerzer :)
       {
          cout<<"Bitte geben Sie die HDD Groesse fuer den "<<i+1<<".ten PC an : ";
          cin>>pcs[i].dat1;
       }
    }
    

    Noch ein paar Kleinigkeiten:

    Statt

    void main ()
    

    schreibt man

    int main()
    

    Da main() ein Ergebnis an das OS zurueckliefert, ob das Programm ordnungsgemaess
    beendet worden ist oder nicht.

    int i,f;
    
    cout<<"Wieviele PC's moechten Sie erfassen ?    : ";
    cin>>f;
    
    test pcs[f];
    

    Diese Vorgehensweise entspricht nicht dem Standard-C++, denn hier muss in '[]'
    ein konstanter Wert stehen, was hier nicht der Fall ist.

    In einem solchen Fall erstellt man das Array dynamisch, was man auf folgende
    Art und Weise machen kann:

    test *pcs = new test[f];
    

    Hier haben wir nun Speicher fuer 'f' Variablen vom Typ 'test' reserviert.
    Natuerlich muss dieser Speicher wieder freigegeben werden und man muss so
    bald es von noeten ist genau dies tun. Hier koennten wir das vor dem Ende
    der main()-Funktion machen:

    delete[] pcs; //hier delete[], da es sich um ein array handelt
    

    Statt eines Arrays koenntest du auch std::vector nutzen. Dein Programm wuerde
    dann folgendermassen aussehen:

    #include <iostream> //std::cout
    #include <cstdlib>
    #include <vector>   //std::vector
    using namespace std; //namensraum std bekannt machen
    
    //Struct erstellen
    struct test
    {
      char dat1[20];
      int dat2;
    };
    
    //Prototyp
    //1. Parameter: Referenz auf einen vector mit 'test'-variablen
    //Der 2. Parameter kann wegfallen, warum, sehen wir unten
    void unter(vector<test>&);
    void eingabe(vector<test>&);
    
    //Hauptprogramm
    int main ()
    {
      int f;
    
      cout<<"Wieviele PC's moechten Sie erfassen ?    : ";
      cin>>f;
    
         //wir legen einen vector an, welcher 'f' 'test'-objekte enthaelt.
         //'f' wird hier als parameter an den konstruktor des vectors uebergeben.
         vector<test> pcs(f);
    
         cout<<"\n"<<endl;
         eingabe(pcs);
    
           cout<<"\nIm Hauptprogramm : "<<endl;
    
           //beschreibung iterator: siehe funktion unter()
           vector<test>::const_iterator It = pcs.begin();
           for ( ; It != pcs.end(); ++It)
              cout<<(*It).dat1<<endl;
    
           //Übergabe an das Unterprogramm
           unter (pcs);
           system ("pause");
           return 0; //main erfolgreich beendet
    } //end main
    
    //Funktion (Unterprog)
    void unter (vector<test> &TestVec)
    {
      /*
        mit einem iterator ist es moeglich, sich durch die
        einzelnen elemente eines vectors zu 'haengeln', sie
        also durchzugehen. TestVec.begin() zeigt auf das
        erste 'test'-objekt im vector. das ist auch der grund,
        warum hier der 2. parameter entfaellt, da wir ihn nicht
        benoetigen. der iterator ist hier const, da wir die
        objektmember nicht manipulieren wollen (wir greifen nur
        lesend auf diese zu).
      */
      vector<test>::const_iterator  It = TestVec.begin();
    
        cout<<endl;
        cout<<"Im Unterprogramm : "<<endl;
    
        /*
          TestVec.end() zeigt hinter das letzte element im vector.
          da wir von allen elementen den member 'dat1' ausgeben wollen,
          muessen wir solange das naechste element ausgeben (It: ist
          das aktuelle 'test'-objekt und mit ++It gehen wir zum naechsten
          'test'-objekt im vector) bis It hinter das letzte element
          im vector zeigt (sprich: It == TestVec.end()).
        */
        for ( ; It != TestVec.end(); ++It)
          cout<<(*It).dat1<<endl;
    }
    
    void eingabe(vector<test>& TestVec)
    {
      /*
        gleiche spiel, wie in der funktion 'unter' mit dem unterschied,
        dass wir hier die 'test'-objekte manipulieren und wir daher keinen
        konstanten iterator nehmen duerfen, da wir sonst das objekt nicht
        veraendern duerfen
      */
      vector<test>::iterator It = TestVec.begin();
    
      for ( int i = 1; It != TestVec.end(); ++It, ++i)
      {
        cout<<"Bitte geben Sie die HDD Groesse fuer den "<<i<<".ten PC an : ";
        cin>>(*It).dat1;
      }
    }
    

    Wie o. zu sehen, brauchst du dich beim Einsatz von 'vector' nicht um den
    Speichermanagment zu kuemmern, da das die Klasse vector fuer dich uebernimmt.

    Noch was zu vector: Wenn du einen vector von 'int'-Elementen haben willst,
    dann schreibst du 'std::vector<int> x'. Das gleiche gilt natuerlich auch
    fuer 'float' oder 'double' oder einen beliebigen anderen Typ.

    So, hoffe ich hab dich nicht mit Informationen ueberrannt, wollte nur zeigen
    dass es auch andere Mittel und Wege gibt, wie man dein Programm ohne new/delete
    schreiben kann. Wenn du Fragen hast, hier ist dein Forum :).

    Falls ich irgendwo einen Fehler gemacht hab, einfach korrigieren ;).

    mfg
    v R



  • Vielen Dank für die zahlreichen Tipps und Ratschläge.
    Werde sie gleich umsetzen und in meinen "Style" mit einfließen lassen 😃

    Auch ein riesen Dank an "virtuell Realisticer" für die ausführliche Erklärung.

    Meinst du es wär möglich mir den code für ein Array anstatt Vector. Da ich Vorlesungsgebunden bin, darf ich net so aus der Reihe tanzen und gleich so professionel Lösungen einfließen lassen :p 😃

    Vielen Dank

    Flamboy



  • Mit nem Array ist das auch kein Problem. Du nimmst einfach die erste eingabe-
    Funktion von meinem Post und ersetzt die entsprechenden Zeilen in deinem Code
    durch diese Funktion.

    Du hast zwar keine Iteratoren mehr, aber du hast immer noch die Arraygrenze
    von 0 bis f (in deinem Fall). Naja, hier der Code mit Hilfe eines Arrays:

    #include <iostream> //std::cout
    #include <cstdlib>
    using namespace std; //namensraum std bekannt machen
    
    //Struct erstellen
    struct test
    {
      char dat1[20];
      int dat2;
    };
    
    //Prototyp
    //1. Parameter: Referenz auf einen vector mit 'test'-variablen
    //Der 2. Parameter kann wegfallen, warum, sehen wir unten
    void unter(test *, int);
    void eingabe(test *, int);
    
    //Hauptprogramm
    int main ()
    {
      int f;
    
      cout<<"Wieviele PC's moechten Sie erfassen ?    : ";
      cin>>f;
    
         //array dynamisch erzeugen
         test *pcs = new test[f];
    
         cout<<"\n"<<endl;
         eingabe(pcs, f);
    
           cout<<"\nIm Hauptprogramm : "<<endl;
    
           for (int i = 0; i < f; ++i)
              cout<<pcs[i].dat1<<endl;
    
           //Übergabe an das Unterprogramm
           unter (pcs, f);
           /*
             reservierten speicher wieder freigeben. weiterarbeiten mit array
             hiernach natuerlich nicht mehr moeglich (neu reservierung natuerlich
             schon):
             pcs[0].dat1 wuerde zu einem speicherzugriffsfehler fuehren
           */
           delete[] pcs;
           system ("pause");
           return 0; //main erfolgreich beendet
    } //end main
    
    //Funktion (Unterprog)
    void unter (test *TestArray, int Anzahl)
    {
        cout<<endl;
        cout<<"Im Unterprogramm : "<<endl;
    
        for (int i = 0; i < Anzahl; ++i)
          cout<<TestArray[i].dat1<<endl;
    }
    
    void eingabe(test *TestArray, int Anzahl)
    {
      for ( int i = 0; i < Anzahl; ++i)
      {
        cout<<"Bitte geben Sie die HDD Groesse fuer den "<<i+1<<".ten PC an : ";
        cin>>TestArray[i].dat1;
      }
    }
    

    So, hoffe ich hab nichts vergessen, aber falls noch en kleiner Fehler irgendwo
    drin sein sollte, sollte es kein Problem darstellen diesen zu beheben.

    mfg
    v R



  • Vielen vielen Dank für die Hilfe, endlich funktionierts !
    Mein Fehler war glaubich, das ich direkt Elemente des Arrays im Unterprogramm mit

    pcu[1].dat1="b";
    

    bezeichnen wollte.

    Nun klappt es wunderbar.

    Vielen Dank nochmal, hab einiges dazu gelernt !


Anmelden zum Antworten