1. C++ / Говнокод #12468

    +21

    1. 01
    2. 02
    3. 03
    4. 04
    5. 05
    6. 06
    7. 07
    8. 08
    9. 09
    10. 10
    11. 11
    12. 12
    13. 13
    14. 14
    15. 15
    16. 16
    17. 17
    18. 18
    19. 19
    20. 20
    21. 21
    22. 22
    23. 23
    24. 24
    25. 25
    26. 26
    27. 27
    28. 28
    29. 29
    30. 30
    31. 31
    32. 32
    33. 33
    34. 34
    35. 35
    36. 36
    37. 37
    38. 38
    39. 39
    40. 40
    41. 41
    #define SWITCH(str)  switch(str_hash_for_switch(str))
    #define CASE(str)    static_assert(str_is_correct(str) && (str_len(str) <= MAX_LEN),\
    "CASE string contains wrong characters, or its length is greater than 9");\
    case str_hash(str, str_len(str))
    #define DEFAULT  default
    
    typedef unsigned char uchar;
        typedef unsigned long long ullong;
    
        const uchar MAX_LEN = 9;
        const ullong N_HASH = static_cast<ullong>(-1);
    
        constexpr ullong raise_128_to(const uchar power)
        {
            return 1ULL << 7 * power;
        }
    
        constexpr bool str_is_correct(const char* const str)
        {
            return (static_cast<signed char>(*str) > 0) ? str_is_correct(str + 1) : (*str ? false : true);
        }
    
        constexpr uchar str_len(const char* const str)
        {
            return *str ? (1 + str_len(str + 1)) : 0;
        }
    
        constexpr ullong str_hash(const char* const str, const uchar current_len)
        {
            return *str ? (raise_128_to(current_len - 1) * static_cast<uchar>(*str) + str_hash(str + 1, current_len - 1)) : 0;
        }
    
        inline ullong str_hash_for_switch(const char* const str)
        {
            return (str_is_correct(str) && (str_len(str) <= MAX_LEN)) ? str_hash(str, str_len(str)) : N_HASH;
        }
    
        inline ullong str_hash_for_switch(const std::string& str)
        {
            return (str_is_correct(str.c_str()) && (str.length() <= MAX_LEN)) ? str_hash(str.c_str(), str.length()) : N_HASH;
        }

    Запостил из-за ошибки на некоторых платформах и компиляторах.

    Запостил: LispGovno, 23 Января 2013

    Комментарии (37) RSS

    • std::string  month;
         std::string  days;
      
         std::cout << "Enter month name: ";
         std::cin  >> month;
      
         SWITCH (month)
         {
            CASE("february"): days = "28 or 29"; break;
      
            CASE("april"):
            CASE("june"):
            CASE("september"):
            CASE("november"): days = "30"; break;
      
            CASE("january"):
            CASE("march"):
            CASE("may"):
            CASE("july"):
            CASE("august"):
            CASE("october"):
            CASE("december"): days = "31"; break;
      
            DEFAULT: days = "?"; break;
         }
      
         std::cout << month << " has " << days << " days." << std::endl;
      Если бы пример использования был из реального проекта, то был бы достоин отдельного говнокода.
      Ответить
      • Я клепал нечто подобное для себя - но у меня все держалость не на хешах, а на свойствах типов, правда длинна строки в таких случах ограничивалась 4 символами.
        Ответить
        • > правда длинна строки в таких случах ограничивалась 4 символами
          И они обрамлялись одинарными кавычками?
          Ответить
    • Раз никто не говорит что это за ошибка, то подскажу: ошибка может приводить к выполнению не той ветки свича без объявления войны.
      Ответить
      • мало в хеш попасть, нужно ещё и совпадение строк проверять, если что. По хешу только группировать можно.
        Ответить
        • >По хешу только группировать можно.
          И фильтроблумить. То бишь проверять отсутствие.
          Ответить
        • Дак это не хеш. Это просто компрессия 9 аски символов в 64 бита. Т.к. код проверяет, что все символы в диапазоне 0x00..0x7F, и проверяет что их не более 9 - то х.з. как что-то может совпасть.
          Ответить
          • Если на платформе ullong не 64 бита, то может. MAX_LEN должен быть вычисляемым от длины ullong в компилетайме.
            Ответить
            • Вот нахрен я это сказал. Нужно было же потятнуть время, а потом стать АнтиУрсусом.
              Ответить
            • Так long long вроде как минимум 64 бита по стандарту? Или я туплю?

              Да, походу затупил, и действительно надо или uint64_t или выражать MAX_LEN через длину long long.
              Ответить
              • По стандарту известно, что
                char <= short <= int <= long <= long long
                Ответить
                • Меня вот эта строка смущает: long long - target type will have width of at least 64 bits (since C++11)

                  http://en.cppreference.com/w/cpp/language/types

                  В стандарте ее что-то найти не могу.
                  Ответить
                  • > Besides the minimal bit counts, the C++ Standard guarantees that
                    
                    1 == sizeof(char) <= sizeof(short) <= sizeof(int) <= sizeof(long) <= sizeof(long long).
                    Note: this allows, as an extreme case, an implementation where all types, including char, are 64 bits wide, and sizeof returns 1 for every type.


                    Хрен знает. Судя по всему какой-то умник статистику по самым популярным платформам собрал.
                    Ответить
                    • Besides the minimal bit counts, the C++ Standard guarantees that.

                      Судя по этой фразе автор как бы намекает нам, что стандарт с++ гарантирует не только те самые неравенства, но и минимальный размер типов в битах. Может быть в драфте они не описаны? Только в полноценной версии?
                      Ответить
                      • > Besides the minimal bit counts
                        Это возможно его заблуждение. Дамой с прогулки вернусь - посмотрю стандарт
                        Ответить
                        • >Дамой с прогулки
                          Сначала прочитал "С дамой, с прогулки вернусь". Потом понял что это фантастика.
                          Ответить
                          • Он вернется с прогулки дамой. Мне страшно подумать, что же с ним делали на прогулке, что он внезапно стал дамой.
                            Ответить
                            • Это ловушка.
                              Ответить
                            • > Он вернется с прогулки дамой.
                              А ты не задумывался, а может я ею всегда был? Ты почему мой возраст не знаешь? Потому что этот вопрос задавать мне не принято.
                              Ответить
                              • >а может я ею всегда был
                                Действительно. Может и был.
                                >мой возраст не знаешь
                                Да тут это вроде все знают - школьных лет.
                                Ответить
                              • А ушел/ушла девушкой?
                                Ответить
                        • уже ведь обсуждали эту проблему
                          сишный стандарт требует, чтобы значения целых типов включали минимальные границы
                          с теми границами unsigned long long может быть больше 64 битов, но не меньше

                          — minimum value for an object of type long long int
                          LLONG_MIN -9223372036854775807 // −(2^63−1)
                          — maximum value for an object of type long long int
                          LLONG_MAX +9223372036854775807 // 2^63−1
                          — maximum value for an object of typeunsigned long long int
                          ULLONG_MAX 18446744073709551615 // 2^64−1
                          Ответить
                          • Это в С++11 появилось? В С++03 же не было?
                            Ответить
                            • Кстати, если в С++11 есть, то я уже обосрался. Код на С++11
                              Ответить
                            • сишный
                              в крестоблядском стандарте все мутно
                              он импортирует <climits>, но не говорит ничего

                              а в драфте с++11 вообще написано, что мнение автора может не совпадать с его точкой зрения
                              The contents are the same as the Standard C library header <limits.h>. [ Note: The types of the constants defined by macros in <climits> are not required to match the types to which the macros refer. —end note ]
                              Ответить
                              • Блиииин!! Сишка уже нормально все сделала, а кресты все мутят воду. Какого хрена?
                                Ответить
                                • потому что крестоблядство есть, а сиблядства нет. есть только байтоебство самое ближайшее наверное.
                                  Ответить
                          • Все, еле как нашел в стандарте крестов: The contents are the same as the Standard C library header <limits.h>.

                            А в С99 как раз описаны минимальные ограничения для каждого типа.
                            Ответить
                            • > сишный стандарт требует, чтобы значения целых типов включали минимальные границы
                              > А в С99 как раз описаны минимальные ограничения для каждого типа.
                              Так, это уже интереснее. В С89 требование к минимуму на тип описано? С89 первый же стандарт сишки? Если в первом стандарте С89 описан минимум на тип, то гарантии наверное есть. Или нет... На каком-нибудь Арме может в limits.h лежать с вырвиглазыми размерами типов, тогда и в крестовом компиляторе все посыпется...
                              Ответить
      • Сдаюсь, в чем же ошибка?
        Ответить
    • Source
      http://habrahabr.ru/post/166201/
      Ответить
      • Да уж.. сегодня читал, удивился.
        Ответить
        • Я думаю этот литературный герой достаточно точно выразился по данному вопросу:
          http://www.youtube.com/watch?v=LxHdzGDazXg
          Ответить
          • Да мистер Пи, n комментариев выше ты оказался прав. Вчера в школе читали.
            Ответить

    Добавить комментарий