Вопросы

KlasterK
Освоившийся

В format и sscanf есть конструкция "{Float, _}:...". Первую часть конструкции я понимаю, теги. Но что значит "..."? Можно ли эту конструкцию использовать в своих функциях, и как обращатся к ней? Я в какой-то функции видел "Float:oper1, ...", получается, нужно обращатся через oper1, oper2, oper3?

Поделиться сообщением


Ссылка на сообщение

2 ответа на этот вопрос

  • 0
Sleash
Завсегдатый

{Float,_}:.. обозначает неопределённое кол-во параметров, к примеру в том же использовании sscanf при вводе команды:

/goto 36 // тут только 1 параметр
/sethp 36 0 // тут уже 2 параметра

Не думаю, что это можно использовать в ваших фанкция (вроде как {Float,_}:.. идёт только для плагинов), но вы можете использовать вместо этого массив:

stock multiprint(texts[])
{
    for(i = 0; i < sizeof texts; i++) {
        print(texts[i]);
    } return 1;
}
// use:
main() {
    new a = rand(110);
    multiprint({1"asd", a, 32.7});
    return 1;
}

Вроде так

Поделиться сообщением


Ссылка на сообщение
  • 0
Cawfee
Великий Гуру
1 час назад, Sleash сказал:

вроде как {Float,_}:.. идёт только для плагинов

Есть лишь одна синтаксема языка Pawn, которая не имеет никакого смысла без подключения сторонних программ, и эта синтаксема – ключевое слово native.

 

9 часов назад, KlasterK сказал:

{Float, _}:...

Для начала имеет смысл сказать пару слов о тегах. Для того, чтобы переменная или параметр функции могли принимать значение, принадлежащее определенному множеству значений, на уровне компилятора есть такая замечательная вещь как теги, использование которых, очевидно, помогает защитить себя от непреднамеренных ошибок. По умолчанию у всех переменных есть тег "_:", написание которого необязательно. Однако вы можете создавать свои собственные теги, чтобы, как уже было сказано, ограничить множество принимаемых значений.

 

В примере ниже реализована программа, создающая множество фигур, чтобы позволить тегированным переменным принимать значения из этого множества. В окне консоли можно увидеть слово "Круг".

Спойлер

#include <a_samp>



enum EShape: {
    CIRCLE = 0,
    TRIANGLE,
    SQUARE,
    OVAL
};

main() {
    new EShape:eShape = CIRCLE;
    
    switch (eShape) {
        case CIRCLE: {
            print("Круг");
        }
        case TRIANGLE: {
            print("Треугольник");
        }
        case SQUARE: {
            print("Квадрат");
        }
        default: {
            print("Неизвестная фигура");
        }
    }
}

 

 

Отмечу, что присвоение тегированной переменной значения, не входящего в множество допустимых значений, влечет предупреждение компилятора о несовпадении тегов (tag mismatch). Однако, несмотря на предупреждение, переменная eShape получает значение SOME_VALUE2, эквивалентное нулю (что совпадает со значением TRIANGLE), и в окне консоли мы видим слово "Треугольник".

Спойлер

#include <a_samp>


enum EShape: {
    CIRCLE = 0,
    TRIANGLE,
    SQUARE,
    OVAL
};

enum ESomeEnum: {
    SOME_VALUE1 = 0,
    SOME_VALUE2
};

main() {
    new EShape:eShape = SOME_VALUE2;
    
    switch (eShape) {
        case CIRCLE: {
            print("Круг");
        }
        case TRIANGLE: {
            print("Треугольник");
        }
        case SQUARE: {
            print("Квадрат");
        }
        default: {
            print("Неизвестная фигура");
        }
    }
}

 

 

Кроме того, можно попытаться присвоить и литерал. Однако в приведенном ниже примере вы все также можете увидеть предупреждение компилятора о несовпадении тегов. В окне консоли можно увидеть слово "Овал".

Спойлер

#include <a_samp>


enum EShape: {
    CIRCLE = 0,
    TRIANGLE,
    SQUARE,
    OVAL
};

enum ESomeEnum: {
    SOME_VALUE1 = 0,
    SOME_VALUE2
};

main() {
    new EShape:eShape = 3;
    
    switch (eShape) {
        case CIRCLE: {
            print("Круг");
        }
        case TRIANGLE: {
            print("Треугольник");
        }
        case SQUARE: {
            print("Квадрат");
        }
        case OVAL: {
            printf("Овал");
        }
        default: {
            print("Неизвестная фигура");
        }
    }
}

 

 

Кроме того, можно попытаться смешать тегированные и нетегированные переменные, что также повлечет предупреждение компилятора, но в целом будет работать. В окне консоли можно увидеть слово "Квадрат".

Спойлер

#include <a_samp>


enum EShape: {
    CIRCLE = 0,
    TRIANGLE,
    SQUARE,
    OVAL
};

enum ESomeEnum: {
    SOME_VALUE1 = 0,
    SOME_VALUE2
};

main() {
    new EShape:eShape = CIRCLE + 1// 0 + 1 + 1 = 2
    
    switch (eShape) {
        case CIRCLE: {
            print("Круг");
        }
        case TRIANGLE: {
            print("Треугольник");
        }
        case SQUARE: {
            print("Квадрат");
        }
        case OVAL: {
            printf("Овал");
        }
        default: {
            print("Неизвестная фигура");
        }
    }
}

 

 

В примерах выше я никак не пытался удовлетворить компилятор в части несоответствия тегов. Однако, если вы хотите явным образом работать с переменными, теги которых не совпадают, вы можете искусственно изменить тег переменной или параметра функции. И таким образом, например, можем либо явно тегировать литералы, либо сбросить теги переменных.

new EShape:eShape = CIRCLE + EShape:1 + 1// 0 + 1 + 1 = 2

В случае, если вы хотите выполнить сравнение двух переменных, имеющих разные теги, вы также можете привести их к общему тегу (например, тег по умолчанию):

Спойлер

new EShape:eShape = CIRCLE;
new ESomeEnum:eSomeEnum = SOME_VALUE1;

if (_:eShape == _:eSomeEnum) {
    print("Equals!");
}
else {
    print("Not equals");
}

if (EShape:eShape == EShape:eSomeEnum) {
    print("Equals!");
}
else {
    print("Not equals");
}

if (eShape == EShape:eSomeEnum) {
    print("Equals!");
}
else {
    print("Not equals");
}

 

 

 

Кроме того, из школьного курса математики вам должно быть известно, что фигурные скобки есть множество, а элементы внутри этих скобок – элементы множества. Выражение "{Float,_}:" содержит множество тегов, которые могут быть получены как аргументы функции. Вам ничто не мешает вписать в это множество и свои собственные теги:

someFunction({Float,_,EShape, ESomeEnum}:...) {
    // тело функции
}

main() {

    new EShape:eShape = CIRCLE;
    new ESomeEnum:eSomeEnum = SOME_VALUE1;

    someFunction(eShape, eSomeEnum);
}

Кроме того, вы можете и не перечислять все теги, что не понравится компилятору: он выдаст предупреждение, поскольку функция не ожидает получить на вход переменные, снабженные неизвестными для нее тегами.

someFunction({Float,_}:...) {
    // тело функции
}

main() {

    new EShape:eShape = CIRCLE;
    new ESomeEnum:eSomeEnum = SOME_VALUE1;

    someFunction(eShape, eSomeEnum);
}

Однако для разрешения возникшей проблемы можно просто привести переменные к тегу по умолчанию:

someFunction({Float,_}:...) {
    // тело функции
}

main() {

    new EShape:eShape = CIRCLE;
    new ESomeEnum:eSomeEnum = SOME_VALUE1;

    someFunction(_:eShape, _:eSomeEnum);
}

 

Теперь что касается самих параметров. Как вы уже могли заметить по функциям вроде printf, SendClientMessage и прочим – все они могут получать на вход переменное число аргументов: либо ни одного, либо не меньше некоторого натурального числа N. Поскольку программист на этапе написания программы и сам не имеет понятия, сколько аргументов в конкретном случае будет передано в функцию, работа с параметрами функции идет посредством обращения в стек: указываем порядковый номер параметра и вытаскиваем из стека значение этого параметра. Узнать, сколько передано параметров в функцию, можно при помощи функции numargs, а обратиться к некоторому параметру – с помощью функции getarg. Ниже приведен пример использования функции с переменным числом аргументов.

 

Спойлер

someFunction(const types[], const size = sizeof(types), {Float,_}:...) {
    new lastCheckedArg = 2;

    for (new i = 0; i < size - 1; i++) {
        if (types[i] == 'd') { // рассматриваем число
            printf("%d", getarg(lastCheckedArg));
        }
        else if (types[i] == 's') { // рассматриваем строку
            new nIdxs = types[i + 1] - '0';

            for (new j = 0; j < nIdxs; j++) {
                printf("%c", getarg(lastCheckedArg, j));
            }

            i++; // также мы посмотрели размер, так что переходим далее
        }
        else if (types[i] == 'f') { // рассматриваем вещественное число
            printf("%f", getarg(lastCheckedArg));
        }
        else {
            print("Unknown param");
            break;
        }
        
        lastCheckedArg++; // переходим к следующему аргументу
    }
}

main() {
    someFunction("ddds5s1s3f", _, 23082023"pawno""-""rus"777.555);
}

 

 

Результат в консоли представлен далее.

Спойлер

23
8
2023
p
a
w
n
o
-
r
u
s
777.554992

 

 

Но, будем честны, мне сложно представить ситуацию, при которой появляется необходимость в написании функции с переменным числом аргументов.

Поделиться сообщением


Ссылка на сообщение
Гость
Эта тема закрыта для публикации ответов.
  • Последние посетители   0 пользователей онлайн

    Ни одного зарегистрированного пользователя не просматривает данную страницу

  • Похожий контент

    • Дебилойд
      От Дебилойд
      Здравствуйте!
      Мы ищем талантливого 3D-моделлера в команду нашего CRMP-проекта!
      Что нужно будет делать:
      Моделировать и адаптировать автомобили.
      Создавать и настраивать скины (модели персонажей).
      Большим плюсом будет:
      Умение создавать качественные и оптимизированные интерьеры.
      Если вы хотите стать частью нашей команды и развивать проект вместе с нами, пишите в ЛС. Ждем ваши портфолио!
    • LORDIKUS
      От LORDIKUS
      Уважаемые участники форума - всех приветствую, кто перешел в беседу моей темы обсуждения. В настоящее время у меня зарождается огромное желание и мысль создать собственный CR:MP проект, но столкнулся с единственной проблемой - с отсутствием команды людей, у которых будет искреннее желание ежедневно вкладывать свой труд на разработку проекта. Особого опыта в скриптинге, маппинге, дизайне или в моделировании у меня не имеется, поэтому такой критерий как опыт в определенной сфере для желающих вступить в команду я не рассматриваю. Так как проект не открыт и находится на начальной стадии создания, мое сотрудничество выстраивается на некоммерческой основе (без выплаты за проделанную работу и труд), однако я не собираюсь отрицать высокую ценность вложенного командой труд — труд, особенно на первой стадии разработки я рассматриваю превыше всего. После открытия проекта в зависимости от коммерции и чистой прибыли каждый участник будет получать настоящую выплату, однако это также может убить еще значительное время. Мне нужна команда, которая проявит искренний интерес в создании общего между командой CR:MP проекта, пожертвует свое время, а также вложит собственный труд благодаря заработанным навыкам. Если вас заинтересовала данная тема обсуждения, пожалуйста, свяжитесь со мной по любым возможным и удобным для вас контактам связи ниже. Спасибо всем, кто зашел в мою беседу!

      🔗 Спец. Связь:
      — DISCORD: https://discord.com/users/1452715348196589691 (перейти по ссылке и добавить в друзья) ИЛИ _shin833_ (ввести никнейм и отправить запрос дружбы)
      — VK: https://vk.com/shin833
      — TG: https://t.me/s_hin833
    • Korochansky
      От Korochansky
      Настало время объявить о скором выпуске первого релиза среды разработки под названием Spawn.

      В настоящее время программа находится на заключительных этапах доработки кода и локализации интерфейса.
      Таким образом, в течение следующей недели будет выпущена быстрая и современная среда разработки, обладающая следующими возможностями (о которых я расскажу сейчас, а о других — позже):
       
      Полнофункциональный локальный Git: 
      Индексирование, фиксации, индикаторы состояния и мягкий/жесткий сброс до любой точки сохранения одним щелчком мыши. Разрабатывайте свой игровой сервер, не боясь его сломать.
      Новички могут рассматривать это как историю кодовой базы вашего сервера (что и есть на самом деле).
       
      Чистый UTF-8 (без BOM): 
      Полный отказ от устаревшей кодировки Windows-1251 (CP1251) для абсолютной стабильности и идеальной совместимости с Git.
      Реализация поддержки CP1251 привела бы к нестабильному поведению программы и ухудшила бы пользовательский опыт.
       
      История изменений строк: Редактор выделяет измененные строки в реальном времени в полях рядом с номерами строк. Это позволяет мгновенно видеть границы изменений, внесенных с момента открытия файла.
       
      Сопоставление и выделение фигурных скобок: мгновенное выделение открывающих и закрывающих фигурных скобок для быстрой навигации по структуре кода и защиты от ошибок компиляции.
       
      Интеграция с SAMPCTL: готовая к использованию автоматизация процессов. Сборка, запуск сервера и менеджер зависимостей (управление библиотеками и плагинами) работают напрямую из интерфейса редактора.
       
      И многое другое...
       
      И самое главное: проект будет с открытым исходным кодом под лицензией GPLv3!
      Следите за новостями о выпуске в репозитории: https://github.com/daniilkorochansky/spawn
    • KodBi
      От KodBi
      шапка
      по одиночке работают
      нужны оба