Форум программистов, компьютерный форум, киберфорум
Наши страницы

С++ для начинающих

Войти
Регистрация
Восстановить пароль
 
Vladimir.
158 / 158 / 10
Регистрация: 24.11.2009
Сообщений: 375
#1

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

07.07.2014, 00:00. Просмотров 444. Ответов 10
Метки нет (Все метки)

К утилите прикручена интерактивная оболочка, юзер вводит команду в ответ на которую выполняется некоторый код.
Сейчас выглядит так:
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). Не понятно как определить соответствие по сигнатурам. Вопрос: чего я не знаю и куда посмотреть, как такие штуки делаются?
0
Лучшие ответы (1)
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
Similar
Эксперт
41792 / 34177 / 6122
Регистрация: 12.04.2006
Сообщений: 57,940
07.07.2014, 00:00
Я подобрал для вас темы с готовыми решениями и ответами на вопрос Дать юзеру возможность вводить команды с параметрами (C++):

Не дать клиету класса вводить числа и знаки - C++
В общем, суть такова, как можно запретить клиенту класса вводить числа и знаки? Должно быть имя преподавателя, ясное дело тут циферки и...

Список студентов: возможность вводить оценки, изменять, удалять - C++
нужно сохдать программу списка студентов и их оценок (баллы от 0-100, чтобы пройти экзамен нужно набрать минимум 65 баллов, не набравшие 65...

MaskedTextBox (дать возможность пользователю вводить е-mail) - C#
Помогите, пожалуйста, разобраться с MaskedTextBox! Надо дать возможность пользователю вводить е-mail. Какую маску я должна написать в...

Нельзя ли юзеру запретить т.е дать работать только в одном окне? - C# ASP.NET
Нельзя ли юзеру запретить т.е дать работать только в одном окне. Пр: пользователь ввел свой пароль и вошел на сервер, и в другом окне...

Дать возможность пользователю создать и заполнить массив - C (СИ)
Всем привет! Пытаюсь реализовать метод конечных разностей, и, после недели в гугле, программа работает. Единственно что хотелось улучшить...

Дать пользователю возможность выбора размерности массива - C (СИ)
Добрый вечер. Помогите пожалуйста, даны размеры 2-х массивов 5х10 и 6х8, как сделать, что бы у пользователя в самом начале программы был...

10
DrOffset
7517 / 4513 / 1024
Регистрация: 30.01.2014
Сообщений: 7,362
07.07.2014, 01:54 #2
Цитата Сообщение от Vladimir. Посмотреть сообщение
дать юзеру возможность вводить команды с параметрами ( вида foo или foo param )
А param, я так понимаю, хочется любого типа?

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

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

DrOffset, не очень понял, что именно вы имели ввиду, поясните пожалуйста.
0
ForEveR
В астрале
Эксперт С++
7992 / 4751 / 321
Регистрация: 24.06.2010
Сообщений: 10,547
Завершенные тесты: 3
14.07.2014, 12:55 #5
Vladimir., Так и делают вообщем-то. В основном именно через лист switch-case. Других вариантов по сути нет, извращаться можно по-разному, но в конечном итоге все сведется в switch-case или нечто подобному. Парсинг аргументов из строки и выбор функций для вызова каким-то вариантом - единственный вариант.
0
Tulosba
:)
Эксперт С++
4705 / 3240 / 297
Регистрация: 19.02.2013
Сообщений: 9,046
14.07.2014, 14:15 #6
Цитата Сообщение от Vladimir. Посмотреть сообщение
Не понятно как определить соответствие по сигнатурам.
В самом первом приближении - изменить общую сигнатуру на void (*)(void*). Т.е. чтобы был аргумент типа void*. Который можно будет кастовать к необходимому типу.
0
DrOffset
7517 / 4513 / 1024
Регистрация: 30.01.2014
Сообщений: 7,362
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;
}
1
Tulosba
14.07.2014, 21:40
  #8

Не по теме:

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

0
DrOffset
14.07.2014, 21:41
  #9

Не по теме:

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

0
Tulosba
14.07.2014, 21:43
  #10

Не по теме:

DrOffset, например.

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

Не по теме:

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

0
MoreAnswers
Эксперт
37091 / 29110 / 5898
Регистрация: 17.06.2006
Сообщений: 43,301
14.07.2014, 21:48
Привет! Вот еще темы с ответами:

Как дать возможность узнать о своей программе? - Delphi
Представим себе что написали на наш взгляд довольно таки полезную программу а как сделать так чтобы о ней узнали?

Дать пользователю возможность указать путь к файлу - C (СИ)
Помогите зделать так чтобы Доступ к файлу, был возможен и задавался в диалоге с пользователем. вот у меня есть функция которая обращается...

Дать пользователю возможность самому выбирать путь к файлу - PHP
&lt;? $file = fopen(&quot;c:/www/html/pavlovo.jpg&quot;,&quot;rb&quot;); if(!file) { echo(&quot;Ошибка открытия файла&quot;);} else { fpassthru($file);} ?&gt; ...

Хочу дать возможность пользователю нажать на кнопку Cancel. - C++/CLI WinForms
Нужно, в процессе длительной работы (например, в цикле), дать возможность пользователю отменить эту длительную работу. Короче дать...


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

Или воспользуйтесь поиском по форуму:
11
14.07.2014, 21:48
Ответ Создать тему
Опции темы

КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin® Version 3.8.9
Copyright ©2000 - 2018, vBulletin Solutions, Inc.
Рейтинг@Mail.ru