Shell/Konsole schreiben
-
Ja, so was habe ich hier Mal gebastelt, habe aber das Parsen weggelassen, weil ich da gerade noch keine super-schöne Lösung gefunden habe:
#include <iostream> #include <string> #include <vector> #include <map> class Command { private: void* funcPtr_; unsigned int arguments_; public: Command(void* funcPtr, unsigned int arguments) : funcPtr_(funcPtr), arguments_(arguments) {} void operator()(const std::string& argumentString) { std::vector<double> argumentList; // Nach eigenem Bedarf argumentString nach Argumenten parsen std::assert(argumentList.size() == arguments_); switch(argumentList.size()) { case 0: (*reinterpret_cast<void(*)()>(funcPtr_))(); break; case 1: (*reinterpret_cast<void(*)(double)>(funcPtr_))(argumentList[0]); break; case 2: (*reinterpret_cast<void(*)(double, double)>(funcPtr_))(argumentList[0], argumentList[1]); break; } } }; void sleep(double seconds) {/* ... */} void punch(double lowPunchs, double highPunchs) {/* ... */} int main() { std::map<std::string, Command> CommandMap; CommandMap.insert(std::pair<std::string, Command>("sleep", Command(&sleep, 1))); CommandMap.insert(std::pair<std::string, Command>("punch", Command(&punch, 2))); std::string blub; while(std::getline(std::cin, blub)) { std::string command; std::string argumentPart; // Von blub den Teil vor der Klammer und zwischen den Klammern parsen CommandMap[command](argumentPart); } int u; std::cin >> u; }
-
Für den Anfang und mit 50 Befeheln reicht doch auch etwas ganz leichtes, sowas zb:
#include <iostream> #include <map> #include <cstdlib> //für exit void help() { std::cout << "Auflistung aller Befehle:\n"; //... } void exit() { exit(0); } int main(int argc, char **argv) { std::map<std::string, void (*)()> befehl_normal; befehl_normal["help"] = &help; befehl_normal["exit"] = &exit; std::string eingabe; for(;;) { std::cout << argv[0] << " >> "; std::getline(std::cin, eingabe); if(befehl_normal.find(eingabe) != befehl_normal.end()) //ist der befehl vorhanden? { befehl_normal[eingabe](); //wenn ja, fuer aus } else { std::cerr << "Der Befehl \"" << eingabe << "\" ist entweder falsch geschrieben\n" "oder ist nicht vorhanden.\n"; } } }Und das könnte man für den Anfang noch weiter ausbauen. Für 50 Befehle reicht das, und wenn das Prog nur die Konsole sein soll braucht es auch nicht mehr, finde ich.
-
Er wollte aber Parameter haben.
-
Gibt es da eigentlich auch eine Möglichkeit mit Templates? Mir fällt da nichts ein.
-
Wie, mit Templates? Ein Klassentemplate kann man nicht als Typ einer Map/eines Vectors nehmen oder was willst Du templatisieren? Oder mit diesen neuen variablen Argumenten?
-
Eisflamme schrieb:
Ein Klassentemplate kann man nicht als Typ einer Map/eines Vectors nehmen
Wie meinst du das? Das versteh ich nicht. Meinst du sowas
std::vector<TemplateKlasse<Typ>> array? Und wiese geht das eigentlich nicht ohne Typ, sodass man dann sowas hat:
std::vector<TemplateKlasse> array; array.push_back(TemplateKlasse<int>); //hier ein objekt mit typ int hinzufügen array.push_back(TemplateKlasse<char>); //hier mit charKann man das irgendwie erreichen?
-
Vorsicht, Du meinst mit Templateklasse gerade Klassentemplate.

Das geht nicht, weil das unterschiedliche Typen sind. Du kannst eine abstrakte Klasse in einen Container stecken, aber das Klassentemplate ist ja kein Typ, bevor es nicht typisiert ist.
Man kann das erreichen, indem man noch Vererbung dazu bastelt...
class HiIAmRandy { public: virtual callMethode(std::string&) = 0; }; template<class T> class IKilledYouInThePastSeveralTimes : public HiIAmRandy { public: virtual callMethode(std::string&) {/* Parsen und methode aufrufen */} void methode(T bla) {} }; std::vector<HiIAmRandy*> einVectorEinVectorHurra;Na ja, aber das nützt nichts. Wenn ich nämlich von diesem Objekt was in den vector schreibe, geht der Funktionspointer logischerweise auch nicht auf ein Funktionstemplate, sondern nur auf eine Templatefunktion und damit bringt mir die Flexibilität durch das Template wieder nichts, weil ich für jeden Typ was in die map schieben muss... Vielleicht ist das einer der seltenen Fälle, wo boost::any Sinn machen würde. Aber double deckt eh fast alles ab, also wird das wohl reichen.
-
Ich habe mittlerweile begonnen die konsole zu schreiben.
Die Eingabe durch den Benutzer erfolgt nun durch folgendes Muster:befehlsname par1 par2 par3Das Parsen der Eingabe hab ich folgendermaßen realisiert:
int main( int argc, char * argv[] ) { while(1) { parse( argc, argv ); } } void parse(int argc, const char * const * argv) { vector<string> args; for (int i = 0; i < argc; i++) args.push_back(argv[i]); }Die strings werden anschließen in die entsprechenden Variablentypen umgewandelt.
Nun wäre es noch schön, in der Konsole zusätzlich eine "history" (mit pfeiltaste oben) und eine "autovervollständigung" (tabulator) einzurichten.
Hat jemand eine Idee wie man das machen könnte?
Gibt es dazu für Linux Bibliotheken die einem sowas erleichtern?
Danke für alle die sich Zeit nehmen dies durchzulesen.
-
hallo 123 schrieb:
Nun wäre es noch schön, in der Konsole zusätzlich eine "history" (mit pfeiltaste oben) und eine "autovervollständigung" (tabulator) einzurichten.
Hat jemand eine Idee wie man das machen könnte?Nicht mit Standard-C++ Bordmitteln. Das kennt nämlich keine Pfeiltaste und Tabulatortaste - und in der Konsole den Befehl zu verfollständigen klappt auch nur mit OS-Spezifischen Konsole-Funktionen.
Daher stell deine Frage am besten im jeweiligen OS-Unterforum in einem neuen Thread
-
hallo 123 schrieb:
void parse(int argc, const char * const * argv) { vector<string> args; for (int i = 0; i < argc; i++) args.push_back(argv[i]); }WArum nicht einfach per
vector<string> args(argv,argv+argc);Nun wäre es noch schön, in der Konsole zusätzlich eine "history" (mit pfeiltaste oben) und eine "autovervollständigung" (tabulator) einzurichten.
Hat jemand eine Idee wie man das machen könnte?
Gibt es dazu für Linux Bibliotheken die einem sowas erleichtern?
Danke für alle die sich Zeit nehmen dies durchzulesen.Da mußt du die Tasten in deinem Programm abfangen (das geht nicht mit C++ Bordmitteln, aber mit Funktionen deines Systems) und darauf reagieren.
-
Daher stell deine Frage am besten im jeweiligen OS-Unterforum in einem neuen Thread

Danke, das werd ich gleich machen!