C# C#-Schulaufgabe (Container)

Griffindor01

Cadet 3rd Year
Registriert
Feb. 2021
Beiträge
33
Hallo liebe Gemeinde,

Ich gehe zurzeit in die 11. Klasse eines Gymnasiums und lerne im fachrichtungsbezogenen Unterricht die Grundlagen von C#.

Ich komme nun bei einer Aufgabenstellung nicht weiter und würde mich sehr über eure Hilfe freuen.


Die eigentliche Frage fängt erst ab Aufgabe 4 an, das davor ist nur eine Erläuterung.

Kurze Vorabinfo:
Im Vorhinein haben wir zwei Klassen (Person und Adressen) erstellt.
In der Klasse Adresse ist eine Adresse in verschiedene Attribute (wie Hausnummer, Postleitzahl) etc gegliefert worden.
In der Klasse Person haben wir einen Vor-und Nachnamen, ein Geburtsdatum und ein Objekt der Klasse Adresse eingespeist.

Nun sollen wir mit Containern verschiedene Operationen an diesen Klassen vornehmen.

Aufgabe 1 war zum Beispiel:

1. Ergänzen Sie das Projekt zur Adressverwaltung um eine Liste personen.

Lösung:

List<Person> personen = new List<Person>();

2.
Erstellen Sie im Programm mindestens fünf Person-Objekte auf verschiedene Arten.
Nutzen Sie hierzu sowohl den Standardkonstruktur als auch den überladenen Konstruktor.
Nehmen Sie alle Person-Objekte in die Liste personen auf.

Lösung (exemplarisch für die 5 Personen):

Person Mustermann = new Person();
Person XY = new Person("Computerbase", "Forum", new DateTime(2002, 05, 09), new Adresse("Musterweg", "1", "74565", "Berlin"));

personen.Add(Mustermann);
personen.Add(XY);


3. Zeigen Sie die Daten aller Person-Objekte mit einer foreach-Schleife.

Lösung:

foreach (Person person in personen)

