Vektor-Funktion bricht nach einer Eingabe ab



  • Wie wäre es wenn du dir ein gutes Buch kaufst? Mit Nachfragen kommst du nicht immer weiter. Es gibt Gebiete in C++ die du so vielleicht nicht kennenlernst und du kannst keine Fragen zu Themen stellen von denen du nichtmal weißt, dass es sie gibt. Ein gutes Buch wird dich Stück für Stück aufklären und da kommts garnicht erst zu solchem Code wie oben. Da lernst du es von Anfang an richtig. Wenn du dann noch Fragen hast die du nach ausführlicher Google-Recherche nicht selbst beantworten kannst, wird dir hier sicher gern weiter geholfen 🙂



  • @Zhavok

    Ich habe das Buch von Bjarne Stroustrup „Einführung in die Programmierung C++“.

    Aber solche Lücken, die ich aufweise, werden in dem Buch oftmals nur schwer verständlich vermittelt. Viele Preisen das Buch, ich finde es an sich auch nicht schlecht, aber die Basics werden für einen Anfänger irgendwie schwer vermittelt

    #edit: Ich muss ja noch nicht direkt im ersten Semestef C++ voll drauf haben. Das wäre auch stark unrealistisch.
    Aber was ich hier mache dient der Klausurvorbereitung und da sollte ich zumindest mal Klassen aufstellen und entsprechende Funktionen schreiben können



  • Häufig helfen Bücher erst, wenn man schon Basics kennt. Basis aus Büchern zu lernen, finde ich schwierig. Reine Einsteigerbücher sind oft schlecht.

    Daher erstmal ein bisschen rumprobieren. Natürlich nicht ganz wahllos!

    Aber für den Anfang hilft häufig ein bisschen gesunder Menschenverstand:

    Was ist ein Video? Was sind die Eigenschaften eines Videos? Damit hast du schon eine erste Idee, wie deine Klasse "Video" aussehen sollte.

    Dann machst du weiter: was macht eine Videothek aus?

    Was macht einen Person aus, die in einer Videothek etwas ausleiht? Nun stellst du fest, dass "Person, die in einer Videothek was ausleiht" kein geeigneter Klassenname ist. Ist zu kompliziert. Also vielleicht: "Kunde"? Oder "Person"? Eine Person könnte Kunde mehrer Videotheken sein usw. Und dann wird es schwieriger.

    Ich dachte, dass ich hier einen Benutzer erzeuge, der die ID der zuvor eingegeben Nummer übernimmt

    Danach sieht es aus. Aber Benutzer(ID) sollte einen Benutzer mit einer Benutzer-ID erzeugen.

    und sie dann in Zeile 2 per push_back als Speicher dem Benutzer zuweist.

    Den Satz verstehe ich nicht. Du kopierst damit "newBenutzer" in die Liste von Videos. Ein Benutzer ist aber kein Video. Das geht also nicht.

    Außerdem: der Name "list" ist schlecht. Unter einer Liste würde man leicht eine std::list vermuten. Nenne sie lieber nach dem Inhalt, aber als Plural. Also zum Beispier "users" für einen std::vector<User> oder "videos" für einen std::vector<Video> (sofern du nicht mehrere solche Variablen hast, dann brauchst du noch bessere Namen).



  • Hallo zusammen. Danke für eure Kritik und Verbesserungsvorschläge. Ich habe mich nochmal rangesetzt und versucht den Code so einfach wie möglich, und das ohne Zeiger, zu strukturieren.

    Meine Erfolge:

    Benutzer.cpp

    Benutzer::Benutzer() { }
    
    Benutzer::Benutzer(string u, string pw) : user(u), password(pw) {}
    
    Benutzer::~Benutzer() {}
    
    
    void Benutzer::setCurrent_video(int current_video) { //kann sich aendern, guckt nicht nur ein Video, sondern mehrere
        
        this->current_video = current_video; 
    }
    
    
    string Benutzer::get_User() const {
        
        return user; 
    }
    
    string Benutzer::get_Password() const {
        
        return password; 
    }
    
    void Benutzer::print() {
    
        
            cout << "Benutzer-ID: " << user << endl << "Passwort: " << password << endl;
    }
    
    void Benutzer::fillFavourite(int id) {
        
        this->myFavourite.push_back(id); //ich lege in meinen Vektor myFavourite jedesmal die ID 
          
        
    }
    

    OnlineVideothek

    OnlineVideothek::OnlineVideothek() {}
    
    OnlineVideothek::~OnlineVideothek() {}
    
    void OnlineVideothek::createUser(string name, string password) {
        
        //Alternative
        /*Benutzer b(name, password); 
        this->users.push_back(b);*/
        
        bool notFound = true;
        for (unsigned int i=0; i < users.size(); i++) {
            
            if ( name == users.at(i).get_User() ) {
                
                cout << "Name ist bereits belegt!";
                notFound = false;
                break;
            }
        }
        if(notFound)
        {
            this->users.push_back(Benutzer(name, password));
        }
    }
    
    void OnlineVideothek::createVideo(string title, int maxViews) {
        
        bool notFound = true;
        
        for (unsigned int i=0; i < videos.size(); i++) {
            
            if (title == videos.at(i).getTitel()){
                
                cout << "Titel ist bereits vorhanden!";
                notFound = false;
                break;
            }
        }
        
        if (notFound) {
        
            this->videos.push_back(Video(title,0,maxViews));
        
        }
    }
    
    bool OnlineVideothek::login(string name, string password) {
        
        for (unsigned int i=0; i < this->users.size(); i++) {
            
            if ( name == this->users.at(i).get_User() && password == this->users.at(i).get_Password() )
            {    
                return true;
            } 
            else 
            {
                
                return false;
            }
        }
        
        return false; 
    }
    
    void OnlineVideothek::showAllVideos() const {
        
        for (unsigned int i = 0; i < videos.size(); i++) {
            
            cout << "Video: ";
            videos.at(i).print(); 
            
        }
        
    }
    
    void OnlineVideothek::addToFavorites(string name, int id) {
        
        
        bool foundUser = false;
        bool foundVideo = false;
        int userIndex = -1;
        int videoIndex = -1;
        
        for (unsigned int i = 0; i < users.size(); i++) 
        {
            if(users.at(i).get_User() == name)
            {
                
                foundUser = true;
                userIndex = i;
                
            }
            else {
                
                throw runtime_error {"Benutzer nicht gefunden!"};
            }
        }
        
        
        for (unsigned int i = 0; i < videos.size(); i++) 
        {
            if (videos.at(i).getID() == id )
            {
                foundVideo = true;
                videoIndex = i;
            }
            else {
                
                throw runtime_error {"Video nicht gefunden!"};
            }
        }
        
        
        if (foundUser && foundVideo) 
        {
            users.at(userIndex).fillFavourite(videos.at(videoIndex).getID());
        }
    }
    

    Damit bin ich auch fast bei der Vollendung meines Übungstests, allerdings fehlt mir nur noch eine Funktion

    watch(string name, int id) 
    

    Bei der ich simulieren muss, dass der angegebene Benutzer das angebene Video anschaut. Dazu muss ich dem angegebenen Benutzer die entsprechende ID des Videos übergeben.

    Ich weiß, dass die Parameter, die hier übergeben werden, sprich string name, der Name des Users ist und int id, die ID des Videos.
    Ich habe bei Benutzer.cpp die Methode geschrieben:

    void Benutzer::setCurrent_video(int current_video) { //kann sich aendern, guckt nicht nur ein Video, sondern mehrere
        
        this->current_video = current_video; 
    }
    

    Diese Methode muss ich für meine watch-Funktion aufrufen und der Methode die ID-Nummer des Videos übergeben und die Anzahl der Zuschauer des Videos um 1 inkrementieren, da wir dadurch einen neuen Zuschauer für das Video haben.

    Mein Grundgedanke:

     
    void OnlineVideothek::watch(string name, int id) {
            
            int current_video = 0;
            int current_watching = 0; 
            bool videoFound = false;
            bool userFound = false;
            
            
            for ( unsigned int i = 0; i < this->videos.size(); i++ ) {
                
                if ( id == videos.at(i).getID() ) {
                    
                    videoFound = true; 
                    current_video = i; 
                    
                }
                
                
            }
            
            for ( unsigned int i = 0; i < this->users.size(); i++) {
                
                if ( name == users.at(i).get_User()) {
                    
                    userFound = true; 
                    current_watching = i;
                     
                    
                }
                
            }
            
            if ( userFound && videoFound )
            {
                this->users.at(current_watching).setCurrent_video(videos.at(current_video).getID());
                current_watching++; 
                 
            }  
        }
    
    

    Meine Idee dahinter ist, dass ich beide Vektoren auf den richtigen User und Video überprüfen muss und dann, wenn der richtige User und das richtige Video gefunden wurde, dann das gefundene Video, die ID, dem gefundenen User übergebe.

    #edit: Ich habe meinen Ansatz mal gepostet, wo könnte dort ein Problem entstehen oder an welcher Stelle macht das ganze keinen Sinn?



  • @Suprax sagte in Vektor-Funktion bricht nach einer Eingabe ab:

    #edit: Ich muss ja noch nicht direkt im ersten Semestef C++ voll drauf haben. Das wäre auch stark unrealistisch.
    Aber was ich hier mache dient der Klausurvorbereitung und da sollte ich zumindest mal Klassen aufstellen und entsprechende Funktionen schreiben können

    klassen sind objektorientierte modellierung!

    #edit: Ich habe meinen Ansatz mal gepostet, wo könnte dort ein Problem entstehen oder an welcher Stelle macht das ganze keinen Sinn?

    funktioniert es denn?



  • Das tut ja beim zusehen schon weh!?

    #include <cstddef>
    #include <limits>
    #include <stdexcept>
    #include <algorithm>
    #include <utility>
    #include <iterator>
    #include <vector>  // eine deque taete es auch
    #include <string>
    #include <map>
    #include <iostream>
    #include <fstream>
    
    
    class user_t {
    	std::string username;
    	std::string password;  // nein, natürlich nicht. man speichert nur einen gesalzenen hash.
    	std::string display_name;
    	
    	using favourite_videos_t = std::vector<std::size_t>;
    	favourite_videos_t favourite_videos;
    
    public:
    	user_t() = default;
    	user_t(std::string username, std::string password, std::string display_name = "")
    	: username     { username     }
    	, password     { password     }
    	, display_name { display_name }
    	{}
    
    	std::string get_username()                 const { return username; }
    	std::string get_display_name()             const { return display_name; }
    	std::size_t get_favourites_count()         const { return favourite_videos.size(); }
    	favourite_videos_t const& get_favourites() const { return favourite_videos; }
    
    	friend bool operator==(user_t const &lhs, user_t const &rhs);
    	friend std::istream& operator>>(std::istream &is, user_t &user);
    	friend std::ostream& operator<<(std::ostream &os, user_t const &user);
    };
    
    bool operator==(user_t const &lhs, user_t const &rhs)
    {
    	return lhs.username == rhs.username && lhs.password == rhs.password;
    }
    
    std::istream& operator>>(std::istream &is, user_t &user)
    {
    	std::string username, password, display_name;
    	if (is >> username >> password >> display_name) {
    		user = { username, password, display_name };
    		std::copy(std::istream_iterator<std::size_t>{is}, std::istream_iterator<std::size_t>{},
    		          std::back_insert_iterator<user_t::favourite_videos_t>{ user.favourite_videos });
    		is.clear();
    	}
    	return is;
    }
    
    std::ostream& operator<<(std::ostream &os, user_t const &user)
    {
    	return os << user.username << ' ' << user.password << ' ' << user.display_name;
    }
    
    
    class video_t {
    	std::size_t id{};
    	std::string title;
    
    public:
    	video_t() = default;
    	video_t(std::size_t id, std::string title)
    	: id    { id }
    	, title { title }
    	{}
    	
    	std::size_t get_id() const { return id; }
    
    	friend std::istream& operator>>(std::istream &is, video_t &video);
    	friend std::ostream& operator<<(std::ostream &os, video_t const &video);
    	friend std::ostream& operator<<(std::ostream &os, std::pair<std::size_t, video_t> const &id_video_pair);
    };
    
    std::istream& operator>>(std::istream &is, video_t &video)
    {
    	std::size_t id;
    	std::string title;
    	if ((is >> id) && std::getline(is, title))
    		video = { id, title };
    	return is;
    }
    
    std::ostream& operator<<(std::ostream &os, video_t const &video)
    {
    	return os << video.id << ' ' << video.title;
    }
    
    std::ostream& operator<<(std::ostream &os, std::pair<std::size_t, video_t> const &id_video_pair)
    {
    	return os << id_video_pair.second;
    }
    
    
    class video_library_t {
    	static char const * const users_file_name;
    	static char const * const videos_file_name;
    
    	using users_t = std::vector<user_t>;
    	using videos_t = std::map<std::size_t, video_t>;
    
    	users_t users;
    	videos_t videos;
    
    	users_t::iterator current_user;
    
    public:
    	video_library_t();
    
    	bool logon(std::string username, std::string password);
    	void greet() const;
    	void show_account_info() const;
    	void list_users_favourites() const;
    	void list_available_videos() const;
    };
    
    char const * const video_library_t::users_file_name{ "users.txt" };
    char const * const video_library_t::videos_file_name{ "videos.txt" };
    
    video_library_t::video_library_t()
    {
    	std::ifstream users_stream{ users_file_name };
    	if (!users_stream.is_open())
    		throw std::runtime_error{ "Couldn't open users file :(" };
    	
    	std::copy(std::istream_iterator<user_t>{ users_stream }, std::istream_iterator<user_t>{},
    	          std::back_insert_iterator<users_t>{ users });
    
    	std::ifstream videos_stream{ videos_file_name };
    	if (!videos_stream.is_open())
    		throw std::runtime_error{ "Couldn't open videos file :(" };
    
    	using tmp_videos_t = std::vector<video_t>;
    	tmp_videos_t tmp_videos;
    	std::copy(std::istream_iterator<video_t>{ videos_stream }, std::istream_iterator<video_t>{},
    	          std::back_insert_iterator<tmp_videos_t>{ tmp_videos });
    	
    	for (auto &video : tmp_videos)
    		videos[video.get_id()] = video;	
    }
    
    bool video_library_t::logon(std::string username, std::string password)
    {
    	current_user = std::find(users.begin(), users.end(), user_t{ username, password });
    	return current_user != users.end();
    }
    
    void video_library_t::greet() const
    {
    	if (current_user != users.end())
    		std::cout << "Hello, " << current_user->get_display_name() << "!\n";
    	else
    		throw std::logic_error{ "There is no logged on user :(" };
    }
    
    void video_library_t::show_account_info() const
    {
    	if (current_user != users.end())
    		std::cout << "Username:     " << current_user->get_username() << '\n'
    		          << "Display name: " << current_user->get_display_name() << '\n'
    		          << "Favourites:   " << current_user->get_favourites_count() << '\n';
    	else
    		throw std::logic_error{ "There is no logged on user :(" };
    }
    
    void video_library_t::list_users_favourites() const
    {
    	if (current_user != users.end()) {
    		for (auto id : current_user->get_favourites()) {
    			std::cout << id << '\n';
    		}
    	}
    	else
    		throw std::logic_error{ "There is no logged on user :(" };
    }
    
    void video_library_t::list_available_videos() const
    {
    	std::copy(videos.begin(), videos.end(), std::ostream_iterator<std::pair<std::size_t, video_t>>{ std::cout, "\n" });
    }
    
    
    int main()
    {
    	try {
    		std::cout << "Welcome to the worlds greatest(tm) Online Video Library :)\n\n";
    
    		std::string username;
    		std::string password;
    		if (!(std::cout << "  Username: ", std::cin >> username) || !(std::cout << "  Password: ", std::cin >> password))
    			throw std::runtime_error{ "Input error during logon :(" };
    
    		video_library_t video_library;
    		if (!video_library.logon(username, password)) {
    			std::cout << "Invalid username and/or password :(\n\n";
    			return EXIT_SUCCESS;
    		}
    
    		for (;;) {
    			std::cout << "\n\n";
    			video_library.greet();
    			std::cout << "\n[1]  Show my account info\n"
    			               "[2]  List my favourite videos\n"
    			               "[3]  List available videos\n"
    			               "[0]  Exit\n\n"
    			               "Your choice: ";
    			int choice;
    			if (!(std::cin >> choice)) {
    				std::cerr << "\nInput Error :(\n\n";
    				std::cin.clear();
    				std::cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
    				continue;
    			}
    
    			std::cout.put('\n');
    
    			switch (choice) {
    			case 1:  // Show my account info
    				std::cout << "---== Account info ==--- \n";
    				video_library.show_account_info();
    				break;
    			
    			case 2:  // List my favourite movies
    				std::cout << "---== Favourite movies ==---\n";
    				video_library.list_users_favourites();
    				break;
    			
    			case 3:  // List available movies
    				std::cout << "---== Available movies ==---\n";
    				video_library.list_available_videos();
    				break;
    			
    
    			// to-do:  - edit users favourite movies (add / delete)
    			//         - edit available movies  (add / alter / delete)
    			//           (a deleted movie should probably be removed of users favourites as well)
    			//         - ...
    			//         - ???
    			//         - Profit.
    
    
    			case 0:  // Exit
    				std::cout << "Bye :)\n\n";
    				return EXIT_SUCCESS;
    
    			default:
    				std::cerr << "There is no menu item #" << choice << " :(\n";
    			}
    		}
    	}
    	catch (std::runtime_error &e) {
    		std::cerr << "Runtime error: " << e.what() << "\n\n";
    		return EXIT_FAILURE;
    	}
    	catch (std::logic_error &e) {
    		std::cerr << "Logic error: " << e.what() << "\n\n";
    		return EXIT_FAILURE;
    	}
    	catch (...) {
    		std::cerr << "An unknown exception occured :(\n\n";
    		return EXIT_FAILURE;
    	}
    }
    

    videos.txt
     1 Last Tango in Paris
     2 Eternal Sunshine of the Spotless Mind
     3 Rebel Without a Cause
     4 Cool Hand Luke
     5 Dangerous Liaisons
     6 Raging Bull
     7 Fatal Attraction
     8 Mo Better Blues
     9 No Country for Old Men
    10 Gone With The Wind
    11 Apocalypse Now
    12 Things We Lost in the Fire
    13 The French Connection
    14 There Will Be Blood
    15 Slumdog Millionaire
    16 Zero Dark Thirty
    17 Super Fly
    18 Silence of the Lambs
    19 Tinker, Tailor, Soldier, Spy
    20 Run Lola Run
    21 Almost Famous
    22 The Devil Wears Prada
    23 The Good, the Bad and the Ugly
    24 A Low Down Dirty Shame
    25 I'm Gonna Get You Sucka
    26 Austin Powers: International Man of Mystery
    27 Dr. Strangelove
    28 Psycho
    29 Enter the Dragon
    30 One Flew Over the Cuckoo's Nest
    31 Tears of the Sun
    32 The Last Picture Show
    33 Blade Runner
    34 Along Came a Spider
    35 Embrace the Serpent
    36 The Last Emperor
    37 Whale Rider
    38 The Man Who Fell to Earth
    39 A Clockwork Orange
    40 Things to Do in Denver When You're Dead
    41 The Longest Day
    42 Bring Me the Head of Alfredo Garcia
    43 Shawshank Redemption
    44 Good Will Hunting
    45 Bang the Drum Slowly
    46 The Place Beyond the Pines
    47 They Shoot Horses, Don't They?
    48 Kill Bill
    49 Three Days of the Condor
    50 Snakes on a Plane
    

    users.txt
    foo a MrFoo 5 23 4
    bar b MrBar 17
    


  • @Swordfish: Die Member-Variable current_user ist bei deinem Code uninitialisiert, d.h. ohne Aufruf von logon würden die Abfragen auf users.end() trotzdem so nicht funktionieren (und wahrscheinlich einen Speicherzugriffsfehler auslösen ;-).



  • @Wade1234 ja es kompiliert fehlerfrei.
    Aber ob die Funktion so ihren Zweck erfüllt bin ich mir nicht wirklich sicher?

    @Swordfish jetzt hast du mir einen kompletten Quellcode gecodet, danke! Aber ich arbeite mit meinen erstmal weiter und baue den so gut ich kann aus.
    Dein Niveau zu programmieren ist noch ein Stück zu hoch für mich, da ich ja erst noch dabei bin zu lernen. Für dich ist mein Programmcode zwar schmerzhaft beim anschauen, aber ich möchte den so einfach halten wie möglich 😃



  • @Suprax sagte in Vektor-Funktion bricht nach einer Eingabe ab:

    @Wade1234 ja es kompiliert fehlerfrei.
    Aber ob die Funktion so ihren Zweck erfüllt bin ich mir nicht wirklich sicher?

    der programmtest gehört zur entwicklung dazu. 🙄



  • @Suprax sagte in Vektor-Funktion bricht nach einer Eingabe ab:

    aber ich möchte den so einfach halten wie möglich

    Das ist ja das Problem. std::find() ist einfach. Einfach zu erlernen, einfach zu lesen und einfach viel wenig Fehleranfällig als immer wieder Schleifen hinzuschreiben wie Du es in Deinen letzen Codeschnippeln gemacht hast. Mein Code sollte Dir eigentlich zeigen wie sehr einfach es sein kann. Du solltest wirklich, wirklich alles vergessen was Du Dir durch irgendwelche utube-Videos angeeignet hast, das Buch vom Struppi nehmen und von vorne anfangen. Ganz vorne. Wenn was unklar ist beim Durcharbeiten des Buches: fragen.



  • Moin an Alle,
    ich habe mein Programm so gut wie fertig geschrieben.
    @Swordfish Ich möchte an der Stelle anmerken, dass ich mir deinen Rat bzgl. des Buches zu Herzen nehmen werde, allerdings muss ich erstmal bis zu den Klausuren mit meinen Kenntnissen arbeiten und kann nicht sozusagen von 0 das ganze Buch von vorne anfangen, daher versuch nicht allzu sehr Augenschmerzen beim Quellcode zu bekommen 😃

    OnlineVideothek::OnlineVideothek() {}
    
    OnlineVideothek::~OnlineVideothek() {}
    
    void OnlineVideothek::createUser(string name, string password) {
        
        //Alternative
        /*Benutzer b(name, password); 
        this->users.push_back(b);*/
        
        bool notFound = true;
        for (unsigned int i=0; i < users.size(); i++) {
            
            if ( name == users.at(i).get_User() ) {
                
                cout << "Name ist bereits belegt!";
                notFound = false;
                break;
            }
        }
        if(notFound)
        {
            this->users.push_back(Benutzer(name, password));
        }
    }
    
    void OnlineVideothek::createVideo(string title, int maxViews) {
        
        bool notFound = true;
        
        for (unsigned int i=0; i < videos.size(); i++) {
            
            if (title == videos.at(i).getTitel()){
                
                cout << "Titel ist bereits vorhanden!";
                notFound = false;
                break;
            }
        }
        
        if (notFound) {
        
            this->videos.push_back(Video(title,0,maxViews));
        
        }
    }
    
    vector<Video> OnlineVideothek::getVideos() const {
        
        return this->videos;
    }
    
    vector<Benutzer> OnlineVideothek::getUsers() const {
        
        return this->users; 
    }
    
    bool OnlineVideothek::login(string name, string password) {
        
        for (unsigned int i=0; i < this->users.size(); i++) {
            
            if ( name == this->users.at(i).get_User() && password == this->users.at(i).get_Password() )
            {    
                return true;
            } 
            else 
            {
                
                return false;
            }
        }
        
        return false; 
    }
    
    void OnlineVideothek::showAllVideos() const {
        
        for (unsigned int i = 0; i < videos.size(); i++) {
            
            cout << "Video: ";
            videos.at(i).print(); 
            
        }
        
    }
    
    void OnlineVideothek::addToFavorites(string name, int id) {
        
        
        bool foundUser = false;
        bool foundVideo = false;
        int userIndex = -1;
        int videoIndex = -1;
        
        for (unsigned int i = 0; i < users.size(); i++) 
        {
            if(users.at(i).get_User() == name)
            {
                
                foundUser = true;
                userIndex = i;
                
            }
            else {
                
                throw runtime_error {"Benutzer nicht gefunden!"};
            }
        }
        
        
        for (unsigned int i = 0; i < videos.size(); i++) 
        {
            if (videos.at(i).getID() == id )
            {
                foundVideo = true;
                videoIndex = i;
            }
            else {
                
                throw runtime_error {"Video nicht gefunden!"};
            }
        }
        
        
        if (foundUser && foundVideo) 
        {
            users.at(userIndex).fillFavourite(videos.at(videoIndex).getID());
        }
    }
    
    void OnlineVideothek::watch(string name, int id) {
        
        int current_video = -1;
        int current_watching = -1; 
        bool videoFound = false;
        bool userFound = false;
        
        for ( unsigned int i = 0; i < this->videos.size(); i++ ) {
            
            if ( id == videos.at(i).getID() ) {
                
                videoFound = true; 
                current_video = i; 
                
            }  
        }
        
        for ( unsigned int i = 0; i < this->users.size(); i++) {
            
            if ( name == users.at(i).get_User()) {
                
                userFound = true; 
                current_watching = i;
            }
        }
        
        if ( userFound && videoFound )
        {
            this->users.at(current_watching).setCurrent_video(videos.at(current_video).getID());
            
            if ( videos.at(current_video).getLimit() > videos.at(current_video).getViews()) {
            this->videos.at(current_video).addViews(); }
            
            
        }  
    }
    
    Video OnlineVideothek::findVideo(int id) {
        
        for (unsigned int i = 0; i < this->videos.size(); i++) {
            
            if (this->videos.at(i).getID() == id ) {
                
                return this->videos.at(i); 
            }
            
        }
        
    }
    
    Benutzer OnlineVideothek::findUser(string name) {
        
        for (unsigned int i = 0; i < this->users.size(); i++) {
            
            if (this->users.at(i).get_User() == name) {
                
                return this->users.at(i); 
            }
        }
        
    }
    
    Benutzer::Benutzer() { }
    
    Benutzer::Benutzer(string u, string pw) : user(u), password(pw) {}
    
    Benutzer::~Benutzer() {}
    
    
    void Benutzer::setCurrent_video(int current_video) { //kann sich aendern, guckt nicht nur ein Video, sondern mehrere
        
        this->current_video = current_video; 
    }
    
    
    
    string Benutzer::get_User() const {
        
        return user; 
    }
    
    string Benutzer::get_Password() const {
        
        return password; 
    }
    
    vector<int> Benutzer::getFavourite() const {
        
        return this->myFavourite; 
    }
    
    void Benutzer::print() {
    
        
            cout << "Benutzer-ID: " << user << endl << "Passwort: " << password << endl;
    }
    
    void Benutzer::fillFavourite(int id) {
        
        this->myFavourite.push_back(id); //ich lege in meinen Vektor myFavourite jedesmal die ID 
          
        
    }
    
    
    using namespace std;
    
    
    Video::Video( string t, int v, int l) : titel(t), views(v), limit(l) {
    
        id = counter; 
        counter++; 
    }
    
    Video::~Video() {}
    
    int Video::getID() const {
    
        return id;
    }
    
    string Video::getTitel() const {
    
        return titel;
    }
    
    void Video::setViews(int views) {
        
        this->views = views;  //Wir haben einmal views außerhalb und innerhalb der Klasse, die mit dem This sich auf 
                              //das views von dem Parameter der mit setViews übergeben wird
    }
    
    void Video::addViews() {
        
        this->views++; 
        
    }
    
    int Video::getViews() const {
    
        return views;
    }
    
    int Video::getLimit() const {
    
            return limit;
    }
    
    void Video::print() const {
        
        if (limit > 8 || limit < 0) {
    
            throw runtime_error("Ungueltiger Zahlenbereich!");
        } else {
    
        cout << "ID:" << id << " Titel:" << titel << " Views:" << views << " Limit:" << limit << endl;
    
        }
        
    }
    
    #include "Video.h"
    #include "Benutzer.h"
    #include "OnlineVideothek.h"
    #include "myError.h"
    #include <iostream>
    #include <vector>
    
    using namespace std;
    
    int main() try
    {
    
        OnlineVideothek test; 
        
        bool end = false;
        
        do{
            string current_user; 
            int eingabe {}; 
            
            cout << "1. Video hinzufuegen: " << endl;
            cout << "2. Login: " << endl;
            cout << "3. Favoriten anzeigen: " << endl;
            cout << "4. Zu Favoriten hinzufuegen: " << endl;
            cout << "5. Videos anzeigen: " << endl;
            cout << "6. Nur neue Videos anzeigen: " << endl;
            cout << "7. Film ansehen: " << endl; 
            
            cin >> eingabe; 
            
            switch (eingabe) {
                           
                case 1: {
                    string name; 
                    int maxViews; 
                    
                    cout << "Name des Videos: " << endl;
                    cin >> name;
                    cout << "Anzahl der max Views: ";
                    cin >> maxViews; 
                    test.createVideo(name, maxViews);
                    cout << "Video " << name << "wurde erfolgreich hinzugefuegt!" << endl; 
                     
                }
                
                case 2: {
                    string name;
                    string password;
                    cout << "Bitte ID eingeben: ";
                    cin >> name;
                    cout << "Nun das Passwort: ";
                    cin >> password;
                    cout << endl; 
                    
                  
                        
                        if (test.login(name,password)) {
                           
                            cout << "Login wurde erfolgreich ausgefuehrt!"; 
                            current_user = name; 
                        }
                     
                }
                
                case 3: {
                    
                    for ( unsigned int i = 0; i < test.getUsers().size(); i++) {
                        
                        if (test.getUsers().at(i).get_User() == current_user ) {
                            
                            for ( unsigned int j = 0; j < test.getUsers().at(i).getFavourite().size(); j++) {
                           
                                test.findVideo(test.getUsers().at(i).getFavourite().at(j)).print();
                            }
                            
                        }
                        
                    }
                    cout << endl;
                    
                }
                
                case 4: {
                    int id {}; 
                    
                    cout << "Gib eine ID eines Videos ein: ";
                    cin >> id;
                    test.addToFavorites(current_user,id);
                     
                }
                
                case 5: {
                    
                    cout << "Alle deine Videos: ";
                    test.showAllVideos();
                    
                    
                }
                
                case 6: {
                    
                    cout << "Alle deine neuen Videos: ";
                    bool found = false;
                    
                        for(unsigned int j = 0; j < test.getVideos().size(); j++)
                        {
                            
                            for(unsigned int i = 0; i < test.findUser(current_user).getFavourite().size(); i++)
                            {
                                if(test.getVideos().at(j).getID() == test.findUser(current_user).getFavourite().at(i))
                                {
                                    found = true;
                                }
                                else {
                                    
                                    found = false; 
                                }
                            
                            }
                            
                        }
                     
                   }
                
                case 7: {
                    
                    int id; 
                    
                    cout << "Bitte ID eingeben: ";
                    cin >> id;
                    
                    test.findVideo(id).addViews();
                    test.findUser(current_user).setCurrent_video(id); 
                     
                }
            }
            
        
        }while(!end);
        
            return 0; 
            
    }
     catch (std::exception& e) {
        std::cerr << "StdLib Ausnahme: " << e.what();
        return 1;
    } catch (...) {
        std::cerr << "Unbekannte Ausnahme\n";
        return 2;
    }
    

    Das ist mein jetziger Quellcode.
    Er läuft soweit, nur gibt es noch 2 kleine Fehler:

    1. Er führt die Switch-Case Reihe nicht richtig aus. Setze ich kein Break, läuft er von Case 1 zu Case 2, ohne dass der Benutzer eine Eingabe getätigt hast.
      Allerdings soll der Benutzer bei jedem Case neu entscheiden, ob er zu Case 1 oder Case 5 z.b. springt und die Eingabe muss dementsprechend gespeichert werden.

    2. Wenn ich Case 1 ausführe, kann ich nicht "Der Pate" eingeben, sondern nur "Pate" oder "Der", da er anscheinend die zwei Wörter für jeweils einen String hält.
      Kann ich diese Problematik umgehen, ohne noch eine string variable einzuführen?



  • @Suprax sagte in Vektor-Funktion bricht nach einer Eingabe ab:

    Das ist mein jetziger Quellcode.
    Er läuft soweit, nur gibt es noch 2 kleine Fehler:

    1. Er führt die Switch-Case Reihe nicht richtig aus. Setze ich kein Break, läuft er von Case 1 zu Case 2, ohne dass der Benutzer eine Eingabe getätigt hast.

    Standardmäßig solltest du jedes case mit einem break beenden. Hier fehlt es dir in alles cases! Es ist außerdem ungewöhnlich, hinter dem case einen Block mit { anzufangen.
    Also richtig:

    switch (irgendwas) {
      case 1:
         cout << "Fall 1";
         cout << "\n";
         break;
       case 2:
         cout << "Fall 2 -";
         cout << " hier noch ein weiterer Befehl\n";
         break;
       // und so weiter
    }
    

    Allerdings soll der Benutzer bei jedem Case neu entscheiden, ob er zu Case 1 oder Case 5 z.b. springt und die Eingabe muss dementsprechend gespeichert werden.

    ??? Verstehe ich nicht. Genau das erreichst du doch mit break.

    1. Wenn ich Case 1 ausführe, kann ich nicht "Der Pate" eingeben, sondern nur "Pate" oder "Der", da er anscheinend die zwei Wörter für jeweils einen String hält.

    Lies den String mit std::getline(std::cin, name) ein statt mit cin >> name

    Weiterer Fehler:
    du hast eine Funktion Benutzer OnlineVideothek::findUser(string name). Überlege dir mal, was passiert, wenn der Benutzer nicht gefunden wird. Wenn du diese Funktion berichtigst, kannst du sie auch sinnvoll im Code verwenden.



  • @wob habs überall angepasst. Die breaks sind drinne.

    Lies den String mit std::getline(std::cin, name) ein statt mit cin >> name
    

    Habe ich auch implementiert, allerdings nimmt er dann gar keine Eingabe für den Titel entgegen und lässt das Feld leer?

    Wegen der findUser(string name)-Problematik:
    Wenn er den User nicht findet, dann sollte er eine Fehlermeldung ausgeben und das Programm sollte dann nicht mehr laufen.

    Was ich an meinem Programm festgestellt habe:
    Ich kann beliebig viele Videos hinzufügen, das klappt. Auch, dass alle gespeichert werden unter unterschiedliche IDs funktioniert. Aber wenn ich das Video zu den Favoriten hinzufügen möchte, sprich ich erstelle vorher zwei Videos:

    1. Der Pate
    2. Matrix
      kann ich lediglich Der Pate zu den Favoriten hinzufügen.
      Der Film Matrix erscheint zwar, wenn ich alle erstellten Videos ausgebe lasse, allerdings lässt er sich nicht mit der ID zu den Favoriten hinzufügen. Die IDs, die die Filme automatisch zugewiesen bekommen sind feste Werte


  • @Suprax: Stell mal die Warnstufe deines Compiler höher, bzw. beachte die Warnungen (u.a. die find-Funktionen haben keine bzw. nicht genügend return-Anweisungen).
    Und bei der login-Funktion solltest du noch mal den else-Zweig überdenken (aber wie @wob schon schrieb, benutze hier besser die FindUser-Funktion - ebenso in vielen der anderen Funktionen).
    Und die Schleifen in der main-Funktion (bei case 3 und case 6) solltest du auch durch passende Funktionsaufrufe ersetzen.

    @wob sagte in Vektor-Funktion bricht nach einer Eingabe ab:

    Es ist außerdem ungewöhnlich, hinter dem case einen Block mit { anzufangen.

    Aber dies wird benötigt, wenn man lokale Variablen dort definiert (wie im Code von @Suprax)!



  • @Th69 sagte in Vektor-Funktion bricht nach einer Eingabe ab:

    @wob sagte in Vektor-Funktion bricht nach einer Eingabe ab:

    Es ist außerdem ungewöhnlich, hinter dem case einen Block mit { anzufangen.

    Aber dies wird benötigt, wenn man lokale Variablen dort definiert (wie im Code von @Suprax)!

    Dann ist aber der Block für den case tendenziell zu lang und sollte in eine Funktion ausgelagert werden. Und das ist hier der Fall.

    Also besser:

    switch (eingabe) {
        case 1: 
            useraction_add_video(test);
            break;
        case 2: 
            useraction_login_user(test);
            break;
        case 3:
            useraction_list_favorites(test);
            break;
        // ...  
    

    Wobei es irgendwie komisch ist, den Login (case 2) da in dieser Liste zu haben.

    PS: Habe ich schon mal irgendwann erwähnt, dass ich kein Fan von switch-case bin? Oft wird der Code damit unübersichtlich.



  • @Th69 der compiler ist auf More Warnings eingestellt, aber Warnungen bzgl. der find-Funktion tauchen nicht auf.

    Die Funktion weist doch eine return-Funktion auf:
    return this->users.at(i);

    oder müsste am Ende der find-Funktion return 0 erfolgen?

    Bzgl. des logins kann ich ja eine erneute Abfrage des Logins für den else-Zweig implementieren.

    @wob Das auslagern in eine Funktion geht ja flott, da die Funktionen schon stehen. Das mache ich dann noch, sobald ich die kleinen Probleme aus der Welt geschafft habe.
    Dass ich in Case 2 den Login habe, ist vorgegeben aus der Altklausur-Aufgabe. Ich stelle mir aber auch hier die Frage:
    Der Login ist dafür gedacht, eine Abfrage der Daten, bestehend aus Benutzername und Passwort, zu starten. Normalerweise müsste der Benutzer vorher eine Art Registrierung durchlaufen, damit die Login-Funktion einen Sinn macht, oder liege ich da falsch?



  • @Suprax sagte in Vektor-Funktion bricht nach einer Eingabe ab:

    @Th69 der compiler ist auf More Warnings eingestellt, aber Warnungen bzgl. der find-Funktion tauchen nicht auf.
    Die Funktion weist doch eine return-Funktion auf:
    return this->users.at(i);
    oder müsste am Ende der find-Funktion return 0 erfolgen?

    JEDER Weg aus der Funktion muss ein return haben!

    return 0 geht nicht, denn 0 ist ja kein Benutzer, sondern eine Zahl. Du könntest aber z.B. einen Pointer auf den Benutzer returnen und mit nullptr "nicht gefunden" markieren.

    PS: Deine Logik in case 6 ist auch falsch. Überleg mal, wann bei dir true und wann false rauskommt.



  • @wob so ungefähr?

    return this->users nullptr; 
    

    Zu Case 6: Ich iteriere durch mein Benutzer Vektor und mein Video-Vektor, wenn die ID des Videos gleich der ID des Favoritenvideos ist , dann gibt er Truezurück, andernfalls wurde eines vom beiden nicht gefunden, daher false.
    Oder wo sitzt mein Denkfehler?



  • Einen nullptr kannst du nicht zurückgeben, da die Funktion ja ein Benutzer-Objekt zurückgeben soll (keinen Zeiger).
    Du könntest aber am Ende wenigstens eine Exception werfen (wie in addToFavorites, welche du dann auch entsprechend umschreiben kannst, so daß sie diese find-Funktionen aufruft).

    Noch besser wäre es dann jedoch, die Funktion würde statt einer Kopie eine (konstante) Referenz zurückgeben, also

    const Benutzer& OnlineVideothek::findUser(string name)
    // bzw.
    Benutzer& OnlineVideothek::findUser(string name)
    

    Würdest du bisher nämlich Änderungen an dem zurückgegebenen Benutzer-Objekt machen (z.B. durch Aufruf von setCurrent_video), so wären diese Änderungen nicht im vector<Benutzer>-Objekt des OnlineVideothek-Objekts enthalten!

    Edit: In deinem case 6 hast du denselben Logik-Fehler bzgl. dem else wie in der login-Funktion. Überlege mal, was bisher passiert, wenn der 2. Wert der gefundene sein soll?



  • @Th69

    Benutzer& OnlineVideothek::findUser(string name) {
    
        for (unsigned int i = 0; i < this->users.size(); i++) {
    
            if (this->users.at(i).get_User() == name) {
    
                return this->users.at(i);
            } else {
    
                throw runtime_error("User nicht gefunden");
            }
        }
    // Hier müsste dann eine return funktion stehen
    }
    

    Jetzt erscheint auch die Warnung, dass meine Funktion das Ende einer non-void Funktion erreicht.
    Da wo mein Kommentar liegt, müsste ich da dementsprechend eine Exception schreiben?

    Bzgl. case 6: Die Funktion iteriert durch beide Vektoren, wenn erst der 2. Wert der gefundene sein soll, aber der erste Wert nicht der richtige ist, dann gibt er bereits beim 1. Wert ein false zurück und sucht gar nicht erst nach dem zweiten Wert, oder?


Log in to reply