crossplatform.ru

Здравствуйте, гость ( Вход | Регистрация )

 
Ответить в данную темуНачать новую тему
> Правильный парсинг аргументов командной строки
RazrFalcon
  опции профиля:
сообщение 16.12.2010, 21:44
Сообщение #1


Zombie Mod
*****

Группа: Участник
Сообщений: 1654
Регистрация: 24.5.2010
Из: Харьков
Пользователь №: 1752

Спасибо сказали: 64 раз(а)




Репутация:   212  


Делаю так
QCoreApplication a(argc, argv);
    QStringList arg=a.arguments();
    if (arg[1]=="help" || arg[1]=="--help" || arg[1]=="-h")
...
и так далее

Но если будет help на втором месте то уже ничего работать не будет, и если аргуменов меньше чем у меня прописано (идет до arg[5]), то сразу валится прога, нужно еще один if писать для проверки, в духе if (arg.count()>4).
Как правильно *название темы*?
Перейти в начало страницы
 
Быстрая цитата+Цитировать сообщение
Rocky
  опции профиля:
сообщение 16.12.2010, 23:24
Сообщение #2


Старейший участник
****

Группа: Участник
Сообщений: 530
Регистрация: 22.12.2008
Из: Санкт-Петербург
Пользователь №: 463

Спасибо сказали: 22 раз(а)




Репутация:   7  


Ну как бы я бы сделал так. Создал словарь команд (например тот же std::map). Ключ - интуитивно понятное слово либо идентификатор. Потом тупо цикл по входым аргументам. Взял 1-й пришедший элемент - нашел/не нашел его в словаре. Если нашел - выполняю "сценарий" для него. Если нет - перешел к следующему входному параметру.
Перейти в начало страницы
 
Быстрая цитата+Цитировать сообщение
RazrFalcon
  опции профиля:
сообщение 16.12.2010, 23:28
Сообщение #3


Zombie Mod
*****

Группа: Участник
Сообщений: 1654
Регистрация: 24.5.2010
Из: Харьков
Пользователь №: 1752

Спасибо сказали: 64 раз(а)




Репутация:   212  


что то типа:
    for (int i=0; i<arg.count(); i++)
    {
        if(arg[i]=="-h") {тут выплняем нужное};
    }

?
Перейти в начало страницы
 
Быстрая цитата+Цитировать сообщение
Rocky
  опции профиля:
сообщение 16.12.2010, 23:40
Сообщение #4


Старейший участник
****

Группа: Участник
Сообщений: 530
Регистрация: 22.12.2008
Из: Санкт-Петербург
Пользователь №: 463

Спасибо сказали: 22 раз(а)




Репутация:   7  


Что-то типа
std::map<QString, QStringList> roPossibleComands;
roPossibleComands[0] = QStringList() << "-h" << "--help" << "help";
const int nNumArgs = arg.count();
for (nArg = 0; nArg < nNumArgs; ++nArg)
{
   for (std::map<QString, QStringList>::const_iterator it = roPossibleComands.begin(); it != roPossibleComands.end(); ++it)
   {
      if (it->second.find(arg[nArg]))
      {
            foo(it->first);
            break;
      }
   }
}


void foo(int whatShallWeDo)
{
switch (whatShallWeDo)
{
   case 0: //print help
   return;
   //etc
}
}

Если у QStringList нет методов поиска (я не помню), заменить на std::set<QString> например. Это то что пришло сразу в голову не задумываясь.... А вообще я думаю стоит посмотреть на исходники любой консольной линуксовой программки и глянуть как там сделано.

Сообщение отредактировал Rocky - 16.12.2010, 23:42
Перейти в начало страницы
 
Быстрая цитата+Цитировать сообщение
Kagami
  опции профиля:
сообщение 16.12.2010, 23:40
Сообщение #5


Старейший участник
****

Группа: Участник
Сообщений: 601
Регистрация: 2.2.2009
Пользователь №: 523

Спасибо сказали: 101 раз(а)




Репутация:   9  


Раньше в qxt был класс QxtCommandOptions (сейчас он правда куда-то пропал...) В принципе его можно найти в проекте qtmxtools (в папке 3rdparty\libqxt). Он хорошо комментирован, плюс в qtmxtools можно посмотреть как он используется.
Перейти в начало страницы
 
Быстрая цитата+Цитировать сообщение
maint
  опции профиля:
сообщение 17.12.2010, 5:42
Сообщение #6


Участник
**

Группа: Участник
Сообщений: 235
Регистрация: 3.8.2009
Из: Иркутск
Пользователь №: 982

