G
G
grigorkh2013-11-22 02:22:10
C++ / C#
grigorkh, 2013-11-22 02:22:10

How to create a console terminal in C++?

Help write a console terminal in C++.
Or at least find the right materials.
Work example:
#: plus 5 7 ENTER
#: 12
#: minus 10 12 ENTER
#: -2
~~~~~~~~~~~~~
#: help ENTER
#: plus arg1 arg2
minus arg1 arg2
~~~ ~~~
#:exit ENTER

Answer the question

In order to leave comments, you need to log in

6 answer(s)
G
grigorkh, 2013-11-23
@grigorkh

Finally it worked out. Here is the code.

#include <iostream>
#include <string>
#include <map>
#include <vector>
using namespace std;

bool shell_finish = false;
map<string, void*> fnMap;

vector<string> explode(string inputstring, string delimiter){
  vector<string> explodes;
  inputstring.append(delimiter);
  while (inputstring.find(delimiter) != string::npos){
    explodes.push_back(inputstring.substr(0, inputstring.find(delimiter)));
    inputstring.erase(inputstring.begin(), inputstring.begin() + inputstring.find(delimiter) + delimiter.size());
  }
  return explodes;
}
string trim(const string& str, const string& whitespace = " \t")
{
  const auto strBegin = str.find_first_not_of(whitespace);
  if (strBegin == string::npos)
    return "";
  const auto strEnd = str.find_last_not_of(whitespace);
  const auto strRange = strEnd - strBegin + 1;

  return str.substr(strBegin, strRange);
}

void my_plus(string params) {
  double sum = 0;
  vector<string> explodes = explode(params, " ");
  for (int i = 0; i<(int)explodes.size(); i++){
    sum += atof(trim(explodes[i]).c_str());
  }
  cout << sum << endl;
}
void my_exit(string params = "") {
  shell_finish = true;
}
void my_help(string params) {
  map<string, string> help;
  help["plus"] = "Use following syntax: plus <number_1> <nubmer_2> ...";
  help["exit"] = "Exits current shell session.";
  if (help.find(params) != help.end()) {
    cout << help[params] << endl;
  }
  else {
    cout << "help: command not found" << endl;
  }
}

void detect_command(string a) {
  fnMap["plus"] = &my_plus;
  fnMap["exit"] = &my_exit;
  fnMap["help"] = &my_help;
  const int arr_length = 10;
  string commands[arr_length] = { "plus", "help", "exit" };
  string cur_cmd;
  for (int i = 0; i < arr_length; i++) {
    cur_cmd = commands[i];
    if (a.compare(0, cur_cmd.length() + 1, cur_cmd + " ") == 0 || a.compare(0, cur_cmd.length(), cur_cmd) == 0) {
      string params = trim(a.substr(cur_cmd.length()));
      reinterpret_cast<void(*)(string)>(fnMap[cur_cmd])(params);
      break;
    }
  }
}

int main(void) {
  string x;
  while (!shell_finish) {
    getline(cin, x);
    detect_command(x);
  }
  return 0;
}

T
tsarevfs, 2013-11-22
@tsarevfs

Everything is very simple !

T
tsarevfs, 2013-11-22
@tsarevfs

Okay, @grigorkh , you made me laugh.
First you need to learn how to write at least something that works. This
is how you can create your first program.
Next, take a book on C ++, Eckel will do. Read, write at least 5-10 exercises on strings, input-output, loops, if.
You are now ready to begin your task.
In a loop (and by now you already know what it is) you read the commands one at a time until the exit command is entered.
Let each command be a string, the first word of which is the name of the action, the rest are the arguments. Learn how to break a line into words. Next, parse which command is entered and form the required answer. As a result, something like this will turn out:

#include <iostream>
#include <string>

main ()
{
  while (true) 
  {
    std::string command;
    std::getline (std::cin, command); 

    if (command = "exit")
      break;

    std::vector<std::string> words = разбить_на_слова(command)

    if (words[0] == "help")
    {
      std::cout << "plus arg1 arg2\nminus arg1 arg2"
    }

    if (words[0] == "plus")
    {
      std::cout << строка_в_число(words[1]) + строка_в_число(words[2]);
    }

    // дальше аналогично(или не очень) разобрать остальные команды
  }

  return 0;
}

