Datensätze mit Hilfe von Listen speichern
-
Werner Salomon schrieb:
Hallo Eddy131
statt
tNode * deleteList (tNode * node) {darf es ruhig
void deleteList (tNode * node) {heißen
Jetzt gibt er "fatal error LNK1169: Mindestens ein mehrfach definiertes Symbol gefunden." als fehlermeldung aus - ohne Verweis auf eine Stelle(geht bei dem Fehler ja auch nicht).
Werner Salomon schrieb:
In vielen Kursen und Seminaren wird die Implementierung einer einfach verketten Liste geübt. Ich unterstelle mal, dass es es auch bei Dir so ist. Was dabei meistens leider versäumt wird, ist die Möglichkeit, die Liste als Objekt darzustellen. Es scheint wirklich Dozenten zu geben, die 20-30 Jahre hinter der Entwicklung in der Softwaretechnologie hinter her sind.
Wenn Du jemals als Informatiker erfolgreich sein willst, solltest Du Dich genau damit auseinander setzen. Das ist viel wichtiger als das Gefummele mit den Zeiger.Wir haben Listen bis jetzt nur kurz angesprochen. Was noch weiter kommt seh ich im nächsten Semester.
Vielleicht liegt's auch daran, das ich Elektrotechnik studiere und im Gesamten nur 2 Semester Informatik habe^^Werner Salomon schrieb:
Versuche die Liste als ein Objekt zu begreifen, dem man Elemente (tListe) hinzufügen kann, von dem man Elemente entfernen kann, auf das Algorithmen wie 'Sortieren' angewendet werden können oder in dem man nach bestimmten Elementen suchen kann. In der Applikation - also da, wo Du die einzelnen Elemente einliest, hat die Listenverwaltung - und damit auch das new - nichts zu suchen.
Das könnte etwa so aussehen:...OK, wir hatten das new immer in der main-Funktion bei der Deklarierung des Datentyps...
Ein paar der Begriffe und Zeichen kenn ich noch nicht, aber im groben versteh ich den Ablauf.Werner Salomon schrieb:
Mit das wichtigste an einem Objekt sind Konstruktor und Destruktor, soweit dieser notwendig ist. Im Konstruktor (Zeile 20) wird pRoot mit 0 initialisiert, Du hast also keine Chance diese Liste zu verwenden, ohne dessen Zeiger zu initialisieren. er hat immer einen gültigen Wert. Im Destruktor (Zeile 21) wird die Liste wieder abgeräumt - mit der Methode clear(). Auch hier kannst Du als Anwender nichts verkehrt machen, es können keine Memoryleaks erzeugt werden
Verstanden. Auch wenn - bei unseren Programmen - eigentlich eher garnicht bis selten - benutzt. Initialisierung mit 0 in manchen Fällen schon, aber das Freigeben war oft unnötig(?).
Werner Salomon schrieb:
Kopieren und Zuweisen habe ich stillgelegt (Zeile 47,48) .. machen wir vielleicht später.
Zeile 47 ist leer und in 48 steht "private:"? In den Zeilen vertan oder versteh ich's nicht..?
Werner Salomon schrieb:
Nebenbei: Ist "using namespace std;" nicht einfacher und weniger Schreibkramm als immer st:: davor zu schreiben?
Man sollte überall dort, wo Typen definiert werden (z.B. tListe) das std:: davor schreiben. Der Grund dafür liegt einfach darin, dass die Typdefinitionen sehr schnell in einem H-File landen und dort solltest Du auf keinen Fall ein 'using namespace std' stehen haben.
Warum das so ist ... ok, schreib erst mal größere Programme. Letztlich hebelst Du den namespace-Mechanimus damit aus. Wenn das schief geht, wird's wirklich unangenehm.Das Verständnis dafür kommt bestimmt zu gegebener Zeit noch^^
Werner Salomon schrieb:
registriere Dich doch - kritisch wird es erst, wenn Du gar keine Antworten mehr bekommst

Mach ich doch juste mal

Stimmt!
Danke auch für die Hilfe!
Ich hab echt nicht gedacht, das man hier so gute Hilfe bekommt. Immerhin dauert das schon ein bisschen so'n Programm zu schreiben und sich in die Situation hineinzudenken.Also echt Top!

P.S.
Falls wer Lust hat, hätte ich nichts dagegen, wenn jemand das Programm in der mir gewohnten schreibweise verfassen würde^^P.P.S:
Was habt ihr gegen pop_front??
Auf Englisch ist das doch Jugendfrei
-
@Werner Salomon:
Jetzt hast du open "push~" und unten "pop~"
-
Eddy131 schrieb:
Werner Salomon schrieb:
Kopieren und Zuweisen habe ich stillgelegt (Zeile 47,48) .. machen wir vielleicht später.
Zeile 47 ist leer und in 48 steht "private:"? In den Zeilen vertan oder versteh ich's nicht..?
Ich hatte später noch zwei Zeilen Kommentar eingefügt. Gemeint sind die Zeilen 49 und 50.
Eddy131 schrieb:
@Werner Salomon:
Jetzt hast du open "push~" und unten "pop~"
meine Fehlerquote schient heute anzuziehen .. ich hab's korrigiert.
Gruß
Werner
-
Eddy131 schrieb:
Werner Salomon schrieb:
Kopieren und Zuweisen habe ich stillgelegt (Zeile 47,48) .. machen wir vielleicht später.
Zeile 47 ist leer und in 48 steht "private:"? In den Zeilen vertan oder versteh ich's nicht..?
Ich hatte später noch zwei Zeilen Kommentar hinzugefügt. Gemeint sind die Zeilen 49 und 50.
push - pop ist korrigiert.Gruß
Werner
-
Eddy131 schrieb:
Was habt ihr gegen pop_front??

Pushen und Poppen sind zwei feste Begriffe. Ersteres fügt Elemente hinzu, letzteres entfernt Elemente.
-
Werner Salomon schrieb:
Eddy131 schrieb:
Hab's jetzt bei Visual Studio reinkopiert und erstmal ggetestet.
Kommt gleich ne Fehlermeldung..

(26): error C4716: 'deleteList': Muss einen Wert zurückgeben
Hallo Eddy131
statt
tNode * deleteList (tNode * node) {darf es ruhig
void deleteList (tNode * node) {heißen
Stimmt ja.
-
Eddy131 schrieb:
P.S.
Falls wer Lust hat, hätte ich nichts dagegen, wenn jemand das Programm in der mir gewohnten schreibweise verfassen würde^^1.) was meinst Du damit genau?
2.) Wenn das das ist, was phyax, ich und sicher auch andere als 'C' betrachten, ist das dann auch sinnvoll?Denk' mal d'rüber nach
Gruß
Werner
-
C++ wollt ich schon. Mit C kenn ich mich nur insofern aus, das ich weiß das daraus C++ entstand.
Ich meint damit mehr die Form vom oben vorstellen und nach der main- die anderen Funktionen.
Das letzte von dir geschriebene Programm (Werner Salomon) reicht mir schon völlig, aber es kommt noch der Fehler:"fatal error LNK1169: Mindestens ein mehrfach definiertes Symbol gefunden."
mit dem ich nichts anfangen kann. Zumindest blieben meine Korrekturversuche Fruchtlos.
Es ist doch in C++, oder?
Was sagt mir die Fehlermeldung?
Also auf welche Art könnte ich ihn beheben?@Michael E.: Hätt ich mir denken können... Danke für die Info

Wird gespeichert.
-
Eddy131 schrieb:
Ich meint damit mehr die Form vom oben vorstellen und nach der main- die anderen Funktionen.
Hallo Eddy131,
das wäre kein Problem.
Eddy131 schrieb:
... aber es kommt noch der Fehler:
"fatal error LNK1169: Mindestens ein mehrfach definiertes Symbol gefunden."
ich vermute, dass in Deinem Projekt mehr als eine cpp-Datei enthalten ist, in dem sich eine main-Funktion befindet. Entferne die Dateien, bis auf die eine, die Du übersetzen willst, aus dem Projekt.
In der Fehlermeldung "error LNK2005: <Symbol> ist bereits in <Objekt> definiert" steht der Name des 'mehrfach definiertes Symbols'. Hier wäre das 'main'.Gruß
Werner
-
Werner Salomon schrieb:
ich vermute, dass in Deinem Projekt mehr als eine cpp-Datei enthalten ist, in dem sich eine main-Funktion befindet. Entferne die Dateien, bis auf die eine, die Du übersetzen willst, aus dem Projekt.
In der Fehlermeldung "error LNK2005: <Symbol> ist bereits in <Objekt> definiert" steht der Name des 'mehrfach definiertes Symbols'. Hier wäre das 'main'.Jou, das war's!
Hatte die verschiedenen Variationen von hier jeweils nebeneinander gespeichert. Dachte, das immer nur die oberste cpp Datei gedebugged wird

Man lernt echt nie aus.
So, jetzt arbeite ich mich mal da durch und versuch es zu verinnerlichen.
thanks so far

-
struct Liste { Liste() : pRoot(0) {} ~Liste() { clear(); } void clear() { for( tListe* p = pRoot; p; ) { tListe* tmp = p; p = p->pNext; delete tmp; } } // -- füge am Anfang der Liste ein Element ein void push_front( const tListe& data ) { tListe* p = new tListe( data ); p->pNext = pRoot; pRoot = p; } // -- gebe alle Elemente auf 'out' aus void ausgabe( std::ostream& out ) { for( tListe* p = pRoot; p; p = p->pNext ) out << *p << "\n"; } private: Liste( const Liste& ); Liste& operator=( const Liste& ); tListe* pRoot; };Kann man die Funktionen der zweiten struct auch auslagern, also für push_front, ausgabe und so jeweils eine eigene Funktion?
Und das am Ende mit "private:" kenn und versteh ich nicht. Kann man das irgendwie noch anders bewerkstelligen? bzw. was macht der part genau?
-
Eddy131 schrieb:
Kann man die Funktionen der zweiten struct auch auslagern, also für push_front, ausgabe und so jeweils eine eigene Funktion?
Ja:
// folgendes könnte auch in H-File 'Liste.h' - inklusive tListe struct Liste { Liste(); ~Liste(); void clear(); // -- füge am Anfang der Liste ein Element ein void push_front( const tListe& data ); // -- gebe alle Elemente auf 'out' aus void ausgabe( std::ostream& out ); private: Liste( const Liste& ); Liste& operator=( const Liste& ); tListe* pRoot; }; // hier käme z.B. die main-Funktion // .. nach main() oder so Liste::Liste() : pRoot(0) {} Liste::~Liste() { clear(); } void Liste::clear() { for( tListe* p = pRoot; p; ) { tListe* tmp = p; p = p->pNext; delete tmp; } } void Liste::push_front( const tListe& data ) { tListe* p = new tListe( data ); p->pNext = pRoot; pRoot = p; } void Liste::ausgabe( std::ostream& out ) { for( tListe* p = pRoot; p; p = p->pNext ) out << *p << "\n"; }Gruß
Werner
-
Hier jetzt das fertige Programm:
#include <iostream> #include <string> #include <iomanip> #include <conio.h> using namespace std; struct tListe { int matrNr; string vName; string fName; tListe *pNext; }; void einfuegen(tListe &hp); void ausgabe(); void sortMatrikel(); void sortVName(); void sortFName(); void sucheM(int zahl); void sucheV(string name); void sucheF(string name); tListe *pRoot = 0; int main () { tListe hp; int zahl; string wort; while (true) { cout << "Was wollen Sie tun?\n\n"; cout << "Einfuegen von neuen Datensaetzen [E/e]\n"; cout << "Sortieren [R/r]\n"; cout << "Suchen nach bestimmten Datensatz [S/s]\n"; cout << "Ausgabe der Datensaetze [A/a]\n"; cout << "Programm beenden [B/b]\n\n"; switch (tolower(_getch())) { case 'e': system ("cls"); cout << "Bitte geben Sie die entsprechenden Daten ein:\n\n"; cout << "\t\tMatrikelnummer:\n\t\t"; cin >> hp.matrNr; cout << "\t\tFamilienname:\n\t\t"; cin >> hp.fName; cout << "\t\tVorname:\n\t\t"; cin >> hp.vName; einfuegen(hp); break; case 'r': system ("cls"); cout << "Wonach wollen Sie sortieren?\n\n"; cout << "Matrikelnummer [M/m]\n"; cout << "Vorname [V/v]\n"; cout << "Familienname [F/f]\n\n"; switch (tolower(_getch())) { case 'm': sortMatrikel(); break; case 'v': sortVName(); break; case 'f': sortFName(); break; } ausgabe(); break; case 's': system ("cls"); cout << "Wonach wollen Sie suchen?\n\n"; cout << "Matrikelnummer [M/m]\n"; cout << "Vorname [V/v]\n"; cout << "Familienname [F/f]\n\n"; switch (tolower(_getch())) { case 'm': system ("cls"); cout << "Nach welcher Matrikelnummer soll gesucht werden?\n\n\t"; cin >> zahl; sucheM(zahl); break; case 'v': system ("cls"); cout << "Nach welchem Vornamen soll gesucht werden?\n\n\t"; cin >> wort; sucheV(wort); break; case 'f': system ("cls"); cout << "Nach welchem Familiennamen soll gesucht werden?\n\n\t"; cin >> wort; sucheF(wort); break; } break; case 'a': system ("cls"); ausgabe(); cout << "\n\n"; break; case 'b': return 0; } } } void einfuegen(tListe &hp) { tListe* p = new tListe(hp); p ->pNext = pRoot; pRoot = p; } void ausgabe() { int i = 1; for(tListe *p = pRoot; p; p = p->pNext) { cout << "\n" << i; cout << "\t" << p ->vName << " " << p ->fName << "\n\tMatr.#: " << p ->matrNr << "\n"; i++; } } void sortMatrikel() { tListe *hp1, *hp2; for (tListe *p = pRoot; p; p = p->pNext) { hp1 = pRoot ->pNext; hp2 = pRoot; while (hp1) { if ((hp1 ->matrNr) < (hp2 ->matrNr)) { swap (hp1, hp2); } hp2 = hp1; hp1 = hp1->pNext; } } } void sortVName() { tListe *hp1, *hp2; for (tListe *p = pRoot; p; p = p->pNext) { hp1 = pRoot ->pNext; hp2 = pRoot; while (hp1) { if (hp1 ->vName < hp2 ->vName) { swap (hp1, hp2); } hp2 = hp1; hp1 = hp1->pNext; } } } void sortFName() { tListe *hp1, *hp2; for (tListe *p = pRoot; p; p = p->pNext) { hp1 = pRoot ->pNext; hp2 = pRoot; while (hp1) { if (hp1 ->fName < hp2 ->fName) { swap (hp1, hp2); } hp2 = hp1; hp1 = hp1->pNext; } } } void sucheM(int zahl) { int i = 0; tListe *hp; hp = pRoot; while (hp) { i++; if (hp ->matrNr == zahl) { cout << "\n\nDatensatz vorhanden:\n\n"; cout << "\n" << i; cout << "\t" << hp ->vName << " " << hp ->fName << "\n\tMatr.#: " << hp ->matrNr << "\n\n"; } hp = hp ->pNext; } } void sucheV (string name) { int i = 0; tListe *hp; hp = pRoot; while (hp) { i++; if (hp ->vName == name) { cout << "\n\nDatensatz vorhanden:\n\n"; cout << "\n" << i; cout << "\t" << hp ->vName << " " << hp ->fName << "\n\tMatr.#: " << hp ->matrNr << "\n"; } hp = hp ->pNext; } } void sucheF (string name) { int i = 0; tListe *hp; hp = pRoot; while (hp) { i++; if (hp ->fName == name) { cout << "\n\nDatensatz vorhanden:\n\n"; cout << "\n" << i; cout << "\t" << hp ->vName << " " << hp ->fName << "\n\tMatr.#: " << hp ->matrNr << "\n"; } hp = hp ->pNext; } }eine Frage noch: Das sortieren funktioniert einwandfrei, aber wenn ich mehrere Datensätze (d.h. so ca. 5 Stück) drin hab, hängt er sich auf, also die CPU-Auslastung geht bei einem Kern auf 100% und es tut sich auch nach einer längeren Wartezeit nichts.
Fehler meinerseits oder ist mein Laptop überfordert (kann ich irgendwie nicht glauben...)Ansonsten recht herzliches Dankeschön, super Forum! weiter so!
