Нужен парсер командной строки на чистом Си+WinApi

Тема в разделе "WASM.COMMERCE", создана пользователем M0rg0t, 16 ноя 2020.

  1. M0rg0t

    M0rg0t Well-Known Member

    Публикаций:
    0
    Регистрация:
    18 окт 2010
    Сообщения:
    1.574
    Нужен аналог вот этого https://github.com/hasherezade/paramkit , но на чистом Си (С99), и желательно без CRT.
    Чтобы была корректная обработка строковых параметров (кавычки, пробелы, вот это все).
     
  2. f13nd

    f13nd Well-Known Member

    Публикаций:
    0
    Регистрация:
    22 июн 2009
    Сообщения:
    1.954
    CommandLineToArgvW + lstrcmpiW достаточно будет.
     
    sn0w нравится это.
  3. Rel

    Rel Well-Known Member

    Публикаций:
    2
    Регистрация:
    11 дек 2008
    Сообщения:
    5.241
  4. M0rg0t

    M0rg0t Well-Known Member

    Публикаций:
    0
    Регистрация:
    18 окт 2010
    Сообщения:
    1.574
    f13nd, нужна проверка на недопустимый аргумент, и т.д. Лень самому кодить, может у кого есть готовое.

    Rel, проект на Си, зачем мне там плюсы.
     
  5. Vicshann

    Vicshann Member

    Публикаций:
    0
    Регистрация:
    22 сен 2020
    Сообщения:
    32
    Вот, выдрал из моего шаблона С++, вроде вполне чистый C:)
    Код (C):
    1.  
    2. wchar_t* GetCmdLineParam(wchar_t* CmdLine, wchar_t* Param, unsigned short Scope='\"\"', PUINT ParLen=NULL)
    3. {
    4. char SFchB = Scope >> 8;
    5. char SFchE = Scope;
    6. while(*CmdLine && (*CmdLine <= 0x20))CmdLine++;  // Skip any spaces before
    7. if(*CmdLine == SFchB)CmdLine++;  // Skip opening quote
    8.    else SFchE = 0x20;             // No quotes, scan until a first space
    9. T ParBeg = CmdLine;
    10. if(Param)
    11.   {
    12.    UINT MaxLen = (ParLen)?(*ParLen):(-1);  // -1 is MaxUINT
    13.    while(*CmdLine && (*CmdLine != SFchE) && MaxLen--)*(Param++) = *(CmdLine++);
    14.    *Param = 0;
    15.   }
    16.   else {while(*CmdLine && (*CmdLine != SFchE))CmdLine++;}
    17. if(ParLen)*ParLen = CmdLine - ParBeg;  // In Chars
    18. if(*CmdLine)CmdLine++;  // Skip last Quote or Space
    19. // while(*CmdLine && (*CmdLine <= 0x20))CmdLine++; // Skip any spaces after
    20. return CmdLine;
    21. }
    Вот так это использую:
    Код (C):
    1.  
    2. PWSTR CmdLine = GetCommandLineW();
    3. CmdLine = GetCmdLineParam(CmdLine, PWSTR(0));   // Skip EXE file name and path
    4. int ParCnt = -1;
    5. wchar_t Cmd[64];
    6. wchar_t Arg[MAX_PATH];
    7. for(;*CmdLine;ParCnt++)
    8.   {
    9.   CmdLine = GetCmdLineParam(CmdLine, Cmd);
    10.    if(!lstrcmpi(L"-L", Cmd))
    11.     {
    12.      CmdLine = GetCmdLineParam(CmdLine, Arg);
    13.      if(!AssignFilePath(ListFile, StartUpDir, Arg)){break;}
    14.      continue;
    15.     }
    16.   if(!lstrcmpi(L"-S", Cmd))
    17.   {
    18.   CmdLine = GetCmdLineParam(CmdLine, Arg);
    19.   Step = DecStrToNum(Arg);
    20.   continue;
    21.   }
    22.   }
    Что-то более развитое наверняка потащит за собой CRT:)
     
    Последнее редактирование: 16 ноя 2020
    M0rg0t нравится это.
  6. M0rg0t

    M0rg0t Well-Known Member

    Публикаций:
    0
    Регистрация:
    18 окт 2010
    Сообщения:
    1.574
    Vicshann, спасибо, попробую. Что значит "T ParBeg = CmdLine;" ? Это шаблон какой-то, как это будет в Си?
     
  7. Aiks

    Aiks Member

    Публикаций:
    0
    Регистрация:
    16 апр 2017
    Сообщения:
    109
    Адрес:
    Украина
    wchar_t* ParBeg = CmdLine;
     
    M0rg0t нравится это.
  8. sn0w

    sn0w Active Member

    Публикаций:
    0
    Регистрация:
    27 фев 2010
    Сообщения:
    956
    это значит copy-initialization with scalar initializer (prvalue), copy-elision semantics applied for the CTOR event.
    --- Сообщение объединено, 21 ноя 2020 ---
    а в си это будет alloc(), memcpy(), CTOR() // then use
    --- Сообщение объединено, 21 ноя 2020 ---
    если полиморфный класс надумал копировать, то данные в нём располагаются в порядке (void**pVFT, int a int b, c ну итд)
    --- Сообщение объединено, 21 ноя 2020 ---
    точнее говоря наврал я несколько - важно не scalar/aggregate, а то к какой категории значений(lvalue/prvalue/xvalue) относится инициализирующее выражение - тут и работает семантика копирования/оптимизации копии/перемещения.
    --- Сообщение объединено, 21 ноя 2020 ---
    значёк поинтера относится к декларатору, а не к базовому типу, прекращайте уже путать void* pSrc и void *pSrc; - это одно и тоже, хз кто так ддумался писать - но явно не тот кто матчасть изучал.
     
    Последнее редактирование: 21 ноя 2020
    Aiks и M0rg0t нравится это.
  9. Aiks

    Aiks Member

    Публикаций:
    0
    Регистрация:
    16 апр 2017
    Сообщения:
    109
    Адрес:
    Украина
    Это дело привычки. Стараюсь не объявлять несколько переменных в одной строке. Если это учесть, то запись является лучше читаемой(как минимум для меня). Ибо тип и переменная разделены пробелом.
    Почти всегда работаю над проектами один. Так что это не столь важно. Но в любом случае, спасибо за совет.

    http://www.kurzenkov.com/software_development/asterisk.html
     
  10. sn0w

    sn0w Active Member

    Публикаций:
    0
    Регистрация:
    27 фев 2010
    Сообщения:
    956
  11. Rel

    Rel Well-Known Member

    Публикаций:
    2
    Регистрация:
    11 дек 2008
    Сообщения:
    5.241
    Я кстати тоже всегда uint32_t* ptr пишу или использую auto, там где это возможно. Это куда лучше читается.
     
    Aiks нравится это.
  12. Aiks

    Aiks Member

    Публикаций:
    0
    Регистрация:
    16 апр 2017
    Сообщения:
    109
    Адрес:
    Украина
    Так никто и не спорит, что это все есть описано. Я так пишу код, ибо мне так удобнее/читабельнее. А не потому, что я не знаю как нужно правильно.

    P.S. Менять свою привычку пока не собираюсь. Спасибо! :derisive: