Modernes C++ programmieren

Okt 23, 2024

lst-0977-godb.cpp

//#(compile) c++; compiler:g132; options:-O3 -std=c++23; libs:-
// https://godbolt.org/z/j85P7b3oq 
#include <string>
#include <vector>
#include <iostream>
#include <map>
#include <functional>
std::map<char,std::function<int(int,int)>> binOps { // zweistellige Operatoren
    {'+', std::plus<int>{} },
    {'-', std::minus<int>{} },
    {'*', std::multiplies<int>{} },
    {'/', std::divides<int>{} },
    {'%', std::modulus<int>{} },
    };
std::map<char,std::function<int(int)>> unOps { };    // einstellige Operatoren
auto val = [](auto n) { return [n](){ return n; };}; // gibt ein Lambda zurück
std::map<char,std::function<int()>> zeroOps {        // nullstellige Operatoren
  {'0', val(0)}, {'1', val(1)}, {'2', val(2)}, {'3', val(3)}, {'4', val(4)},
  {'5', val(5)}, {'6', val(6)}, {'7', val(7)}, {'8', val(8)}, {'9', val(9)},
  };
std::map<char,std::function<void(std::vector<int>&)>> stapelOps { 
  { ' ', [](auto &stapel) { } },           // keine Operation
  { 'c', [](auto &stapel) { stapel.clear(); } }, // Stapel ganz löschen
  { ':', [](auto &stapel) {                // obersten zwei Elemente vertauschen
            auto top = stapel.back(); stapel.pop_back();
            auto second = stapel.back(); stapel.pop_back();
            stapel.push_back(top);
            stapel.push_back(second);
  } },
  { '=', [](auto &stapel) {                // ganzen Stapel ausgeben
            for(int elem : stapel) { std::cout << elem; }
            std::cout << "\n";
  } },
};
void rechner(std::string input) {
  std::vector<int> stapel {};
  for(char c : input) {
    int top, second;
    if(auto it = unOps.find(c); it != unOps.end()) {
      // falls einstelliger Operator 
      auto func = it->second;
      top = stapel.back(); stapel.pop_back(); //  hole oberstes Element
      stapel.push_back(func(top));         //  wende func an, Ergebnis auf Stapel
    } else if(auto it = binOps.find(c); it != binOps.end()) {
      // falls zweistelliger Operator 
      auto func = it->second;
      top = stapel.back(); stapel.pop_back(); //  hole die obersten 2 Elemente
      second = stapel.back(); stapel.pop_back();
      stapel.push_back(func(second, top)); //  wende func an, Ergebnis auf Stapel
    } else if(auto it = zeroOps.find(c); it !=zeroOps.end()) {
      // falls nullstelliger Operator 
      auto func = it->second;
      stapel.push_back(func());            //  Ergebnis von func auf Stapel
    } else if(auto it = stapelOps.find(c); it !=stapelOps.end()) {
      // falls Stapeloperator
      auto func = it->second;
      func(stapel);                        //  wende func auf Stapel an
    } else {
      std::cout << "\n'" << c << "' verstehe ich nicht.\n";
    }
  } /* for c */
}
int main(int argc, const char* argv[]) {
    if(argc > 1) {
        rechner(argv[1]);
    } else {
        // 3+4*5+6 mit Punkt- vor Strichrechnung ergibt 29
        rechner("345*+6+=");
    }
    rechner("93-=");                     // 9  3 = Ausgabe: 6
    rechner("82/=");                     // 8 / 2 = Ausgabe: 4
    rechner("92%=");                     // 9 % 2 = Ausgabe: 1
}