Wie berechne ich das? // Neuling was programmieren angeht.



  • Hallo liebe C++-Community,

    ich habe angefangen mich mit C++ zu beschäftigen und habe glaube ich einen Denkfehler und finde anscheinend nicht die richtigen Worte um das zu ergooglen. Falls es doch einfach zu finden gewesen wäre, tut es mir leid.

    Mein erstes Projekt ist eine kleine Speisekarte eines Restaurants. Ich möchte das der Kunde im Bereich Vorspeise/Hauptspeise/Nachspeise eines von drei Gerichten auswählen kann. Soweit komme ich auch. Allerdings möchte ich auch, dass diese drei Gerichte zusammen addiert werden am Ende. (Wie man das Gericht auswählt, habe ich nicht in den Code hier rein geschrieben um ein wenig Platz zu sparen - da habe ich keine Probleme).

    Meine Frage dazu: Wie berechne ich das?

    Das hier ist mein bisheriger (verkürzter) Code:

    void Start() {	
    
    	cout << "Herzlich Willkommen bei Sparrows Speisen.\n\n";
    
    	cout << "***Vorspeisen***\n" << endl;
    	cout << "Nr.  Gericht 	Preis\n" << endl; 
    	cout << "1.   Tomatensuppe  3.00 Euro" << endl; 
    	cout << "2.   Weinbergschnecken  4.50 Euro" << endl; 
    	cout << "3.   Bruschetta	3.50 Euro\n" << endl; 
    
    	cout << "***Hauptspeisen***\n" << endl;
    	cout << "Nr.  Gericht  Preis\n" << endl; 
    	cout << "4.   Hackbraten mit Kartoffeln   6,00 Euro" << endl; 
    	cout << "5.   Hamburger mit Pommes 	 6,50 Euro" << endl; 
    	cout << "6.   Lasagne ala Jaqlyn          5,00 Euro\n" << endl; 
    
    	cout << "***Nachspeisen***\n" << endl;
    	cout << "Nr.  Gericht 	Preis\n" << endl; 
    	cout << "7.   Tiramisu			4,00 Euro" << endl; 
    	cout << "8.   Spaghettieis 		3,50 Euro" << endl; 
    	cout << "9.   Mousse au Chocolate 	4,00 Euro\n" << endl; 
    
    	cout << "0. Beenden\n" << endl; 
    }
    
    int main ()
    
    {	
    	Start(); //Startet die Hauptauswahl
    
    	cin.sync();
    	cin.get();
    	return 0; 
    
    }
    

  • Mod

    Das ist derzeit sehr ungünstig, dass bei dir alle für die Programmlogik relevanten Daten fest in den Zeichenkettenliteralen der Textausgabe stehen. Dein Problem ist doch sicherlich, dass der Nutzer so etwas wie '5' eingibt, aber woher weiß dein Programm dann, dass das Hamburger mit Pommes für 6,50 Euro sein soll? Derzeit gar nicht.

    Mach es umgekehrt: In deinem Programm braucht es eine Liste der Gerichte und der zugehörigen Preise. Aus dieser Liste erzeugst du deine Textausgabe. Dann ist es ganz einfach aus der Nutzereingabe '5' auf Hamburger mit Pommes für 6,50 Euro zu schließen, denn das ist dann einfach der 5. Eintrag in deiner Liste (oder 4., wenn du bei 0 anfängst zu zählen).



  • Bleistift:

    #include <algorithm>
    #include <limits>
    #include <cstdlib>
    #include <tuple>
    #include <array>
    #include <vector>
    #include <string>
    #include <iostream>
    #include <iomanip>
    
    class Dish
    {
    public:
    	enum class dish_type { starter, main_course, dessert, none };
    
    	static char const * const dish_type_names[];
    	static int const name_field_width;
    
    	Dish(dish_type type, std::string const & name, int price)
    	: type{ type }, name{ name }, price{ price } {};
    
    	std::string get_dish_type_name() const { return dish_type_names[static_cast<std::size_t>(type)]; }
    	int get_price() const { return price; }
    	dish_type get_dish_type() const { return type; }
    
    	friend bool operator<(const Dish & lhs, const Dish & rhs)
    	{
    		return std::tie(lhs.type, lhs.name) < std::tie(rhs.type, rhs.name);
    	}
    
    	friend std::ostream & operator<<(std::ostream & os, Dish const &dish)
    	{
    		return os << std::setw(Dish::name_field_width) << std::left << dish.name
    			<< std::setw(5) << std::right << std::setprecision(2) << std::fixed << dish.price / 100.;
    	}
    
    private:
    	dish_type type;
    	std::string name;
    	int price;
    };
    
    char const * const Dish::dish_type_names[] = { "Vorspeisen", "Hauptspeisen", "Nachspeisen" };
    int const Dish::name_field_width{ 30 };
    
    template<typename Iter>
    void print_menu(std::ostream &os, Iter begin, Iter end)
    {
    	Dish::dish_type old_dish_type{ Dish::dish_type::none };
    
    	for (Iter i{ begin }; i != end; ++i) {
    		Dish::dish_type type{ i->get_dish_type() };
    		if (type != old_dish_type) {
    			old_dish_type = type;
    			os << "\n*** " << i->get_dish_type_name() << " ***\nNr. "
    			   << std::setw(Dish::name_field_width) << std::left << "Gericht" << "Preis\n";
    		}
    		os << std::right << std::setw(2) << std::distance(begin, i) + 1 << ": " << *i << '\n';
    	}
    }
    
    void print_bill(std::vector<Dish> const & dishes)
    {
    	int total{};
    	for (auto & i : dishes) {
    		std::cout << i << '\n';
    		total += i.get_price();
    	}
    	std::cout << std::setw(Dish::name_field_width) << std::right << "Gesamt: "
    		<< std::setw(5) << std::setprecision(2) << std::fixed << total / 100. << "\n\n";
    }
    
    int main()
    {
    	std::array< Dish, 9 > menu{
    		Dish{ Dish::dish_type::starter, "Tomatensuppe", 300 },
    		Dish{ Dish::dish_type::starter, "Weinbergschnecken", 450 },
    		Dish{ Dish::dish_type::starter, "Bruschetta", 350 },
    		Dish{ Dish::dish_type::main_course, "Hackbraten mit Kartoffeln", 600 },
    		Dish{ Dish::dish_type::main_course, "Hamburger mit Pommes", 650 },
    		Dish{ Dish::dish_type::main_course, "Lasagne ala Jaqlyn", 500 },
    		Dish{ Dish::dish_type::dessert, "Tiramisu", 400 },
    		Dish{ Dish::dish_type::dessert, "Spaghettieis", 350 },
    		Dish{ Dish::dish_type::dessert, "Mousse au Chocolate", 400 }
    	};
    
    	std::sort(std::begin(menu), std::end(menu));
    
    	std::cout << "Herzlich Willkommen bei Sparrows Speisen.\n";
    	print_menu( std::cout, std::begin(menu), std::end(menu));
    	std::cout << "\n 0. Beenden\n\n";
    
    	std::size_t choice;
    	std::vector< Dish > selection;
    	do {
    		std::cout << "Auswahl: ";
    		if (!(std::cin >> choice)) {
    			std::cin.clear();
    			std::cerr << "Eingabefehler!\n\n";
    			choice = 42;
    		}
    		else if (choice > menu.size()) {
    			std::cerr << "Ungueltige Auswahl!\n\n";
    		}
    		else if (choice) selection.push_back(menu[choice - 1]);
    
    		if(!std::cin.eof())
    			std::cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
    	} while (choice);
    
    	std::cout << "\nRechnung:\n";
    	print_bill(selection);
    }
    

    //edit: C++14



  • Ich finds etwas ungewöhnlich, dass print_menu zusätzlich zum Ausgeben noch das Menü sortiert. Print sollte print bleiben - ich würde das Sortieren vorher separat durchführen.

    Und eine Stilfrage:

    int total{};
    

    Schreibst du das immer so? Ich persönlich finde

    int total = 0;
    // oder
    auto total = 0;
    

    beide viel lesbarer. Ja, geschwungene Klammern sind schön bei sowas wie int i = 4.5; , weil sie das nicht zulassen und den Wertebereich überprüfen. Allerdings finde ich eine explizite "0" klarer als {}.



  • SeppJ schrieb:

    Das ist derzeit sehr ungünstig, dass bei dir alle für die Programmlogik relevanten Daten fest in den Zeichenkettenliteralen der Textausgabe stehen. Dein Problem ist doch sicherlich, dass der Nutzer so etwas wie '5' eingibt, aber woher weiß dein Programm dann, dass das Hamburger mit Pommes für 6,50 Euro sein soll? Derzeit gar nicht.

    Mach es umgekehrt: In deinem Programm braucht es eine Liste der Gerichte und der zugehörigen Preise. Aus dieser Liste erzeugst du deine Textausgabe. Dann ist es ganz einfach aus der Nutzereingabe '5' auf Hamburger mit Pommes für 6,50 Euro zu schließen, denn das ist dann einfach der 5. Eintrag in deiner Liste (oder 4., wenn du bei 0 anfängst zu zählen).

    Ich verstehe, was du meinst und ich werde versuchen es umzusetzen. Allerdings bin ich noch an dem Punkt, wo ich nicht genau weiß, was ich wo einsetzen muss/soll/kann. Ich denke das wird sich ergeben. Ich versuche es heute erneut umzusetzen.

    Swordfish schrieb:

    Bleistift:

    [cpp]#include <limits>
    #include <cstdlib>
    #include <tuple>
    #include <array>
    #include <vector>
    #include <string>
    #include <iostream>
    #include <iomanip>

    class Dish
    {
    public:
    enum class dish_type { starter, main_course, dessert, none };

    static char const * const dish_type_names[];
    static int const name_field_width;

    Es ist sehr lieb, dass du mir das alles abgetippt hast. Ich bin der visuelle Typ und wollte mir das in meinem Compiler umwandeln um zu sehen, was das Programm macht um die Dinge zu verstehen, die du geschrieben hast. Allerdings kommt dann ein Copyright fehler. 😞


  • Mod

    Compiler sind nicht an juristischen Urheberfragen interessiert. Sag mal genau, mit vollständiger Fehlermeldung, was passiert ist.

    Swordfishs Code ist reguläres C++17, bis auf den Fehler, dass ein #include <algorithm> (für std::sort ) fehlt. Ein Compiler, der nicht C++17 spricht, wird sich an dem Semikolons in Zeile 53 verschlucken, was behebbar ist, in dem man die Definition vor das if zieht.

    In keinem Fall spielt Copyright eine Rolle, daher 😕



  • wob schrieb:

    Ich finds etwas ungewöhnlich, dass print_menu zusätzlich zum Ausgeben noch das Menü sortiert. Print sollte print bleiben - ich würde das Sortieren vorher separat durchführen.

    Geändert.

    wob schrieb:

    Und eine Stilfrage:

    int total{};
    

    Schreibst du das immer so?

    Ja.

    SeppJ schrieb:

    Swordfishs Code ist reguläres C++17, bis auf den Fehler, dass ein #include <algorithm> (für std::sort ) fehlt.

    Ergänzt.



  • SeppJ schrieb:

    Compiler sind nicht an juristischen Urheberfragen interessiert. Sag mal genau, mit vollständiger Fehlermeldung, was passiert ist.

    Swordfishs Code ist reguläres C++17, bis auf den Fehler, dass ein #include <algorithm> (für std::sort ) fehlt. Ein Compiler, der nicht C++17 spricht, wird sich an dem Semikolons in Zeile 53 verschlucken, was behebbar ist, in dem man die Definition vor das if zieht.

    In keinem Fall spielt Copyright eine Rolle, daher 😕

    Das hier ploppt dann auf:

    // Copyright (C) 2007-2014 Free Software Foundation, Inc.
    //
    // This file is part of the GNU ISO C++ Library.  This library is free
    // software; you can redistribute it and/or modify it under the
    // terms of the GNU General Public License as published by the
    // Free Software Foundation; either version 3, or (at your option)
    // any later version.
    
    // This library is distributed in the hope that it will be useful,
    // but WITHOUT ANY WARRANTY; without even the implied warranty of
    // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    // GNU General Public License for more details.
    
    // Under Section 7 of GPL version 3, you are granted additional
    // permissions described in the GCC Runtime Library Exception, version
    // 3.1, as published by the Free Software Foundation.
    
    // You should have received a copy of the GNU General Public License and
    // a copy of the GCC Runtime Library Exception along with this program;
    // see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
    // <http://www.gnu.org/licenses/>.
    
    /** @file bits/c++0x_warning.h
     *  This is an internal header file, included by other library headers.
     *  Do not attempt to use it directly. @headername{iosfwd}
     */
    
    #ifndef _CXX0X_WARNING_H
    #define _CXX0X_WARNING_H 1
    
    #if __cplusplus < 201103L
    #error This file requires compiler and library support for the \
    ISO C++ 2011 standard. This support is currently experimental, and must be \
    enabled with the -std=c++11 or -std=gnu++11 compiler options.
    #endif
    
    #endif
    

  • Mod

    Da hast du aber eine tolle IDE, die dir den Ort des Fehlers zeigt, anstatt des Fehlers. Was du da siehst hat auch nichts mit Copyright zu tun, das ist schlicht der Quellcode deiner Standardbibliothek (der dem Copyright unterliegt) und der wird dir vermutlich gezeigt, weil in Zeile 32 ein Fehler erzeugt wird und deine IDE zu diesem Ort springt anstatt dir nur die Meldung

    This file requires compiler and library support for the
    ISO C++ 2011 standard. This support is currently experimental, and must be
    enabled with the -std=c++11 or -std=gnu++11 compiler options.

    zu zeigen.

    Die Fehlermeldung selbst ist wohl selbsterklärend und wird von dem #include<tuple> ausgelöst, welches es erst seit 2011 gibt, wohingegen du mit dem Stand von 1998 unterwegs bist. Dein Compiler ist aber offensichtlich von 2014 (auch nicht mehr so ganz frisch...) und käme wohl durchaus mit den Neuerungen von 2011 zurecht, aber es ist nicht seine Standardeinstellung, sondern du musst den Anweisungen in obiger Fehlermeldung folgen.

    Wie ich weiter oben schon gesagt habe, setzt der Code aber auch ein Feature aus dem Jahr 2017 voraus und voraussichtlich wird das deinen 2014er Compiler sowieso überfordern. Ich habe aber schon beschrieben, wie man es recht einfach so anpassen könnte, dass es auch mit älteren Sprachstandards funktioniert.


Log in to reply