Форум программистов, компьютерный форум CyberForum.ru

Дать юзеру возможность вводить команды с параметрами - C++

Восстановить пароль Регистрация
 
Vladimir.
155 / 155 / 10
Регистрация: 24.11.2009
Сообщений: 375
07.07.2014, 00:00     Дать юзеру возможность вводить команды с параметрами #1
К утилите прикручена интерактивная оболочка, юзер вводит команду в ответ на которую выполняется некоторый код.
Сейчас выглядит так:
C++
1
2
3
4
typedef struct {
    std::string cmd;
    void (*function)(void);
}consoleCommand;
C++
1
2
3
4
5
6
7
8
9
static consoleCommand   commands[] = {
    { "foo", do_foo },
    { "bar", do_bar }
}
for (auto it = std::begin(commands) ; it != std::end(commands); ++it ) {
    if ( !cmd.compare( (*it).cmd)) {
        it->function();
    } 
}
где foo и bar некоторые функции вида void foo().
==========
Что хочется: дать юзеру возможность вводить команды с параметрами ( вида foo или foo param ), соответственно в коде будут реализованы do_foo() и do_foo(param). Не понятно как определить соответствие по сигнатурам. Вопрос: чего я не знаю и куда посмотреть, как такие штуки делаются?
Лучшие ответы (1)
Similar
Эксперт
41792 / 34177 / 6122
Регистрация: 12.04.2006
Сообщений: 57,940
07.07.2014, 00:00     Дать юзеру возможность вводить команды с параметрами
Посмотрите здесь:

C++ Дать совет по ООП
C++ Список студентов: возможность вводить оценки, изменять, удалять
C++ Дать некоторые определения!
просьба дать пояслнения по коду С++ C++
В массиве записаны результаты N игр футбольной команды. Определить количество выигрышей, количество проигрышей и количество ничьих данной команды. C++
После регистрации реклама в сообщениях будет скрыта и будут доступны все возможности форума.
DrOffset
6457 / 3831 / 885
Регистрация: 30.01.2014
Сообщений: 6,627
07.07.2014, 01:54     Дать юзеру возможность вводить команды с параметрами #2
Цитата Сообщение от Vladimir. Посмотреть сообщение
дать юзеру возможность вводить команды с параметрами ( вида foo или foo param )
А param, я так понимаю, хочется любого типа?

Добавлено через 2 минуты
Для начала можно посмотреть в сторону std::function и std::bind вместо обычного указателя на функцию.
gazlan
2863 / 1811 / 272
Регистрация: 27.08.2010
Сообщений: 4,910
Записей в блоге: 1
07.07.2014, 06:11     Дать юзеру возможность вводить команды с параметрами #3
Цитата Сообщение от Vladimir. Посмотреть сообщение
куда посмотреть, как такие штуки делаются
В сторону любого интерпретатора.
Vladimir.
155 / 155 / 10
Регистрация: 24.11.2009
Сообщений: 375
14.07.2014, 09:26  [ТС]     Дать юзеру возможность вводить команды с параметрами #4
вариант с интерпретатором не годится - swich-case полотнище.

пока не придумал ничего умнее, чем изменить сигнатуру ВСЕХ функций на прием вектора (как вариант, строки) аргументов. Но как-то это все выглядит через одно место.

DrOffset, не очень понял, что именно вы имели ввиду, поясните пожалуйста.
ForEveR
Модератор
Эксперт C++
 Аватар для ForEveR
7927 / 4709 / 318
Регистрация: 24.06.2010
Сообщений: 10,524
Завершенные тесты: 3
14.07.2014, 12:55     Дать юзеру возможность вводить команды с параметрами #5
Vladimir., Так и делают вообщем-то. В основном именно через лист switch-case. Других вариантов по сути нет, извращаться можно по-разному, но в конечном итоге все сведется в switch-case или нечто подобному. Парсинг аргументов из строки и выбор функций для вызова каким-то вариантом - единственный вариант.
Tulosba
:)
Эксперт С++
4378 / 3221 / 297
Регистрация: 19.02.2013
Сообщений: 9,044
14.07.2014, 14:15     Дать юзеру возможность вводить команды с параметрами #6
Цитата Сообщение от Vladimir. Посмотреть сообщение
Не понятно как определить соответствие по сигнатурам.
В самом первом приближении - изменить общую сигнатуру на void (*)(void*). Т.е. чтобы был аргумент типа void*. Который можно будет кастовать к необходимому типу.
DrOffset
6457 / 3831 / 885
Регистрация: 30.01.2014
Сообщений: 6,627
14.07.2014, 21:19     Дать юзеру возможность вводить команды с параметрами #7
Сообщение было отмечено автором темы, экспертом или модератором как ответ
Цитата Сообщение от Vladimir. Посмотреть сообщение
DrOffset, не очень понял, что именно вы имели ввиду, поясните пожалуйста.
Ну примерно что-то такое - на таблицах. Только, естественно, эту нужно будет причесать под задачу. Ну и генерировать таблицы можно и в compile-time, чтобы избежать дублирования и ручного заполнения (но это несколько сложнее).
Можно обойтись и без std::function, слегка повысив производительность, но это этого, ИМХО, код больше потеряет, чем приобретет.
Кликните здесь для просмотра всего текста
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
#include <functional>
#include <string>
#include <cstdio>
 