{


Console.WriteLine(
person.getVorname() + "\n" +
person.getNachname() + "\n" +
person.getGeburtstag().ToShortDateString() + "\n" +
person.getAdresse().getPlz() + "\n" +
person.getAdresse().getOrt();




Console.WriteLine("===============");



}




Soweit, sogut, nun ist Aufgabe 4.:


Bisher kann für ein Person-Objekt nur ein einziges Adresse-Objekt gespeichert werden.
Ändern Sie die Klasse Person so ab, dass mehrere Adressen für ein Person-Objekt gespeichert
werden können!
Entfernen Sie die setAdresse()-Methode und fügen Sie stattdessen die neue Methode
addNeueAdresse(_adr:Adresse):void hinzu.
Diese neue Methode bekommt ein Adresse-Objekt übergeben und fügt diese einer Liste
von Adresse-Objekten hinzu.
Ändern Sie die Methode getAdresse():Adresse so ab, dass die Liste mit den Adresse-
Objekten zurückgeliefert wird.
Bennen Sie die Methode entsprechend um; z.B. in getAdressliste().


und zu Aufgabe 5:

Fügen Sie in die foreach-Schleife aus Aufgabe 3 geschachtelt eine zweite foreach-
Schleife ein, die bei jedem Person-Objekt alle Adresse-Objekte ausgibt.




Hier komme ich nun nicht weiter, ich habe euch meine Versuche mal als Anhäng beigefügt.
Das mit der zweiten foreach-Schleife verwirrt mich, da weiß ich gar nicht, wie ich das umsetzen soll.
Habe jetzt mal probiert, die Liste an der Stelle 1 (sollte dann doch nach dem Index das 2. Element sein) auszugeben, aber sowohl wenn ich dort 0 als auch 1 eintrage, kommt eine Fehlermeldung, dass es diese Stelle nicht gäbe, obwohl doch nachweislich Elemente hinzugefügt wurden?!
Außerdem löst das das Problem ja auch nicht, weil automatisch alle Adressen ausgegeben werden sollen und nicht die Adresse(n) an einer bestimmten Stelle.


Ich hoffe sehr, jemand macht sich die Mühe und liest sich das ganze hier mal durch. Stehe echt auf dem Schlauch.


Ich bedanke mich im Voraus!
1.PNG
2.PNG
3.PNG
 
lynxx schrieb:
Probier mal die Rückgabe von getAdresseListe() für Dein foreach zu verwenden:

C#:
             foreach (Adresse adresse in person.getAdresseListe())
             {
...
             }

Edit: Vorher holen geht auch .. aber Du musst ja noch je nachdem wie die Funktionen in Adresse heissen:
C#:
Console.WriteLine( adresse.getPlz() + "\n" + adresse.getOrt());

C#:
    foreach (Person person in personen)

            {
                Console.WriteLine(
                person.getVorname() + "\n" +
                person.getNachname() + "\n" +
                person.getGeburtstag().ToShortDateString() + "\n");
                List<Adresse> adressen = person.getAdresseListe();

                foreach (Adresse adresse in adressen)

                {

                    Console.WriteLine(adresse.getPlz());


                }

Quasi so? Lässt sich komischerweise ausführen, aber kommt zu keiner entsprechenden Ausgabe
 
Zuletzt bearbeitet:
C#:
foreach (Person person in personen)

            {
                Console.WriteLine(
                person.getVorname() + "\n" +
                person.getNachname() + "\n" +
                person.getGeburtstag().ToShortDateString() + "\n");
             

                foreach (Adresse adresse in person.getAdresseListe())

                {
                    Console.WriteLine(adresse.getStrasse());
                    Console.WriteLine(adresse.getHausnr());
                    Console.WriteLine(adresse.getPlz());
                    Console.WriteLine(adresse.getOrt());

                }
             


            }

Jetzt mal direkt in der ForEach den getAdresseListe-Ausdruck eingefügt.
Leider aber wie gesagt immer noch keine Ausgabe (nur Vorname, Nachname, Geburtstag für jede Person), Programm lässt sich aber ausführen, weiß nicht an was das liegt
 
Griffindor01 schrieb:
Hier nochmal ein Versuch. Dachte schon, ich hätte es jetzt, aber leider auch erfolglos..
Das sieht doch schon mal deutlich besser aus! Und was genau funktioniert denn nun nicht? Wenn etwas nicht funktioniert, spuckt die IDE entweder Syntaxfehler aus, Compilerfehler oder Laufzeitfehler. Kommt einfach nur nicht das erwartete Ergebnis - der Code wird also ansonsten technisch einwandfrei ausgeführt - dann solltest du mittels Breakpoints durch die Anwendung durchsteppen und dir den Zustand der Variablen anschauen.

Griffindor01 schrieb:
Console.WriteLine(adresse);
Wenn du bei sowas ein Objekt übergibst, wird Console.Writeline implizit die .ToString() Methode des Objekts aufrufen. Sofern dort eine bestimmte Ausgabe erwünscht ist, muss man die ToString() Methode in der Klasse entsprechend einprogrammieren, sonst wird dort stets nur der Typ des Objekts ausgegeben.

Du hast doch bei der Personen-Liste schon alles an der Hand was du dafür brauchst. Oder hast du dort irgendwo Console.WriteLine(person) stehen? Nein, sondern Zeile für Zeile die Getter abgerufen und einzeln ausgegeben. Mach das doch bei den Adressen 1:1 genau so!
 
Raijin schrieb:
* überflüssiges Komplettzitat entfernt *
Ja, habe ich jetzt verstanden, da habe ich wohl nicht richtig nachgedacht ...
Programm lässt sich einwandrei ausführen, nur eben ohne das Ergebnis, dass die Adressen ausgegeben werden. :(
Was meinst du mit Breakpoints? Wurde bei uns noch nicht behandelt
 
Zuletzt bearbeitet von einem Moderator:
Fügst Du den mindestens eine Adresse jeder Person hinzu? Evtl. mal den Code von der Klasse Adresse posten ..
 
Griffindor01 schrieb:
Leider aber wie gesagt immer noch keine Ausgabe (nur Vorname, Nachname, Geburtstag für jede Person), Programm lässt sich aber ausführen, weiß nicht an was das liegt
Ok, das letzte Update kam während ich noch getippt hatte. Wie ich aber eben schon schrieb solltest du bei funktionierendem Code mit falschem Ergebnis den Code debuggen. Setze Breakpoints und prüfe den Inhalt der Variablen. Wenn zB bei der Person gar keine Adresse hinzugefügt wurde und somit die Adressliste leer ist, kann auch keine Ausgabe erfolgen.
Ergänzung ()

Griffindor01 schrieb:
Was meinst du mit Breakpoints? Wurde bei uns noch nicht behandelt
Womit programmierst du denn? Ich gehe mal von Visual Studio aus? Dann kannst du so Breakpoints einfügen und debuggen.

An dieser Stelle können wir anhand von Code-Schnipseln aber auch nicht mehr weiterhelfen, weil der Code funktionieren sollte, wenn die Rahmenbedingungen stimmen - zB korrekt hinzugefügte Adressen. Aktuell gehe ich davon aus, dass du keine Adressen hinzugefügt hast und die Listen in den Personen-Objekten schlicht und ergreifend leer sind. Poste doch bitte mal den Code der Klassen Person und Adresse sowie deine Main bzw. die Methoden, in denen du Personen und Adressen hinzufügst und die Ausgabe auslöst.
 
Zuletzt bearbeitet:
[CODE:CSHARP]

public void addNeueAdresse(Adresse _adr)
{


adressen.Add(_adr);
adressen.Add(new Adresse());

Ist die addNeueAdresse-Methode korrekt oder rührt da vielleicht der Fehler?
Aufgabenstellung ist schließlich, dass die Methode ein Adressen-Objekt übergeben kriegt und das einer Adressen-Liste hinzufügt. Habe dann, damit in der Liste 2 Adressen enthalten sind, noch eine neue Adresse mit den Werten des Standard-Konstruktors hinzugefügt wie im Code zu lesen.


Code:
 
Griffindor01 schrieb:
adressen.Add(_adr);
adressen.Add(new Adresse());
Damit fügst du erst die übergebene Adresse _adr zur Liste hinzu und danach noch eine weitere, leere Adresse. Wozu? Es reicht das erste Add, die ganze Methode besteht also aus einer einzigen Zeile und das war's.

Es geht an dieser Stelle aber auch darum ob die Funktion korrekt aufgerufen wird. Bitte poste den Code der Klassen und der Main bzw. die Stelle wo du Personen und Adressen hinzufügst und ausgibst.
 
Raijin schrieb:
* überflüssiges Komplettzitat entfernt *
Alles klar, ich sende euch mal die Klassen-Inhalte. Richtig, programmiere in Visual Studio




Klasse Person:

C#:
using System;
using System.Collections.Generic;
using System.Linq;

namespace KlasseMasse
{
    class Person
    {

        List<Adresse> adressen = new List<Adresse>();



        // Eigenschaften
        private string vorname;
        private string nachname;
        private DateTime geburtstag;
        private Adresse adresse;

        // Konstruktoren

        public Person()
        {
            vorname = "Erika";
            nachname = "Mustermann";
            geburtstag = new DateTime(1964, 8, 12);
            adresse = new Adresse();
        }

        public Person(string _vor, string _nach, DateTime _geb, Adresse _adr)
        {
            vorname = _vor;
            nachname = _nach;
            geburtstag = _geb;
            adresse = _adr;

        }

        // Get und Set Methoden
        public void setStraße(string _vor)
        {
            vorname = _vor;
        }
 
        public string getVorname()
        {
            return vorname;
        }

        public void setNachname(string _nach)
        {
            nachname = _nach;
        }

        public string getNachname()
        {
            return nachname;
        }

        public void setGeburtstag(DateTime _geb)
        {
            geburtstag = _geb;
        }

        public DateTime getGeburtstag()
        {
            return geburtstag;
        }

        public void addNeueAdresse(Adresse _adr)
        {
     
     
            adressen.Add(_adr);
            adressen.Add(new Adresse());
     


        }

        public List<Adresse> getAdresseListe()
        {

            return adressen;
     
     

        }


Klasse Adresse:





using System;
using System.Collections.Generic;
using System.Text;

namespace KlasseMasse
{
    class Adresse // Klassen-Name
    {
        // Eigenschaften (Attribute).
        private string strasse;
        private string hausnr;
        private string plz;
        private string ort;

        // Konstruktoren
        public Adresse() // Den Attributen der Klasse werden Namen bereitgestellt, sofern bei Instanziierung keine Werte angegeben.
        {
            strasse = "Heidestraße";
            hausnr = "17";
            plz = "51147";
            ort = "Köln";
        }

        public Adresse(string _str, string _hnr, string _plz, string _ort) // Werte werden Parametern zugewiesen, sofern definiert. Strasse = Erster Wert, der als _str definiert wurde.
        {
            strasse = _str;
            hausnr = _hnr;
            plz = _plz;
            ort = _ort;
        }

        // Set und Get Methoden
        public void setStrasse(string _str) // Der string _str, also gleichgesetzter string Straße wird an Methode überreicht.
        {
            strasse = _str;
        }
 
        public string getStrasse() // Straße wird ausgegeben
        {

            return strasse;
        }

        public void setHausnr(string _hnr) // Der string _hnr, also gleichgesetzter string Hausnummer wird an Methode überreicht.
        {
            hausnr = _hnr;
        }

        public string getHausnr() // Hausnummer wird ausgegeben
        {
            return hausnr;
        }

        public void setPlz(string _plz) // Der string _plz, also gleichgesetzter string Postleitzahl wird an Methode überreicht.
        {
            plz = _plz;
        }

        public string getPlz() // Postleitzahl wird ausgegeben
        {
            return plz;
        }
 
        public void setOrt(string _ort) // Der string _ort, also gleichgesetzter string Ort wird an Methode überreicht. Attribut kriegt Wert Parameter
        {
            ort = _ort;
        }

        public string getOrt() // Ort wird ausgegeben
        {
            return ort;
        }

 





    }
}



 





    }
}




Die Main:





using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;





namespace KlasseMasse
{

    class Program
    {
        static void Main(string[] args)
 
Zuletzt bearbeitet:
Schau dir mal bitte an wie du Personen erzeugst. Du übergibst dem Konstruktor ein new Adresse, was prinzpiell ja richtig ist. Da die Adresse nun aber nicht mehr in einer einzelnen Variable im Personenobjekt gespeichert, sondern einer Liste hinzugefügt werden soll, muss das im Konstruktor von Person natürlich auch angepasst werden. Aktuell setzt du weiterhin nur Person.adresse, nicht aber die Adressliste.

C#:
        List<Adresse> adressen = new List<Adresse>();    // das ist die neue Adressliste

        // Eigenschaften
        private string vorname;
        private string nachname;
        private DateTime geburtstag;
        private Adresse adresse;    // das ist die ehemalige, einzelne Adresse

        // Konstruktoren
        public Person()
        {
            vorname = "Erika";
            nachname = "Mustermann";
            geburtstag = new DateTime(1964, 8, 12);
            adresse = new Adresse();  // Hier setzt du immer noch die einzelne Adresse
        }

        public Person(string _vor, string _nach, DateTime _geb, Adresse _adr)
        {
            vorname = _vor;
            nachname = _nach;
            geburtstag = _geb;
            adresse = _adr; // Hier setzt du immer noch die einzelne Adresse
        }

Da adressen vom Konstruktor nicht gesetzt bzw. gefüllt wird und du auch nicht addNeueAdresse aufrufst, ist die Adressliste schlicht und ergreifend leer. Baue den Konstruktor also so um, dass er statt adresse eben direkt adressen.Add ausführt oder - besser - rufe im Konstruktor addNeueAdresse auf.

Griffindor01 schrieb:
Mit dem Befehl new Adresse() erstelle ich doch ein Adressen-Objekt mit den Werten aus dem Standard-Konstruktor, oder nicht?
Das ist zwar richtig, ist an dieser Stelle aber unangebracht, weil es komische Ausgaben erzeugt, wenn du zB 3 Adressen hinzufügst. Dann tauchen plötzlich 6 Adressen in der Liste auf, von denen jede 2. leer ist. Rufe zum Test mit mehreren Adressen einfach addNeueAdresse mehrmals auf und dann ist die Liste auch mit mehreren Adressen gefüllt.
 
private Adresse adresse; kann weg in Person, das ist ein überbleibsel aus der nur 1 Adresse-Klasse.

statt "adresse = ..." -> addNeueAdresse(_adr); im Person Kontruktor.
 
Raijin schrieb:
Schau dir mal bitte an wie du Personen erzeugst. Du übergibst dem Konstruktor ein new Adresse, was prinzpiell ja richtig ist. Da die Adresse nun aber nicht mehr in einer einzelnen Variable im Personenobjekt gespeichert, sondern einer Liste hinzugefügt werden soll, muss das im Konstruktor von Person natürlich auch angepasst werden. Aktuell setzt du weiterhin nur Person.adresse, nicht aber die Adressliste.

C#:
        List<Adresse> adressen = new List<Adresse>();    // das ist die neue Adressliste

        // Eigenschaften
        private string vorname;
        private string nachname;
        private DateTime geburtstag;
        private Adresse adresse;    // das ist die ehemalige, einzelne Adresse

        // Konstruktoren
        public Person()
        {
            vorname = "Erika";
            nachname = "Mustermann";
            geburtstag = new DateTime(1964, 8, 12);
            adresse = new Adresse();  // Hier setzt du immer noch die einzelne Adresse
        }

        public Person(string _vor, string _nach, DateTime _geb, Adresse _adr)
        {
            vorname = _vor;
            nachname = _nach;
            geburtstag = _geb;
            adresse = _adr; // Hier setzt du immer noch die einzelne Adresse
        }

Da adressen vom Konstruktor nicht gesetzt bzw. gefüllt wird und du auch nicht addNeueAdresse aufrufst, ist die Adressliste schlicht und ergreifend leer. Baue den Konstruktor also so um, dass er statt adresse eben direkt adressen.Add ausführt oder - besser - rufe im Konstruktor addNeueAdresse auf.


Das ist zwar richtig, ist an dieser Stelle aber unangebracht, weil es komische Ausgaben erzeugt, wenn du zB 3 Adressen hinzufügst. Dann tauchen plötzlich 6 Adressen in der Liste auf, von denen jede 2. leer ist. Rufe zum Test mit mehreren Adressen einfach addNeueAdresse mehrmals auf und dann ist die Liste auch mit mehreren Adressen gefüllt.
Herzlichen Dank für die großzügige Hilfe! Programm klappt soweit, bis auf das Personen-Objekt, das mit dem Standard-Konstruktor erstellt wird.

Habe es mal so versucht:

C#:
public Person()
        {
            vorname = "Erika";
            nachname = "Mustermann";
            geburtstag = new DateTime(1964, 8, 12);
            addNeueAdresse(new Adresse());
        
        }


Leider ab keine Ausgabe, wie muss ich da den Konstruktor verändern?


[\CODE]
 
Zurück
Oben