Such code will have many drawbacks, for example, it is not very convenient to add new commands. Yes, and 2 + 2 * 2 he does not understand. But this is still very far away.
And learn how to google. It has answers to 99.99% of the questions you'll have in the next few months of learning how to program.

T
tsarevfs, 2013-11-24
@tsarevfs

@grigorkh
don't use reinterpret_cast unless absolutely necessary.
I propose to create an interface and implement for each command:

class command_t
{
public:
  virtual void apply(std::vector< std::string > const &args) = 0;
  virtual std::string get_help() = 0;
};

class add_command_t : command_t
{
public:
  void apply(std::vector< std::string > const &args)
  {
    int ans = atoi(args[1].c_str()) + atoi(args[2].c_str());
    std::cout << ans;
  }

  std::string get_help()
  {
    return "add arg1 arg2\n";
  }
};

//аналогично mul_command и.т.д

Then push instances instead of functions into map.
typedef std::map< std::wstring, command_t * > command_map_t;
typedef command_map_t::iterator command_iter;

//////////////////////////////////////////

command_map_t commands;
commands['add'] = new add_command_t();
//...

while (true)
{
  std::string x;
  std::getline(cin, x);
  std::vector< std::string > words = split(x); //напиши split сам

  command_iter iter = commands.find(words[0]); 
  if (iter != commands.end()) //если такая команда есть
  {
    iter->apply(words);
  }
  else
  {
    std::cout << "Wrong command!\n";
  }
}

So you can implement commands not only with 2 int parameters. You can pass a pointer to commands to the help_command constructor and, depending on the arguments, issue help on all commands, or on a specific one.
Don't forget to clear your memory at the end.

G
grigorkh, 2013-11-22
@grigorkh

I’ll help Google here from various examples, I collected a few lines, what do you think is missing here

#include <iostream>
#include <string>
#include <map>
using namespace std;
void detect_command(string a);
int plus(int a, int b) {
  return a + b;
}
int minus(int a, int b) {
  return a + b;
}

typedef void *(*fp)(void **, int);

struct function_object{
  string name;
  int params;
  fp pointer;

  function_object(const string &n) :name(n), params(0), pointer(0){}
  function_object &operator()(int p){ this->params = p; return *this; }
  function_object &operator=(fp p){ this->pointer = p; return *this; }
  bool operator<(const function_object &b){ return this->name<b.name; }
};
void main(void) {
  string x;
  
  while (true) {
    getline(cin, x);
    detect_command(x);
  }
}
void detect_command(string a) {
  const int arr_length = 10;
  
  set<function_object> functions;
  functions.insert(function_object("add")(2) = f);


  string commands[arr_length] = { "plus", "minus", "help", "exit" };
  for (int i = 0; i < arr_length; i++) {
    if (a.compare(0, commands[i].length(), commands[i]) == 0) {
      cout << reinterpret_cast<int(*)(int)>(fnMap[commands[i]])(5, 4) << endl;
      break;
    }
  }
}

G
grigorkh, 2013-11-23
@grigorkh

It turned out something like that. but not working yet

#include <iostream>
#include <string>
#include <map>
using namespace std;
map<string, void*> fnMap;
void my_plus(int a, int b) {
  cout << a + b;
}
void my_minus(int a, int b) {
  cout << a - b;
}

typedef struct fn_table_entry {
  char *name;
  void(*fn)(int a, int b);
} fn_table_entry_t;

void detect_command(string a) {
  fnMap["plus"] = &my_plus;
  fnMap["minus"] = &my_minus;
  const int arr_length = 10;
  string commands[arr_length] = { "plus", "minus", "help", "exit" };
  for (int i = 0; i < arr_length; i++) {
    if (a.compare(0, commands[i].length(), commands[i]) == 0) {
      cout << reinterpret_cast<int(*)(int, int)>(fnMap[commands[i]])(5, 4);
      break;
    }
  }
  
}

int main(void) {
  string x;
  while (true) {
    getline(cin, x);
    detect_command(x);
  }
  return 0;
}

Didn't find what you were looking for?

Ask your question

Ask a Question

731 491 924 answers to any question