Спасибо сказали: 28 раз(а)




Репутация:   2  


есть такая штучка getopt называется. Сишники ей сто лет уже пользуются для разборки командной строки. Она свободна
Перейти в начало страницы
 
Быстрая цитата+Цитировать сообщение
Kagami
  опции профиля:
сообщение 17.12.2010, 16:37
Сообщение #7


Старейший участник
****

Группа: Участник
Сообщений: 601
Регистрация: 2.2.2009
Пользователь №: 523

Спасибо сказали: 101 раз(а)




Репутация:   9  


Можно и getopt использовать, но гораздо удобнее использовать QxtCommandOptions, который умеет работать с QString.

P.S. QxtCommandOptions из libqxt никуда не делся, просто из документации почему-то его убрали
Перейти в начало страницы
 
Быстрая цитата+Цитировать сообщение
Litkevich Yuriy
  опции профиля:
сообщение 17.12.2010, 18:44
Сообщение #8


разработчик РЭА
*******

Группа: Сомодератор
Сообщений: 9669
Регистрация: 9.1.2008
Из: Тюмень
Пользователь №: 64

Спасибо сказали: 807 раз(а)




Репутация:   94  


ну или ручками
Пример из действующей программы
/*!
\file main.cpp
\brief Основной файл программы.
*/

#include <QCoreApplication>
#include <QTextCodec>
#include <QTextStream>
#include <QRegExp>
#include <QFileInfo>
#include <QDir>
#include <iostream>

#include "bomparser.h"


const char * SW_VERSION = "2.0.0";


void showVersion()
{
    fprintf(stdout, "Converter from BOM-files to SQLite databdase, version %s\n", SW_VERSION);
}

void showHelp(const char *appName)
{
    showVersion();

    fprintf(stdout, "Usage: %s [option] <file.bom>\n\n"
            "This program convert SQLite databdase file file.bom.proj from file.bom\n"
            "  -r, --rewrite             rewrite existing project\n"
            "  -h, --help                display this help and exit\n"
            "  -v, --version             display version\n"
            "\n", appName);
}



int main(int argc, char *argv[])
{

  int arg = 0;
  QString    bomFilename;
  bool isRewrite = false;
  QTextStream out(stdout);
  
  
    while (arg < argc)
    {
        ++arg;    
        QString opt = QString::fromLocal8Bit(argv[arg]);
        QRegExp rx("*.bom");
        rx.setPatternSyntax(QRegExp::Wildcard);
        //out << "option: " << opt << endl;
        
        if (opt == QLatin1String("-h") || opt == QLatin1String("--help"))
        {
            showHelp(argv[0]);
            return 0;
        }
        else if (opt == QLatin1String("-v") || opt == QLatin1String("--version"))
        {
            showVersion();
            return 0;
        }
        else if (opt == QLatin1String("-r") || opt == QLatin1String("--rewrite"))
        {
            isRewrite = true;
        }
        else if (rx.exactMatch(opt))
        {
            bomFilename = opt;
            break;
        }
        else
        {
            showHelp(argv[0]);
            return 1;
        }
    }
    
    QCoreApplication app(argc, argv);

    // Устанавливаем кодеки
    QTextCodec::setCodecForCStrings(QTextCodec::codecForLocale());
    QTextCodec::setCodecForTr(QTextCodec::codecForName("UTF-8")); // Для функций перевода tr()

    // Проверяем существует-ли файл
    QFileInfo     fi;

    fi.setFile(bomFilename);
    if(!fi.exists()){
        fprintf(stderr, "ERROR: BOM file %s, is not exist", qPrintable(bomFilename));
        return 1;
    }    

    // Имя файла БД
    QString    dbname = fi.path() +  QDir::separator()  + fi.fileName() + QString(".proj");

    fi.setFile(dbname);
    if(fi.exists()){
        if (!isRewrite){
            fprintf(stderr, "ERROR: project file: %s - already exist", qPrintable(dbname));
            return 1;
        }else{
            if (!QFile::remove(dbname)){
                fprintf(stderr, "ERROR: unable delete project file: %s", qPrintable(dbname));
                return 1;            
            }
        }
    }
    
    BomParser    parser(bomFilename);
    
    parser.setDelimiter(QString("@"));
    parser.setDbName(dbname);
    
    return parser.parse();

}
Перейти в начало страницы
 
Быстрая цитата+Цитировать сообщение

Быстрый ответОтветить в данную темуНачать новую тему
Теги
Нет тегов для показа


1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0




RSS Текстовая версия Сейчас: 21.12.2024, 19:23