[Anfänger sucht Hilfe] Personalverwaltung - Datenerfassung und Ausgabe
-
Eventuell hilft dir das hier weiter:
-
AlphaX2 schrieb:
Das geht jedoch im Moment nur für 1 Person. Jetzt suche ich allerdings einen Weg, wie ich mehrere Personen eingeben und danach direkt als "Tabelle" ausgeben kann. In Python würde ich einfach Listen (die Daten) in eine Liste packen und ausgeben. Kann man sowas in C++ auch nachstellen, also structs in eine Liste packen oder so?
Ja und wie! Vergiss einfach diesen C/C++-Mischmasch. In "richtigem" C++ ist das total einfach:
(Ungetestet)
#include <string> #include <vector> #include <iostream> #include <limits> struct PersonInfoStruct // Ich würde bei Typennamen nicht angeben, dass es ein struct ist. Wozu soll das gut sein? { // Hier sollte man überlegen, ob die Attribute nicht lieber private sein sollten. std::string name; // Vergiss char-Arrays, außer du hast einen sehr guten Grund std::string surname; float hours; }; // Deine sub_new_person schreiben wir ein bisschen um und nennen sie anders: std::istream& operator>>(std::istream& in, PersonInfoStruct& person) { std::cout << "\tGeben Sie den Vornamen ein: "; // Naja, eigentlich sollte eine Eingabefunktion nix ausgeben, aber ich will nicht alles umbauen getline(person.name, in); std::cout << "\tGeben Sie den Nachnamen ein: "; getline(person.surname, in); std::cout << "\tGeben Sie die Arbeitsstunden ein: "; in >> person.hours; in.ignore(std::numeric_limits<std::streamsize>::max(), '\n'); return in; } // Ausgabe gibt's auch noch dazu: std::ostream& operator<<(std::ostream& out, const PersonInfoStruct& person) { return out << "Vorname: " << person.name << "\nNachname: " << person.surname << "\nArbeitsstunden: " << person.hours << '\n'; } int main() { // Wenn man das so gemacht hat, dann ist das Hauptprogramm sehr übersichtlich: std::vector<PersonInfoStruct> personenliste; for (PersonInfoStruct person; std::cin >> person; personenliste.push_back(person)); std::cout << "Folgende Personen sind bekannt:\n"; for (auto person : personenliste) std::cout << person << '\n'; }
-
Jo, SeppJ's Programm macht dasselbe wie meins (Telefonnummer <-> Arbeitsstunden).
Dafür speichert meins aber auch gleich die Daten in ner Datei ab, sodass sie beim nächsten Start des Programms noch da sind.
Das macht das Löschen/Ändern natürlich ein wenig interessanter, kannst dir ja was einfallen lassen.
-
Das ist ja überwältigend wie schnell man hier Hilfe bekommt. Erstmal vielen Dank dafür!!!
Ich werde mir mal die Sache mit den Vectoren ansehen, da ich grade noch die Hälfte des Codes verstehe.
Später wäre es sicherlich eh sinnvoller sowas als Objekt zu realisieren und wenn möglich zu speichern.
Ich werd mich mal einlesen und im Zweifelsfall nochmal nachfragen.
Danke!
AlphaX2
-
SeppJ schrieb:
struct PersonInfoStruct // Ich würde bei Typennamen nicht angeben, dass es ein struct ist. Wozu soll das gut sein? { // Hier sollte man überlegen, ob die Attribute nicht lieber private sein sollten. std::string name; // Vergiss char-Arrays, außer du hast einen sehr guten Grund std::string surname; float hours; };
Willst du dann für alle Member getter und setter machen, oder was hast du dir da genau vorgestellt?
Wäre es nicht auch besser, statt
float hours
int minutes
zu nehmen und zu Darstellungszwecken durch 60 zu teilen?
-
out schrieb:
Willst du dann für alle Member getter und setter machen, oder was hast du dir da genau vorgestellt?
Kommt auf die Anwendung an. Meine Klassen tun gewöhnlich etwas und sind nicht reine Datenhalden. Für reine Datenhalden bietet sich tatsächlich an, alles public zu machen. Für arbeitende Klassen
sollte besser alles gekapselt sein, sonst pfuscht noch jemand von außen an den Interna herum.
Wäre es nicht auch besser, statt
float hours
int minutes
zu nehmen und zu Darstellungszwecken durch 60 zu teilen?Kommt auch auf die Anwendung an.
-
Hmm ich hab mal versucht das ganze zu verstehen, wenn ich das richtig sehe wird cin überladen und damit der Part für die Eingabe ausgelöst, oder?!
Ist das so nötig, oder ist das nur zum verkürzen der Schreibarbeit?
@Incocnito:
Bei deinem Beispiel verstehe ich nicht ganz wie das mit dem vector läuft, der unter dem Namen "liste" auftaucht, dann ja aber nie genutzt wird, oder sehe ich das falsch? Du schreibst einfach in die Datei oder?AlphaX2
-
AlphaX2 schrieb:
Hmm ich hab mal versucht das ganze zu verstehen, wenn ich das richtig sehe wird cin überladen und damit der Part für die Eingabe ausgelöst, oder?!
Ist das so nötig, oder ist das nur zum verkürzen der Schreibarbeit?
@Incocnito:
Bei deinem Beispiel verstehe ich nicht ganz wie das mit dem vector läuft, der unter dem Namen "liste" auftaucht, dann ja aber nie genutzt wird, oder sehe ich das falsch? Du schreibst einfach in die Datei oder?AlphaX2
Also erstmal wird cin nicht überladen, sondern nur der Eingabeoperator. Schau dir einfach mal "Operatorüberladung" an. Das spart in der Tat nur Schreibarbeit und sieht cooler aus. Eine Funktion
... operator >>(...)
ist nur ne stinknormale Funktion wie jede andere, nur dass du halt Operatoren als Name und keine Buchtaben oder so verwendest. Kannst aber auch einfach eine Funktionvoid daten_einlesen(Person& p)
oder sowas verwenden, wenn du das mit den Operatoren noch nicht checkst. Ist aber echt einfach.Und zu meinem Code: Der vector da ist tatsächlich erstmal unnötig. Ich hatte den da aber stehn, weil ich schon in Gedanken dabei war, Löschen und Ändern zu implementieren, das dann aber wohl einfach gelassen und dann vergessen hatte, die Zeile zu löschen. Ich wollte nämlich zum Löschen/Ändern aus der Datei die Personen einlesen, im vector zwischenspeichern, dann den vector bearbeiten und danach mit dem (neuen) Inhalt des vectors die Datei überschreiben.
-
Ja das meinte ich eigentlich auch, dass der Operator >> überladen wird, das Prinzip kenn ich, hab es aber tatsächlich nur 1x (in Python) genutzt.
Und in deinem Beispiel wollte ich nur sicher gehen, dass ich das richtig gecheckt hab.Jedenfalls Danke, hab mich jetzt erst mal mit einem Minimal-Beispiel mit nur einer einfachen Zahleingabe und Zahlenliste eingefuchst.
Danke!
AlphaX2
-
So ich hab nochmal probiert und das ganze soweit (dachte ich), auf die Reihe bekommen, hab nun aber ein Problem mit der Ausgabe, der Code sieht jetzt so aus:
#include <iostream> #include <string> #include <vector> struct Person { std::string name; std::string surname; float hours; }; struct Person add_person() { Person p; std::cout << "Vorname: "; std::cin >> p.name; std::cout << "Nachname: "; std::cin >> p.surname; std::cout << "Stunden: "; std::cin >> p.hours; return p; } int main() { std::vector<Person> personenliste; Person result; do { result = add_person(); personenliste.push_back(result); } while(personenliste.size() < 3); std::cout << "Dies sind die Eingaben:" << std::endl; int i; for(i=0; i<personenliste.size(); i++) std::cout << personenliste[i].name << std::endl; std::cout << personenliste[i].surname << std::endl; std::cout << personenliste[i].hours << std::endl; return 0; }
Das ganze endet jedoch mit der Ausgabe der Vornamen (alle hintereinander) und anschließend mit einem Speicherzugriffsfehler.
Leider bin ich nämlich aus der Beispiel-Ausgabe von SeppJ nicht ganz schlau geworden, also genau genommen wie die for-Schleife hier genutzt wird:
std::cout << "Folgende Personen sind bekannt:\n"; for (auto person : personenliste) std::cout << person << '\n';
Vielen Dank für jeden weiteren Tipp.
AlphaX2
-
AlphaX2 schrieb:
... int i; for(i=0; i<personenliste.size(); i++) std::cout << personenliste[i].name << std::endl; std::cout << personenliste[i].surname << std::endl; std::cout << personenliste[i].hours << std::endl; ...
Auf Anhieb fallen mir diese Zeilen schon auf.
1. solltest du (sofern es nicht einen guten Grund gibt) die Deklaration von i auch in der Schleife machen... Dann sollte dir der 2te Fehler schon selbst auffallen.
2. Einrückung macht noch keinen Scope. Überlege mal wozu die geschweiften Klammern auch bei Schleifen dienen.
-
* zuviel verraten *
-
AlphaX2 schrieb:
Leider bin ich nämlich aus der Beispiel-Ausgabe von SeppJ nicht ganz schlau geworden, also genau genommen wie die for-Schleife hier genutzt wird:
std::cout << "Folgende Personen sind bekannt:\n"; for (auto person : personenliste) std::cout << person << '\n';
Diese for-Schleife (ebenso wie 'auto') funktioniert nur mit C++11, und ist eine spezielle Form (In anderen Sprachen wird sie häufig foreach genannt). Der erste Ausdruck ist das Element, der zweite die Liste über die iteriert wird.
-
Okay wo ist der Facepalm Smilie
Danke! Jetzt geht es wunderbar!Ah okay, werd ich mal paar Infos einholen zu dem for mit auto, klingt so, als würde es ähnlich wie in Python funktionieren.
Mal noch eine allgemeine Frage, bei dem Tutorial auf learncpp.com wird immer ein
using namespace std;
genutzt, hier scheint es ja die Mehrheit zu lassen und immer dasstd::
mit zu schreiben. Woran soll(te) man sich denn halten?Vielen Dank.
-
AlphaX2 schrieb:
Ah okay, werd ich mal paar Infos einholen zu dem for mit auto, klingt so, als würde es ähnlich wie in Python funktionieren.
Das auto hat erst einmal nichts mit diesem Schleifentyp zu tun. auto ist ein Stellvertreter für einen Typ der sich eindeutig herleiten lässt. Dient im wesentlichen der verkürzten Schreibweise:
// Was findest du verständlicher: std::vector<int> intvector; //... // Alte Schleifenvariante und Iteratorverwendung ohne auto for(std::vector<int>::const_iterator it=intvector.begin(), end=intvector.end(); it!=end; ++it) cout << *it; // Alte Schleifenvariante und Iteratorverwendung mit auto for(auto it=intvector.begin(), end=intvector.end(); it!=end; ++it) cout << *it;
Nachtrag:
Die neue for-Schleife ("for each"), hat den Aufbau: "for(<Typ> <Variablenname> : <Container>)" - du bist nicht gezwungen in dieser Kombination auto zu verwenden. Aber es bietet sich hier fast an.AlphaX2 schrieb:
Mal noch eine allgemeine Frage, bei dem Tutorial auf learncpp.com wird immer ein
using namespace std;
genutzt, hier scheint es ja die Mehrheit zu lassen und immer dasstd::
mit zu schreiben. Woran soll(te) man sich denn halten?Solange du niemals using namespace im Header, und immer hinter allen Inkludes machst, wird dir kaum einer reinreden, dann sind es persönliche Stilvorlieben. Erst wenn es zu Namenskonflikten kommt wird man dann etwas vorsichtiger.
-
AlphaX2 schrieb:
Mal noch eine allgemeine Frage, bei dem Tutorial auf learncpp.com wird immer ein using namespace std; genutzt, hier scheint es ja die Mehrheit zu lassen und immer das std:: mit zu schreiben. Woran soll(te) man sich denn halten?
Witzig, die Frage wiederholt sich ja.
http://www.c-plusplus.net/forum/p2232284#2232284
So, jetzt haben wir den Thread zweimal
Achja, das mit for(auto a : b) ist ein range-based for. Der Begriff wurde glaub ich noch nicht genannt. Einfach mal googeln.