Консольная программа. Получение команд от пользователя. (Интерактивный режим.)

Модератор: Модераторы разделов

richrd
Сообщения: 227

Консольная программа. Получение команд от пользователя.

Сообщение richrd »

Может не совсем точно описал тему, извините, если что.
Суть вот в чём.
Запускается программа, что то отображает и ждёт последующего ввода команд до ввода команды выхода или Ctrl+z.
Формат вводимых команд:

Код: Выделить всё

-comand-name [param] [param] [pam] [pam]

В идеале хотелось бы получить всё в виде int argc, char **argv, но как? Не могу найти.
man gets 3:

Код: Выделить всё

fgetc, fgets, getc, getchar, gets, ungetc - input of characters and strings

Можно получить полностью введённую строку и её анализировать, но что то кажется что это через неправильно.
Подскажите правильный путь.

QT/С++
Спасибо сказали:
sciko
Сообщения: 1744
Статус: Ъ-участник
ОС: Debian/Ubuntu/etc

Re: Консольная программа. Получение команд от пользователя.

Сообщение sciko »

Qt в консоли? Можно, конечно, но зачем?

richrd писал(а):
29.11.2010 15:59
fgetc, fgets, getc, getchar, gets, ungetc - input of characters and strings
Ещё можно заюзать scanf.

richrd писал(а):
29.11.2010 15:59
В идеале хотелось бы получить всё в виде int argc, char **argv, но как?
Такие параметры получает только одна функция: main.

Кроме того, я бы глянул в сторону функции getopt() и библиотеки popt.
Спасибо сказали:
watashiwa_daredeska
Бывший модератор
Сообщения: 4038
Статус: Искусственный интеллект (pre-alpha)
ОС: Debian GNU/Linux

Re: Консольная программа. Получение команд от пользователя.

Сообщение watashiwa_daredeska »

Для ввода строк есть библиотека readline (GPL) и несколько подобных, которые поддерживают историю и т.п. В формат (int argc, char** argv), правда, придется самому переводить.

Можно запускать основную программу в фоне и сделать несколько сопутствующих команд-сателлитов, которые будут связываться с фоновой программой, а сами получать аргументы в нужном виде. Команда-сателлит может быть даже одна (на которую сделано несколько симлинков), которая определяет действие на основании argv[0].
Спасибо сказали:
Аватара пользователя
agentprog
Сообщения: 362
Статус: Ad Astra per aspera
ОС: openSUSE 11.4, Arch

Re: Консольная программа. Получение команд от пользователя.

Сообщение agentprog »

man strtok
а вообще, раз Qt, то может QString::split() уж?
и да, чем не нравится прочитать всю строку от пользователя? разве что только обрывать ввод при прочтении каких-то неправильных символов и/или токенов.
No problems - just solutions!
Спасибо сказали:
Аватара пользователя
Crazy
Сообщения: 862
Статус: Адепт Дзен.
ОС: Mint, Win7.

Re: Консольная программа. Получение команд от пользователя.

Сообщение Crazy »


Desipere in loco
Спасибо сказали:
sciko
Сообщения: 1744
Статус: Ъ-участник
ОС: Debian/Ubuntu/etc

Re: Консольная программа. Получение команд от пользователя.

Сообщение sciko »

IMB, надо было сразу давать man 3 getopt -- это стандартная функция glibc.

Crazy, а на кой ТС регэкспы?

agentprog, ваш пост огорчает Керигана и Ритчи: strtok(). Единственное, не забываем, что тут можно выстрелить в ногу.
Спасибо сказали:
Аватара пользователя
Crazy
Сообщения: 862
Статус: Адепт Дзен.
ОС: Mint, Win7.

Re: Консольная программа. Получение команд от пользователя.

Сообщение Crazy »

sciko на регулярных выражениях + map'ах можно сделать простой и мощный обработчик пользовательских команд.

Desipere in loco
Спасибо сказали:
Аватара пользователя
RasenHerz
Сообщения: 1341
ОС: Arch Linux amd64

Re: Консольная программа. Получение команд от пользователя.

Сообщение RasenHerz »

Crazy писал(а):
29.11.2010 22:54
sciko на регулярных выражениях + map'ах можно сделать простой и мощный обработчик пользовательских команд.

Не надо ничего выдумывать, все уже сделано за вас - http://tiswww.case.edu/php/chet/readline/readline.html , пункт 2.6 и далее.
Спасибо сказали:
sciko
Сообщения: 1744
Статус: Ъ-участник
ОС: Debian/Ubuntu/etc

Re: Консольная программа. Получение команд от пользователя.

Сообщение sciko »

RasenHerz, конечно настройка своих дополнений -- это интересно, но мне кажется что ТС более интересны парсинг опций.

Crazy писал(а):
29.11.2010 22:54
sciko на регулярных выражениях + map'ах можно сделать простой и мощный обработчик пользовательских команд.
Можно. Но зачем, когда есть getopt и strtok?
Спасибо сказали:
Аватара пользователя
RasenHerz
Сообщения: 1341
ОС: Arch Linux amd64

