Блог пользователя MikeMirzayanov

Автор MikeMirzayanov, 5 лет назад, По-русски

Привет!

Мне кажется все последние годы я что-то писал прям в то время, пока все нормальные люди отмечают Новый год. Это прям традиция какая-то. Собственно, большая часть базовой функциональности Codeforces была написана в новогодние праздники 2010-го года: авторизация, блоги, базовая поддержка соревнований.

Возможно, я хочу провести и следующий год с интересом что-то улучшая в инфраструктуре Codeforces (да-да, как Новый год встретишь — так его и проведёшь). А может просто в Новый год вроде работать не обязательно и делаешь не то, что вот прям сейчас надо, а то, что хорошо бы когда-нибудь сделать.

В этот раз я выделил чуток времени, чтобы добавить в testlib поддержку разбора параметров командной строки. Мне очень не нравится в генераторах писать такое int n = atoi(argv[3]);. Собственно по нескольким причинам:

  • небезопасно к тому, что 3-го параметра командной строки может и не быть;
  • небезопасно к тому, что 3-й параметр командной строки может не оказаться корректным 32-х битным целым числом.

Теперь вместо этого следует писать так: int n = opt<int>(3);. Кроме того, вы может писать и такое int64_t m = opt<int64_t>(1);, такое bool t = opt<bool>(2); или даже string s = opt(4);.

Кроме того, я поддержал именованные параметры. Если параметров слишком много, то запись g 10 20000 a true менее читаемая чем g -n10 -m200000 -t=a -increment.

В таком случае теперь вы можете использовать такие сниппеты кода в вашем генераторе:

int n = opt<int>("n");
long long n = opt<long long>("m");
string t = opt("t");
bool increment = opt<bool>("increment");

Вы можете свободно смешивать чтение параметров по индексу и по именам.

Поддерживаются следующие варианты записи именнованных параметров:

  • --key=value или -key=value;
  • --key value или -key value — если value не является стартом нового параметра (не начинается с дефиса или после одного/двух дефисов не идёт буква);
  • --k12345 или -k12345 — если ключ k это одна буква и затем идёт цифра;
  • -prop или --prop — для включения булевских свойств.

Ниже записаны примеры для запуска нескольких вымышленных генераторов:

g1 -n1
g2 --len=4 --s=oops
g3 -inc -shuffle -n 5
g4 --length 5 --total 21 -ord

Возможно, я в торопях написал что-то не очень удачно или даже с багами. Предлагаю вам посмотреть в мои последние коммиты. Буду рад дельным предложениям или фиксам.

Спасибо за внимание.

А какие у вас есть традиции на Новый год?

  • Проголосовать: нравится
  • +468
  • Проголосовать: не нравится

»
5 лет назад, # |
  Проголосовать: нравится +39 Проголосовать: не нравится

Одна из традиций, дорешивать Goodbye 20xx :)

»
5 лет назад, # |
Rev. 2   Проголосовать: нравится +30 Проголосовать: не нравится

О, наконец-то такое есть в самом testlib'е :)

Раньше мне приходилось решать проблему с параметрами командной строки с помощью самописной библиотеки.

»
5 лет назад, # |
  Проголосовать: нравится +40 Проголосовать: не нравится

auto n = opt<int>(3)?

»
5 лет назад, # |
  Проголосовать: нравится -16 Проголосовать: не нравится

What traditions do you have for the New Year?

Every New Year as proud Hrvat me and my comrades partake in rare art of "shitpost" which mblazev teach to me.

»
5 лет назад, # |
  Проголосовать: нравится +24 Проголосовать: не нравится

We have a tradition of serving Malpua (A deep-fried pancake). "Mal-" means goods. "-Pua" means Pancake. It has Dry fruits with optional mashed banana fried in clarified butter. It's a lip-smacking experience for any feast. Hope the next contest on codeforces is as tasty as that :) HNY2020

»
5 лет назад, # |
  Проголосовать: нравится -10 Проголосовать: не нравится

Мне кажется, имя плохое: уж очень похоже на optional<T>

  • »
    »
    5 лет назад, # ^ |
      Проголосовать: нравится +51 Проголосовать: не нравится

    Не думаю, что в этом есть какая-то проблема:

    • не так и похоже (редакционное расстояние $$$5$$$, перепутать их при беглом чтении или разработке невозможно);
    • никто не использует optional в генераторах (большинство вообще не знают о них);
    • термин opt довольно принят для подобной функциональности, не я его выдумал (есть библиотеки cxxopts,getopt, boost::program_options и другие).
»
5 лет назад, # |
Rev. 2   Проголосовать: нравится +65 Проголосовать: не нравится

Обычно всё-таки program -abc эквивалентно program -a -b -c, e.g. ls -lah, а длинные опции требуют двух минусов

»
5 лет назад, # |
  Проголосовать: нравится +20 Проголосовать: не нравится

В примерах генераторов в полигоне сейчас записан старый прием разбора аргументов командной строки (например, тут) Предлагаю поменять на новый.

»
5 лет назад, # |
  Проголосовать: нравится -9 Проголосовать: не нравится

Так а что вернёт opt<int>(3), если третьего аргумента нет, или он не является корректным 32-битным числом?

  • »
    »
    5 лет назад, # ^ |
      Проголосовать: нравится +32 Проголосовать: не нравится

    Если нет: FAIL Opts: index '3' is out of range [0,3)

    Если не корректное число: FAIL Opts: expected integer but 'abcd' found

    Если число слишком большое: FAIL Opts: integer overflow: expected integer but '179179179179' found

    Предлагаю в подобных случаях запускать и проверять (я так сделал)).

»
5 лет назад, # |
Rev. 4   Проголосовать: нравится +7 Проголосовать: не нравится

When i try to use opt in my generator i get this compile error when uploading it to polygon:

More information: the following code causes the same error:

#include "testlib.h"
#include <iostream>

int main(int argc, char* argv[])
{
    registerGen(argc, argv, 1);
    int n=opt<int>("n");
    cout<<n<<endl;
}

I tried ticking the Auto-Update box next to testlib.h but the same error appears.

UPD: I'm able to compile it now.

»
5 лет назад, # |
  Проголосовать: нравится 0 Проголосовать: не нравится

Ok, now i seem to be able to put opts in my generator in polygon without a compile error, but one thing the blog doesn't mention is how to make a boolean variable false. I assumed that since the blog says that for example -increment makes opt<bool>("increment") true that simply not putting anything related to increment to command line would make opt<bool>("increment") false, but instead it gives an error FAIL Opts: unknown key 'keyname'. Something like -keyname=false works, but is there a better way?

»
5 лет назад, # |
Rev. 2   Проголосовать: нравится +30 Проголосовать: не нравится

Could you support options which receive default values when they are missing in the command line?

»
4 года назад, # |
  Проголосовать: нравится +10 Проголосовать: не нравится

Having used this feature extensively, there is one thing that regularly confuses me. If you write int n = opt<int>("n"); but do not provide n in the command line, the error message is something like "unknown key: 'n'". To me, this suggests the exact opposite situation: that the key is in the command line arguments but not in the program (even though this doesn't make sense in this case). Could we change the wording here?