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

    +171

    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
    42. 42
    #include <iostream>
    
    template <int n>
    struct Solution
    {
      static const int count = Solution<n / 10>::count + 1;
      static const int sum = Solution<n / 10>::sum + n % 10;
      static const int last = n % 10;
      static const int first = Solution<n / 10>::first;
    };
    
    #define DECLARE_ONE_DIGIT_SOLUTION(n) template <>\
                                          struct Solution<n>\
                                          {\
                                            static const int count = 1;\
                                            static const int sum = n;\
                                            static const int last = n;\
                                            static const int first = n;\
                                          };
    
    DECLARE_ONE_DIGIT_SOLUTION(0)
    DECLARE_ONE_DIGIT_SOLUTION(1)
    DECLARE_ONE_DIGIT_SOLUTION(2)
    DECLARE_ONE_DIGIT_SOLUTION(3)
    DECLARE_ONE_DIGIT_SOLUTION(4)
    DECLARE_ONE_DIGIT_SOLUTION(5)
    DECLARE_ONE_DIGIT_SOLUTION(6)
    DECLARE_ONE_DIGIT_SOLUTION(7)
    DECLARE_ONE_DIGIT_SOLUTION(8)
    DECLARE_ONE_DIGIT_SOLUTION(9)
    
    int main()
    {
      const int number = 1024; // <-- то самое число a
    
      std::cout << "Number of digits: " << Solution<number>::count << std::endl;
      std::cout << "Sum: " << Solution<number>::sum << std::endl;
      std::cout << "Last digit: " << Solution<number>::last << std::endl;
      std::cout << "First digit: " << Solution<number>::first << std::endl;
    
      return 0;
    }

    Это один из ответов к слезной просьбе какого-то школьника (студента) выполнить за него д/з на С++ в разделе development форума на ЛОРе. Такую программу нарочно хрен напишешь.

    Само задание: «Дано натуральное число а (a≤100). Напишите программу, определяющую количество цифр в этом числе, сумму его цифр, выводящую на экран первую и последнюю цифру через два пробела».

    Запостил: deniska, 16 Февраля 2011

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

    • показать все, что скрытоСовсем ООП людям мозг съело.
      Ответить
      • ООП времени компиляции со всеми костылями вокруг этого (ШАБЛОНЫ) действительно съело мозг бедным приплюснутым.
        Ответить
      • Где здесь ООП?
        Ответить
    • показать все, что скрытоРешение в функцианальном стиле.
      Ответить
      • Б. Тарас, наконец решился почитать про функциональную парадигму. Похвально.
        Ответить
        • вместо традиционного "на паскале такое говно невозможно впринципе"?
          Ответить
    • а все таки человека, придумавшего преподавать школьникам плюсы -- надо четвертовать

      сначала надо человека сям научить и процедруному подходу
      потом грузить неокрепший мозг темплейтами
      Ответить
      • А в задании и не написано про темплэйты. Если школьник изъебывается с тем, что не знает и не давали, это вина препода?
        Кстати, и не школьник это писал -- это ответ на его просьбу. Так что школота в этот раз только свою лень показала.
        Ответить
    • Плюсанул сабж! Но вовсе не потому что говнокод, как раз наоборот - это достойно жить!
      Вычисления в компайл-тайме - уважаю!

      ЗЫ: любопытно, примут ли работу у того школьника?
      Ответить
      • примут, если сможет объяснить
        Ответить
        • Это такой хитрый отрицательный ответ.
          Ответить
          • Ну почему же. Вероятность есть.
            Ответить
            • Ага, конечно.
              Ответить
              • Может он с философского фак-та, загрузит препода, мама не горюй :)
                Ответить
                • Проблема в том, что программирование на философском факультете преподаёт не философ, а человек с киберфака или мехмата. И на философию у него должен быть иммунитет.
                  Ответить
                  • Артефакт учебник математики: +5 резист к философии. :)
                    Ответить
    • этот код не всегда будет компайл таймом... чтоб был компайлтаймом надо заменить инты на enum'ы... вот так

      enum
      {
      count = Solution<n / 10>::count + 1,
      sum = Solution<n / 10>::sum + n % 10,
      last = n % 10,
      first = Solution<n / 10>::first,
      };

      компилятор может забить на разворачивание интов и тупо вставить код который их вычисляет...
      Ответить
      • Компилятор "Некрофил+"?)) Просто что-то я не застал компилятора, который считает константы.
        Ответить
        • буквально на днях где-то в блогах читал что МС компилятор для флоатов разворачивает только двойную вложенность констант, для тройной уже вставляет код вычисления...
          в гсс с такой проблемой сталкивался сам год назад, в жизни до main были неинициализированные константы...
          Ответить
      • Не может, вообще не может. Шаблоны разворачиваются 100% во время компиляции и никак иначе.
        Ответить
        • я сталкивался с ситауцией когда генерился код вычисления, мне это стоило нескольких часов отладки...
          Ответить
          • Значит было разыменование переменной или что-нить подобное.
            Ответить
          • Выражение в студию.
            Ответить
            • чуть ниже я описал ситуацию...

              приведу псевдокод еще раз
              // c1.cpp
              const int& some_val_ref = Some_template<param>::value;

              // c2.cpp
              extern const int& some_val_ref;
              некоторый класс в жизни до main обращался к этой переменной и получал в ответ 0, при этом в main этот же код читал правильное значение...
              Ответить
              • Это не имеет никакого отношения к static const int some_val = constexpr.
                Ответить
                • я не разбирался где именно проблема... я лишь вынес урок что const int не всегда компайл тайм переменная в отличии от enum{ some_const }; которая в случае невозможности вычисления в компайл тайм, выдаст ошибку компиляции...
                  Ответить
      • const засунет только в том случае в код, если на него заюзать const_cast, а так останется констатой и не полезет в рантайм, таков уж стандарт.
        Ответить
        • я использовал ссылку на эту переменную... до определенного момента из переменной читался 0, потом оказалось что она просто вычислялась позже чем я ее пытался читать... компилятор GCC 4.0 из iPhone SDK
          Ответить
          • Ну это тоже говнокодовость, нафига ссылку давать на POD тип? Очень сильно попахивает. При условии, что передача POD типов очень хорошо оптимизируется, ну а так же ссылка приводит к разыменованию переменной, что и привело к тому, что переменная покинула пределы compile-time.
            Ответить
            • одна из библиотек для линковки требовала несколько констант, которые она принимала по ссылке, типа так
              extern const int& use_some;
              extern const bool& enable_something;
              Ответить
              • Ну вот это жесть, хотя для objective c это может и в порядке вещей. Я бы пальцы вырвал такому разработчику, кто придумал передавать так данные в либу)))
                Ответить
                • это не обжектив С, это код одной старой игры которую я портировал на iPhone...
                  Ответить
      • >static const int
        В стандарте до С++0х не с компилируется.
        По крайней мере майкрософсткий компилятор до 2010 студии это делать не будет.
        Ответить
        • Это Вы сейчас про какую строку?
          Инициализация статических интегральных типов возможна внутри класса.
          Ответить
          • >Это Вы сейчас про какую строку?
            Например:
            static const int count = Solution<n / 10>::count + 1
            Ответить
            • Половина шаблонных библиотек использует этот приём.
              Ответить
              • >Половина шаблонных библиотек использует этот приём.
                Зато другая и более надёжная половина библиотек использует заместо этого приёма enum.
                Ответить
          • >Инициализация статических интегральных типов возможна внутри класса.
            Конечно, только не во всех компиляторах. Например майкрософстская 2008 студия - сольёт.
            Ответить
            • VS 2008:
              class A
              {
              public:
              	const static int a = 20;
              };

              работает
              Ответить
              • Странно. Может обновления какие накачены на студию?
                И при зависимости от шаблона тоже работает?
                Ответить
                • Работает и от шаблона. Версия 9.0.30729.1 SP. Т.е. сервис пак 1 установлен.
                  Ответить
              • Ок. Спасибо.
                Ответить
        • По крайней мере со стандарта C++98 и компилится и повсеместно используется. Вот раньше вроде были проблемы кое-где.
          Ответить
    • А школьник потом не начал орать, что 1024 больше 100?
      Ответить
    • не понял смысла в макросе DECLARE_ONE_DIGIT_SOLUTION. Без него все делается шаблонами отлично.
      Ответить
      • Во-во. Я думал, я чего-то не понимаю.
        Ответить
      • Разверните шаблон вручную - он уйдет в рекурсию без этих макросов.
        Ответить
        • Я все понимаю, но временами надо головой подумать, а не чем-нить другим, есть и другие решения без такого изврата.
          Ответить
    • если объявлять константы через const int то где то в СPP файле нельзя будет сделать так
      int array[Solution<10>::count];
      метод с enum лишен этого недостатка...
      Ответить
      • С чего бы это?
        Ответить
        • незнаю, но такая проблема есть...
          Ответить
          • Со времён Borland C++ 3.1 for DOS с таким не сталкивался.
            Ответить
            • эта проблема есть либо в vc2008 либо в GCC 4.0 - 4.2
              Ответить
              • Код в студию.

                Интересно, и как STL, а тем более Boost, где такое применяется в шерсть и в гриву, чувствуют себя на таких компиляторах?
                Ответить
                • В STL и BOOST больше везде используется enum.
                  Ответить
                  • $ grep -rw 'static const int' /usr/include/c++/4.4.3/ | wc -l
                    161
                    $ grep -rw 'static const bool' /usr/include/c++/4.4.3/ | wc -l
                    280
                    $ grep -rw enum /usr/include/c++/4.4.3/ | wc -l
                    172

                    Но немалая часть enum употреблена по делу, для перечислений, или в комментариях.
                    Ответить
                    • Не доказательство. Возможно во всех этих static const int нет инициализации в определении класса.
                      То есть в большинстве случаев может быть:
                      static const int p;
                      ,а не:
                      static const int p=5;
                      Ответить
                      • Все с инициализацией.
                        Ответить
                        • Может быть с такой:
                          //class.h:
                          class CLASS
                          {
                            static const int p;
                          };
                           
                          
                          //class.cpp:
                          const int CLASS::p=5;
                          ,а не с такой:
                          //class.h:
                          class CLASS
                          {
                            static const int p=5;
                          };
                          ?
                          Ответить
                          • Вы не поверите, но в /usr/include/c++/4.4.3/ -- только хидеры.

                            Да что я тут грепом машу -- см. 9.4.2.
                            Ответить
                            • Надо мне глянуть на STL из MS VS. По моему там конструкций в определениях классов, вида static const * = *; нет. Только через enum.
                              Жалко MS VS дома не стоит...
                              Ответить
                            • Кстати, для чего пишете ваткомом? Думал, его пик популярности прошёл...
                              Ответить
                • да, в 2008 студии такой проблемы нет... чуть позже проверю GCC...
                  Ответить
    • а почему плюсуют? нормальный же код...
      Ответить
      • Не доступно.
        Ответить
      • Довольно забавно и сурово.
        Ответить
      • а это так принято заворачивать жесткие выражения в препроцессор?
        Ответить
        • если что-то можно сделать в компайл тайме, это нужно сделать именно там...
          Ответить
          • а потом основная прога похожа на брейнфак
            Ответить
            • не похожа... паскалисты считают что от обилия скобочек и уголков она даже выглядит круче...
              Ответить
              • (((скобочки (любить "скобочки") "скобочки" "скобочки") ((ебать скобочки) (скобочки)) (скобочки)))
                Ответить
          • показать все, что скрытодрайверописатель детектед
            Ответить
            • я игры пишу...
              Ответить
              • да, тогда ок)
                там действительно допустимо превратить код в кусок говна ради скорости
                Ответить
                • Угу, как раз недавно играл в такую. Если персонаж на рассвете посмотрит вправо и немного вверх, игра превращается в слайд-шоу. По прошествию 3 патчей - не исправлено.
                  Ответить
                  • думаете, пушков писал?
                    Ответить
                    • все они одинаковые, до дедлайна говнокодят, после - не рефакторят
                      Ответить
                      • а в геймдеве это не важно уже

                        там надо к кристмасу выпустить
                        Ответить
                      • это правда... и это печально...
                        только говнокодят обычно в ноч перед дедлайном, а потом живут по принципу "работает - не трогай"...
                        обидно, что можно жить по другому, но в это мало кто верит...
                        Ответить
                  • тут явно не в коде дело... где-то затесался жЫрный меш...
                    Ответить
                    • а бывает что какое-нибудь животне с дифферентом на нос бороздит поверхность холма, так что только хвост наружу торчит
                      тоже явно не в коде дело :-D
                      Ответить
                      • Тоже, бывает, что не в коде дело, а аниматор не верно указал boundary box меша или прочие параметры объекта.
                        Ответить
                        • не, чаще всего они выравниваются и резво норовят засмотревшегося PC схватить за жопу
                          Ответить
                      • в геймдеве очень много data driven кода, и иные подходы считаются очень говнокодными.
                        время программистов дороже времени геймдизайнеров и артистов, поэтому все стараются выносить из кода в данные...
                        отсюда любовь ко всяким луа, хмл, и тп...
                        Ответить
                        • желание описывать данные декларативно -- совершенно логичное
                          в хорошем энтерпрайзе тоже есть DSL
                          Ответить
                • Особенно ради её уменьшения.
                  Ответить
                • Извини, сарказм?
                  Ответить
        • Шаблон тут только для сокращения копипасты.
          Ответить
    • static const int заменить на enum и
      нужна специализация только для нуля. потом last и надо выкинуть из шаблона first. вместо него ввести степень 10.
      template<const size_t n>
      struct solution {
        enum { count = solution<n / 10>::count + 1 };
        enum { sum = solution<n / 10>::sum + n % 10 };
        enum { power_10 = solution<n / 10>::power_10 * 10 };
      };
      
      template<>
      struct solution<0> {
        enum { count = 1 };
        enum { sum = 0 };
        enum { power_10 = 1 };
      };
      
        std::cout << "Number of digits: " << solution<number>::count << std::endl;
        std::cout << "Sum: " << solution<number>::sum << std::endl;
        std::cout << "Last digit: " << number % 10 << std::endl;
        std::cout << "First digit: " << (10 * number) / solution<number>::power_10 << std::endl;
      Ответить
      • Верно, специализация для 10 цифр понадобилась из-за first. Ваш вариант не работает для очень больших чисел (возможно переполнение в 10 * number) -- следует использовать number / solution<number/10>::power_10.

        Ну и использовать enum вместо static const int не нужно.
        Ответить
      • Вместо енамов, кстати, можно использовать BOOST_STATIC_CONSTANT и будет кроссплатформенность
        Ответить
    • очень даже приличный код.
      Ответить

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