Re: Консольная программа. Получение команд от пользователя.

Сообщение RasenHerz »

sciko писал(а):
30.11.2010 12:08
RasenHerz, конечно настройка своих дополнений -- это интересно, но мне кажется что ТС более интересны парсинг опций.

Гм, я специально указал п. 2.6 и _далее_, на сколько я помню где-то там (после п2.6) рассмотрена привязка команд к функциям программы (в том числе автодополнение команд).

Запускается программа, что то отображает и ждёт последующего ввода команд до ввода команды выхода или Ctrl+z.

Самый простой вариант - читать с stdin и sscanf'ом парсить каждую строку.
Спасибо сказали:
sciko
Сообщения: 1744
Статус: Ъ-участник
ОС: Debian/Ubuntu/etc

Re: Консольная программа. Получение команд от пользователя.

Сообщение sciko »

RasenHerz писал(а):
30.11.2010 16:29
Самый простой вариант - читать с stdin и sscanf'ом парсить каждую строку.
А смысл парсить sscanf'ом? Это довольно тяжёлая функция. Кроме того, scanf сразу читает с stdin. Ну, и подходит это если число опций всегда должно быть одним и тем же.
Спасибо сказали:
Аватара пользователя
RasenHerz
Сообщения: 1341
ОС: Arch Linux amd64

Re: Консольная программа. Получение команд от пользователя.

Сообщение RasenHerz »

sciko писал(а):
30.11.2010 16:53
А смысл парсить sscanf'ом? Это довольно тяжёлая функция. Кроме того, scanf сразу читает с stdin. Ну, и подходит это если число опций всегда должно быть одним и тем же.

sscanf или scanf в данном случае скорее дело вкуса, лично я, когда решал похожую задачу делал так: в цикле считывал блоками по 4кб данные с stdin, потом этот блок строка за строкой обрабатывал (у команд было фиксированное количество параметров, так что все было довольно просто реализовать).
Спасибо сказали:
richrd
Сообщения: 227

Re: Консольная программа. Получение команд от пользователя.

Сообщение richrd »

sciko писал(а):
29.11.2010 17:10
Qt в консоли? Можно, конечно, но зачем?

Qt в консоли! Что бы была консольная версия GUI`шной программы/для самообразования
В общем вышло так:

Код: Выделить всё

            std::string str_in;
            do{
                std::getline(std::cin,str_in);
                QString user_command = QString(str_in.data());
                QStringList user_command_list = user_command.split(" ",QString::SkipEmptyParts);
                if(user_command_list.count()){
                    switch(get_arg_code(QString(user_command_list[0]).toLocal8Bit().data())){
                    case CommandOptionCode::ADD_FILE:{
                            fprintf(stdout,"\033[31mADD_FILE!\033[0m\n");
                        break;};
                    case CommandOptionCode::DEL_FILE:{
                            fprintf(stdout,"\033[31mDEL_FILE!\033[0m\n");
                        break;};
                    }
                } else {
                    show_help();
                }
            }while(str_in != "q");
            fprintf(stdout,"\033[31mGood bay!\033[0m\n");

get_arg_code:

Код: Выделить всё

int get_arg_code(std::string opt){
    const CommandOption* option = Perfect_Hash::IsValidCommandLineOption(opt.c_str(), opt.length());
    if(option){
        return option->OptionCode;
    }return -1;
}

man gperf или : )

Всем спасибо!
Спасибо сказали:
richrd
Сообщения: 227

Re: Консольная программа. Получение команд от пользователя.

Сообщение richrd »

Наткнулся на "засаду".
При нажатии ctrl+d
уходит в бесконечный цикл и показывает справку, то есть на

Код: Выделить всё

  show_help();

На простом примере:

Код: Выделить всё

#include <iostream>
#include <stdio.h>
#include <string>
int main()
{
  std::string str_in;
  puts("begin test");
  do {
          std::getline(std::cin,str_in);
          puts("in");
  } while(str_in != "q");
  puts("end test");
        return 0;
}

Это почему и как этого избежать?
Спасибо сказали:
Аватара пользователя
Rootlexx
Бывший модератор
Сообщения: 4471
Статус: GNU generation
ОС: Debian GNU/Linux

Re: Консольная программа. Получение команд от пользователя.

Сообщение Rootlexx »

richrd писал(а):
06.12.2010 15:45
Это почему и как этого избежать?

Потому, что нажатие Ctrl-D устанавливает EOF на поток стандартного ввода, а std::getline() при этом сразу завершается. В результате в str_in содержится пустая строка. Условие выхода из цикла - эквивалентность "q". Очевидно, что оно в таком случае никогда не выполнится.
Просто измените условие выхода:

Код: Выделить всё

...
} while (str_in != "q" && !std::cin.eof());
Спасибо сказали: