Добро пожаловать на Pro Pawn - Портал о PAWN-скриптинге.
Показано с 1 по 7 из 7
  1. #1
    Аватар для Paradox
    Пользователь

    Статус
    Оффлайн
    Регистрация
    08.06.2015
    Адрес
    Запорожье
    Сообщений
    117
    Репутация:
    1 ±

    zcmd + sscanf (команды)

    Доброе время суток еще раз.
    В общем, можно ли как-то реализовать вот такой код:
    PHP код:
    public OnPlayerCommandText(playeridcmdtext[])
    {
        new 
    cmd[128], idx;
        
    cmd strtok(cmdtextidx);
        if(
    strcmp(cmd"/house"true) == 0)
        {
            
    cmd strtok(cmdtextidx);
            if(!
    strlen(cmd))
            {
                
    SendClientMessage(playerid, -1"Используйте: /house [params]");
                
    SendClientMessage(playerid, -1"sell - продать");
                
    SendClientMessage(playerid, -1"enter - вход");
                
    SendClientMessage(playerid, -1"exit - выход");
                return 
    true;
            }
            if(
    strcmp(cmd"sell"true) == 0)
            {
                
    cmd strtok(cmdtextidx);
                if(!
    strlen(cmd))
                {
                    return 
    SendClientMessage(playerid, -1"Используйте: /house sell [amount]");
                }
                new 
    amount strval(tmp);
                
    //
                
    return true;
            }
            if(
    strcmp(cmd"enter"true) == 0)
            {
                
    // вход
                
    return true;
            }
            if(
    strcmp(cmd"exit"true) == 0)
            {
                
    // выход
                
    return true;
            }
            return 
    true;
        }
        return 
    true;


    на zcmd + sscanf, что бы параметры вводились постепенно, если можно пару примеров как это реализовать.

  2. #2
    Аватар для whale
    Пользователь

    Статус
    Оффлайн
    Регистрация
    10.04.2014
    Сообщений
    74
    Репутация:
    17 ±
    А к чему, собственно, подобный мазохизм?
    Последний раз редактировалось whale; 30.01.2020 в 05:24.

  3. #3
    Аватар для L0ndl3m
    Пользователь

    Статус
    Оффлайн
    Регистрация
    19.10.2013
    Адрес
    Ярославль
    Сообщений
    1,366
    Репутация:
    774 ±
    Предлагаю варианты:

    С использованием стандартного командного процессора + sscanf:
    1. public OnPlayerCommandText(playerid, cmdtext[])
    2. {
    3. static const house_cmd[] = "/house"; // имя команды с правым слэшем
    4. const house_cmd_size = sizeof(house_cmd)-1;
    5.  
    6. if(strcmp(cmdtext, house_cmd, true, house_cmd_size) == 0)
    7. {
    8. new
    9. house_param_sell[] = "sell", // имя параметра "продажа"
    10. house_param_enter[] = "enter", // имя параметра "вход"
    11. house_param_exit[] = "exit"; // имя параметра "выход"
    12. const
    13. // подсчёт длин каждой команды во время компиляции
    14. house_param_sell_size = sizeof(house_param_sell)-1,
    15. house_param_enter_size = sizeof(house_param_enter)-1,
    16. house_param_exit_size = sizeof(house_param_exit)-1;
    17.  
    18. // расчёт максимальной длины из указанных ранее параметров
    19. #if house_param_sell_size>house_param_enter_size
    20. #define final_size house_param_sell_size
    21. #else
    22. #define final_size house_param_enter_size
    23. #endif
    24. #if house_param_exit_size > final_size
    25. #undef final_size
    26. #define final_size house_param_exit_size+1
    27. #endif
    28.  
    29. new
    30. param_name[final_size], // массив, содержащий имя параметра
    31. amount, // переменная, хранящая стоимость
    32. fmt_str[] = "s[%i]D(-1)", // массив спецификаторов
    33. spec_str[sizeof(fmt_str) + (-2 + 3)]; // массив, хранящий отформатированную строку со спецификаторами
    34.  
    35. format(spec_str, sizeof(spec_str), fmt_str, final_size+1);
    36.  
    37. #undef final_size
    38.  
    39. sscanf(cmdtext[house_cmd_size], spec_str, param_name, amount);
    40. if(isnull(param_name)) // если не указан параметр
    41. {
    42. SendClientMessage(playerid, -1, "Используйте: /house [params]");
    43. SendClientMessage(playerid, -1, "sell - продать");
    44. SendClientMessage(playerid, -1, "enter - вход");
    45. SendClientMessage(playerid, -1, "exit - выход");
    46. }
    47. else if(strcmp(param_name, house_param_sell, true, house_param_sell_size) == 0)
    48. {
    49. if(amount == -1)
    50. return SendClientMessage(playerid, -1, "Используйте: /house sell [amount]");
    51. }
    52. else if(strcmp(param_name, house_param_enter, true, house_param_enter_size) == 0)
    53. {
    54. SendClientMessage(playerid, -1, "Вы вошли в ваш дом.");
    55. }
    56. else if(strcmp(param_name, house_param_exit, true, house_param_exit_size) == 0)
    57. {
    58. SendClientMessage(playerid, -1, "Вы вышли из вашего дома.");
    59. }
    60. else
    61. {
    62. print("Такой параметр не найден.");
    63. }
    64. return true;
    65. }
    66. return true;
    67. }


    Плюсы:
    • Не нужно рассчитывать размер для строк и параметров;
    • Все параметры хранятся в одном месте. Если нужно поменять имя параметра, то не нужно "далеко ходить";
    • Размеры массивов вычисляются максимально точно


    Минусы:
    • Много кода;
    • Небольшой минус к производительности (взамен автоматизации?);
    • При добавлении нового параметра следует создавать константу для неё;


    С использованием ZCMD + sscanf без всяких "изворотов":
    1. CMD:house(playerid, params[])
    2. {
    3. new
    4. param_str[6],
    5. amount;
    6. sscanf(params, "s[5]I(-1)", param_str, amount);
    7. if(isnull(param_str))
    8. {
    9. SendClientMessage(playerid, -1, "Используйте: /house [params]");
    10. SendClientMessage(playerid, -1, "sell - продать");
    11. SendClientMessage(playerid, -1, "enter - вход");
    12. SendClientMessage(playerid, -1, "exit - выход");
    13. }
    14. else if(strcmp(param_str, "sell", true) == 0)
    15. {
    16. if (amount <= 0)
    17. return SendClientMessage(playerid, -1, "Используйте: /house sell [amount]");
    18.  
    19. // код для продажи дома
    20. }
    21. else if(strcmp(param_str, "enter", true) == 0)
    22. {
    23. SendClientMessage(playerid, -1, "Вы вошли в ваш дом.");
    24. }
    25. else if(strcmp(param_str, "exit", true) == 0)
    26. {
    27. SendClientMessage(playerid, -1, "Вы вышли из вашего дома.");
    28. }
    29. else
    30. {
    31. SendClientMessage(playerid, -1, "Указанный параметр не найден.");
    32. }
    33. return true;
    34. }


    P.S.: В сообщение будут вноситься правки при обнаружении более оптимизированных вариантов
    Последний раз редактировалось L0ndl3m; 30.01.2020 в 20:49.

  4. 3 пользователя(ей) сказали cпасибо:
    execution (30.01.2020) Kovshevoy (30.01.2020) Paradox (31.01.2020)
  5. #4
    Аватар для Kovshevoy
    Пользователь

    Статус
    Оффлайн
    Регистрация
    11.07.2015
    Сообщений
    190
    Репутация:
    25 ±
    Цитата Сообщение от L0ndl3m Посмотреть сообщение
    Предлагаю вариант:
    Плюсы:
    • Не нужно рассчитывать размер для строк и параметров;
    • Все параметры хранятся в одном месте. Если нужно поменять имя параметра, то не нужно "далеко ходить";
    • Размеры массивов вычисляются максимально точно


    Минусы:
    • Много кода;
    • Небольшой минус к производительности (взамен автоматизации?);
    • При добавлении нового параметра следует создавать константу для неё;


    P.S.: В сообщение будут вноситься правки при обнаружении более оптимизированных вариантов
    Вот теперь ты точно вернулся)
    p.s. Как обычно, какая-то фигня касаемо "ответить с цитированием" поэтому убрал код.
    (почините уже это дерьмо, господи()

  6. #5
    Аватар для Paradox
    Пользователь

    Статус
    Оффлайн
    Регистрация
    08.06.2015
    Адрес
    Запорожье
    Сообщений
    117
    Репутация:
    1 ±
    Цитата Сообщение от whale Посмотреть сообщение
    А к чему, собственно, подобный мазохизм?
    Очень удобно, в одной команде все подкоманды ненужно ничего запоминать.

    - - - Добавлено - - -

    Цитата Сообщение от L0ndl3m Посмотреть сообщение
    Предлагаю варианты:

    С использованием стандартного командного процессора + sscanf:
    1. public OnPlayerCommandText(playerid, cmdtext[])
    2. {
    3. static const house_cmd[] = "/house"; // имя команды с правым слэшем
    4. const house_cmd_size = sizeof(house_cmd)-1;
    5.  
    6. if(strcmp(cmdtext, house_cmd, true, house_cmd_size) == 0)
    7. {
    8. new
    9. house_param_sell[] = "sell", // имя параметра "продажа"
    10. house_param_enter[] = "enter", // имя параметра "вход"
    11. house_param_exit[] = "exit"; // имя параметра "выход"
    12. const
    13. // подсчёт длин каждой команды во время компиляции
    14. house_param_sell_size = sizeof(house_param_sell)-1,
    15. house_param_enter_size = sizeof(house_param_enter)-1,
    16. house_param_exit_size = sizeof(house_param_exit)-1;
    17.  
    18. // расчёт максимальной длины из указанных ранее параметров
    19. #if house_param_sell_size>house_param_enter_size
    20. #define final_size house_param_sell_size
    21. #else
    22. #define final_size house_param_enter_size
    23. #endif
    24. #if house_param_exit_size > final_size
    25. #undef final_size
    26. #define final_size house_param_exit_size+1
    27. #endif
    28.  
    29. new
    30. param_name[final_size], // массив, содержащий имя параметра
    31. amount, // переменная, хранящая стоимость
    32. fmt_str[] = "s[%i]D(-1)", // массив спецификаторов
    33. spec_str[sizeof(fmt_str) + (-2 + 3)]; // массив, хранящий отформатированную строку со спецификаторами
    34.  
    35. format(spec_str, sizeof(spec_str), fmt_str, final_size+1);
    36.  
    37. #undef final_size
    38.  
    39. sscanf(cmdtext[house_cmd_size], spec_str, param_name, amount);
    40. if(isnull(param_name)) // если не указан параметр
    41. {
    42. SendClientMessage(playerid, -1, "Используйте: /house [params]");
    43. SendClientMessage(playerid, -1, "sell - продать");
    44. SendClientMessage(playerid, -1, "enter - вход");
    45. SendClientMessage(playerid, -1, "exit - выход");
    46. }
    47. else if(strcmp(param_name, house_param_sell, true, house_param_sell_size) == 0)
    48. {
    49. if(amount == -1)
    50. return SendClientMessage(playerid, -1, "Используйте: /house sell [amount]");
    51. }
    52. else if(strcmp(param_name, house_param_enter, true, house_param_enter_size) == 0)
    53. {
    54. SendClientMessage(playerid, -1, "Вы вошли в ваш дом.");
    55. }
    56. else if(strcmp(param_name, house_param_exit, true, house_param_exit_size) == 0)
    57. {
    58. SendClientMessage(playerid, -1, "Вы вышли из вашего дома.");
    59. }
    60. else
    61. {
    62. print("Такой параметр не найден.");
    63. }
    64. return true;
    65. }
    66. return true;
    67. }


    Плюсы:
    • Не нужно рассчитывать размер для строк и параметров;
    • Все параметры хранятся в одном месте. Если нужно поменять имя параметра, то не нужно "далеко ходить";
    • Размеры массивов вычисляются максимально точно


    Минусы:
    • Много кода;
    • Небольшой минус к производительности (взамен автоматизации?);
    • При добавлении нового параметра следует создавать константу для неё;


    С использованием ZCMD + sscanf без всяких "изворотов":
    1. CMD:house(playerid, params[])
    2. {
    3. new
    4. param_str[6],
    5. amount;
    6. sscanf(params, "s[5]I(-1)", param_str, amount);
    7. if(isnull(param_str))
    8. {
    9. SendClientMessage(playerid, -1, "Используйте: /house [params]");
    10. SendClientMessage(playerid, -1, "sell - продать");
    11. SendClientMessage(playerid, -1, "enter - вход");
    12. SendClientMessage(playerid, -1, "exit - выход");
    13. }
    14. else if(strcmp(param_str, "sell", true) == 0)
    15. {
    16. if (amount <= 0)
    17. return SendClientMessage(playerid, -1, "Используйте: /house sell [amount]");
    18.  
    19. // код для продажи дома
    20. }
    21. else if(strcmp(param_str, "enter", true) == 0)
    22. {
    23. SendClientMessage(playerid, -1, "Вы вошли в ваш дом.");
    24. }
    25. else if(strcmp(param_str, "exit", true) == 0)
    26. {
    27. SendClientMessage(playerid, -1, "Вы вышли из вашего дома.");
    28. }
    29. else
    30. {
    31. SendClientMessage(playerid, -1, "Указанный параметр не найден.");
    32. }
    33. return true;
    34. }


    P.S.: В сообщение будут вноситься правки при обнаружении более оптимизированных вариантов
    Спасибо, попробую твой вариант.

  7. #6
    Аватар для red.inc
    Пользователь

    Статус
    Оффлайн
    Регистрация
    30.07.2019
    Адрес
    Беларусь, Витебск
    Сообщений
    23
    Репутация:
    0 ±
    Лучше уже y_stringhash воспользоваться

  8. #7
    Аватар для DeimoS
    Модератор?

    Статус
    Оффлайн
    Регистрация
    27.01.2014
    Адрес
    Восточный Мордор
    Сообщений
    5,588
    Репутация:
    1984 ±
    Цитата Сообщение от red.inc Посмотреть сообщение
    Лучше уже y_stringhash воспользоваться
    Особого профита от y_stringhash тут не будет. Код не так часто вызывается, чтоб важна была каждая миллисекунда.




      Открыть/закрыть
    Предложу такой, ещё более автоматизированный, вариант:
    1. enum _:e_HOUSECMD_ACTIONS_LIST
    2. {
    3. HouseCMD_Action_Sell,
    4. HouseCMD_Action_Enter,
    5. HouseCMD_Action_Exit
    6. };
    7. new const housecmd_actions[e_HOUSECMD_ACTIONS_LIST][] =
    8. {
    9. "sell",
    10. "enter",
    11. "exit"
    12. };


    1. SSCANF:housecmd_actions(const string[])
    2. {
    3. for(new i; i < sizeof(housecmd_actions); i++)
    4. {
    5. if(strcmp(string, housecmd_actions[i], true))
    6. continue;
    7. return i;
    8. }
    9. return -1;
    10. }



    1. CMD:house(playerid, params[])
    2. {
    3. new action;
    4. new amount;
    5. if(sscanf(params, "k<housecmd_actions>I(-1)", action, amount) || action == -1)
    6. {
    7. SendClientMessage(playerid, -1, "Используйте: /house [params]");
    8. SendClientMessage(playerid, -1, "sell - продать");
    9. SendClientMessage(playerid, -1, "enter - вход");
    10. SendClientMessage(playerid, -1, "exit - выход");
    11. return 1;
    12. }
    13. switch(action)
    14. {
    15. case HouseCMD_Action_Sell:
    16. {
    17. if (amount <= 0)
    18. return SendClientMessage(playerid, -1, "Используйте: /house sell [amount]");
    19.  
    20. // код для продажи дома
    21. }
    22. case HouseCMD_Action_Enter:
    23. {
    24. SendClientMessage(playerid, -1, "Вы вошли в ваш дом.");
    25. }
    26. case HouseCMD_Action_Exit:
    27. {
    28. SendClientMessage(playerid, -1, "Вы вышли из вашего дома.");
    29. }
    30. }
    31. return true;
    32. }


    UPD: Хотя я не подумал, что, в случае изменения количества действий, всё равно придётся лезть в код команды для добавления нового элемента в switch, так что получится не так удобно, как задумывалось изначально. Думаю, второй вариант от L0ndl3m тут наиболее оптимальный.
    Последний раз редактировалось DeimoS; 31.01.2020 в 14:05.
    Связаться со мной в VK можно через личные сообщения этой группы
    Заказы не принимаю

    Широко известно, что идеи стоят 0.8333 цента каждая (исходя из рыночной цены 10 центов за дюжину).
    Великих идей полно, на них нет спроса.
    Воплощение идеи в законченную игру требует долгой работы,
    таланта, терпения и креативности, не говоря уж о затратах денег, времени и ресурсов.
    Предложить идею просто, воплотить – вот в чём проблема

    Steve Pavlina

 

 

Информация о теме

Пользователи, просматривающие эту тему

Эту тему просматривают: 1 (пользователей: 0 , гостей: 1)

Ваши права

  • Вы не можете создавать новые темы
  • Вы не можете отвечать в темах
  • Вы не можете прикреплять вложения
  • Вы не можете редактировать свои сообщения
  •