@grigorkh

Как создать консольный терминал на C++?

Помогите написать консольный терминал на C++.
Или хотя бы найти нужные материалы.

Пример работы:

#: plus 5 7 ENTER
#: 12
#: minus 10 12 ENTER
#: -2
~~~~~~~~~~~~~
#: help ENTER
#: plus arg1 arg2
minus arg1 arg2
~~~~~~
#:exit ENTER
  • Вопрос задан
  • 7703 просмотра
Решения вопроса 1
@grigorkh Автор вопроса
Наконец то получилось. Вот код.

#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;
}
Ответ написан
Пригласить эксперта
Ответы на вопрос 5
tsarevfs
@tsarevfs Куратор тега C++
C++ developer
tsarevfs
@tsarevfs Куратор тега C++
C++ developer
Ладно, @grigorkh, ты меня рассмешил.
Сначала нужно научиться писать хоть что-то работающее. Вот
так вы можете создать свою первую программу.
Далее возьмите книжку по C++, Эккель подойдет. Читайте, напишите хотя бы 5-10 упражнений на строки, ввод-вывод, циклы, if.
Теперь вы готовы приступить к выполнению вашего задания.
В цикле (а этому моменту вы уже знаете что это такое) вы считываете команды по одной до тех пор пока не введена команда exit.
Пусть каждая команда это строка, первое слово в которой - имя действия, остальные - аргументы. Научитесь разбивать строчку на слова. Дальше разбираете какая команда введена и формируете требуемый ответ. В итоге получится что-то такое:
#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;
}


У такого кода будет много недостатков, например новые команды не очень удобно добавлять. Да и 2 + 2 * 2 ему не понять. Но до этого еще очень далеко.

И научитесь пользоваться гуглом. Там есть ответы на 99.99% вопросов которые у вас возникнут в ближайшее несколько месяцев изучения программирования.
Ответ написан
tsarevfs
@tsarevfs Куратор тега C++
C++ developer
@grigorkh
не используйте reinterpret_cast без крайней необходимости.

предлагаю создать интерфейс и реализовать для каждой команды:
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 и.т.д


Затем запихнуть экземпляры вместо функций в 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";
	}
}


Так ты сможешь реализовать команды не только с 2 int-овыми параметрами. В конструктор help_command можно передать указатель на commands и в зависимости от аргументов выдавать справку по всем командам, или по конкретной указанной.
Не забудь почистить память в конце.
Ответ написан
Комментировать
@grigorkh Автор вопроса
Я тут спомашю Гугла из разных примеров собрал несколько строк, как вы думаете чего тут не достает

#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;
		}
	}
}
Ответ написан
@grigorkh Автор вопроса
Получилось что-то такое. но пока не паботает

#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;
}
Ответ написан
Комментировать
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Войти через центр авторизации
Похожие вопросы