namespace
{
    void do_foo(std::string const & arg)
    {
        printf("do_foo with one arg=\"%s\".\n", arg.c_str());
    }
    void do_foo()
    {
        printf("do_foo with no arg.\n");
    }
    void do_bar(std::string const & arg0, std::string const & arg1)
    {
        printf("do_foo with two args, arg0=\"%s\", arg1=\"%s\"\n", arg0.c_str(), arg1.c_str());
    }
}
 
static const size_t MaxArgs = 5;
 
void call_do_foo(std::string const (&argsStack)[MaxArgs], size_t const & argsCount)
{
    auto unableCall = [&argsCount] { printf("No function with %d args.", argsCount); };
 
    static const std::function<void()> call_table[MaxArgs] =
    {
        std::bind((void(*)())&do_foo)
      , std::bind((void(*)(std::string const &))&do_foo, argsStack[0])
      , std::bind(unableCall)
      , std::bind(unableCall)
      , std::bind(unableCall)
    };
    if(argsCount < MaxArgs)
    {
        call_table[argsCount]();
    }
    else
    {
        unableCall();
    }
}
void call_do_bar(std::string const (&argsStack)[MaxArgs], size_t const & argsCount)
{
    auto unableCall = [&argsCount] { printf("No function with %d args.", argsCount); };
 
    static const std::function<void()> call_table[MaxArgs] =
    {
        unableCall
      , unableCall
      , std::bind((void(*)(std::string const &,std::string const &))&do_bar, argsStack[0], argsStack[1])
      , unableCall
      , unableCall
    };
    if(argsCount < MaxArgs)
    {
        call_table[argsCount]();
    }
    else
    {
        unableCall();
    }
}
 
int main()
{
    typedef struct {
        char const * cmd;
        std::function<void()> function;
    }
    consoleCommand;
 
    std::string argsStack[MaxArgs];
    size_t      argsCount;
    std::string cmd;
 
    static consoleCommand commands[] = {
        { "foo", std::bind(&call_do_foo, std::cref(argsStack), std::cref(argsCount)) },
        { "bar", std::bind(&call_do_bar, std::cref(argsStack), std::cref(argsCount)) }
    };
 
// First test
    cmd = "bar";
    argsStack[0] = "first";
    argsStack[1] = "second";
    argsCount = 2;
 
    for (auto it = std::begin(commands) ; it != std::end(commands); ++it ) {
        if ( !cmd.compare( (*it).cmd)) {
            it->function();
        }
    }
// Second test
    cmd = "foo";
    argsStack[0] = "first";
    argsCount = 1;
 
    for (auto it = std::begin(commands) ; it != std::end(commands); ++it ) {
        if ( !cmd.compare( (*it).cmd)) {
            it->function();
        }
    }
// Third test
    cmd = "foo";
    argsCount = 0;
 
    for (auto it = std::begin(commands) ; it != std::end(commands); ++it ) {
        if ( !cmd.compare( (*it).cmd)) {
            it->function();
        }
    }
// Last test
    cmd = "foo";
    argsCount = 3;
 
    for (auto it = std::begin(commands) ; it != std::end(commands); ++it ) {
        if ( !cmd.compare( (*it).cmd)) {
            it->function();
        }
    }
    return 0;
}
Tulosba
14.07.2014, 21:40
  #8

Не по теме:

DrOffset, глядя на строки 74-76 подумал, что тебя укусил Mr.X, но в 85-87 ты, к счастью, исправился

DrOffset
14.07.2014, 21:41
  #9

Не по теме:

Цитата Сообщение от Tulosba Посмотреть сообщение
глядя на строки 74-76 подумал, что тебя укусил Mr.X
Поясни.

Tulosba
14.07.2014, 21:43
  #10

Не по теме:

DrOffset, например.

MoreAnswers
Эксперт
37091 / 29110 / 5898
Регистрация: 17.06.2006
Сообщений: 43,301
14.07.2014, 21:48     Дать юзеру возможность вводить команды с параметрами
Еще ссылки по теме:

C++ Дать коментарии коду
C++ Дать значение битовому полю
Не дать клиету класса вводить числа и знаки C++

Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
DrOffset
14.07.2014, 21:48     Дать юзеру возможность вводить команды с параметрами
  #11

Не по теме:

Tulosba, из-за отступа перед argsCount?
Если да, то действительно, я делаю переменные объединенные по смыслу в одном уровне.
Однако я считаю несколько неуместно уравнивать эту, на мой взгляд, невинную привычку, с тотальным подходом, который ты показал по ссылке.

Yandex
Объявления
14.07.2014, 21:48     Дать юзеру возможность вводить команды с параметрами
Ответ Создать тему
Опции темы

Текущее время: 23:53. Часовой пояс GMT +3.
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin® Version 3.8.9
Copyright ©2000 - 2016, vBulletin Solutions, Inc.
Рейтинг@Mail.ru