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

    +997

    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
    43. 43
    44. 44
    45. 45
    46. 46
    47. 47
    48. 48
    49. 49
    50. 50
    51. 51
    52. 52
    53. 53
    54. 54
    55. 55
    56. 56
    57. 57
    58. 58
    59. 59
    60. 60
    61. 61
    62. 62
    63. 63
    64. 64
    65. 65
    66. 66
    67. 67
    68. 68
    69. 69
    70. 70
    71. 71
    72. 72
    73. 73
    74. 74
    75. 75
    76. 76
    77. 77
    78. 78
    79. 79
    80. 80
    81. 81
    82. 82
    class fileOutBuf : public streambuf
    {
    public:
        // ...
        typedef char        char_type;
        typedef int         int_type;
        typedef int         streamsize;
        // ...
        int printf( const char * fpFormat, ... );
    
        inline int vprintf( const char * fpFormat, va_list fvaList )
        {
            if ( NULL != dpFileDescriptor )
            {
                if ( true == sdVerboseFlag  && false == dSkipVerboseOutput)
                    vfprintf( dpVerboseFileDescriptor, fpFormat, fvaList );
    
                return vfprintf( dpFileDescriptor, fpFormat, fvaList );
            }
            else
            {
                if ( NULL != dpOutputFuncPtr )
                    return (*dpOutputFuncPtr)( fpFormat, fvaList );
            }
            return 0;
        }
        // ....
        virtual int_type overflow( int_type c = EOF );
        virtual streamsize xsputn( const char_type *s, streamsize n );
        // ....
    };
    
    int fileOutBuf::printf( const char * fpFormat, ... )
    {
        va_list lvaList;
        int lRet;
    
        va_start( lvaList, fpFormat );
    
        if ( NULL != dpFileDescriptor )
        {
            if ( true == sdVerboseFlag  && false == dSkipVerboseOutput)
                vfprintf( dpVerboseFileDescriptor, fpFormat, lvaList );
    
            lRet = vfprintf( dpFileDescriptor, fpFormat, lvaList );
        }
        else
        {
            if ( NULL != dpOutputFuncPtr )
                lRet = (*dpOutputFuncPtr)( fpFormat, lvaList );
        }
    
        va_end( lvaList );
    
        return lRet;
    }
    
    fileOutBuf::int_type fileOutBuf::overflow( int_type c )
    {
        if ( NULL != dpFileDescriptor )
        {
            if ( true == sdVerboseFlag  && false == dSkipVerboseOutput)
                fputc( c, dpVerboseFileDescriptor );
    
            return fputc( c, dpFileDescriptor );
        }
        else
            return fileOutBuf::printf( "%c", c );
    }
    
    fileOutBuf::streamsize fileOutBuf::xsputn( const fileOutBuf::char_type *s, fileOutBuf::streamsize n )
    {
        if ( NULL != dpFileDescriptor )
        {
            if ( true == sdVerboseFlag  && false == dSkipVerboseOutput)
                fwrite( s, sizeof( char_type ), n, dpVerboseFileDescriptor );
    
            return fwrite( s, sizeof( char_type ), n, dpFileDescriptor );
        }
        else
            return fileOutBuf::printf( "%*s", n, s );
    }

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

    ЗЫ после удаления всей капипасты, от класа в целом осталось что-то около 50 строк.

    Запостил: Dummy00001, 06 Декабря 2011

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

    • показать все, что скрытоКГ / АМ
      Ответить
    • только вот в с++ полезность v*printf стремится к нулю
      Ответить
      • >в с++ полезность v*printf стремится к нулю
        Это почему это?
        Ответить
        • Так, чё скажешь, defecate-plusplus? Мы говна ждем твоего коммента.
          Ответить
          • 1) va_list не работает с аргументами по ссылке и некоторыми другими - UB (т.е. под гцц работает, под студией - нет)
            2) v*printf не проверяет типы и число аргументов - легко уронить приложение и даже не понять почему - при этом, учитывая распространенность сишкопроблемы, g++ имеет -Wformat и ругается на аргументы printf, но не vprintf
            3) под студией поддержка сишкоблядского старья никчемная (ненужно), что приводит к невозможности точного определения через vs*printf размера результирующей строки

            http://ideone.com/luoI8

            так устроит?
            Ответить
            • >1) va_list не работает с аргументами по ссылке и некоторыми другими - UB
              А стандарт что на эту тему говорит?
              Ответить
              • c++03
                18 Language support library
                18.7 Other runtime support
                3. The restrictions that ISO C places on the second parameter to the va_start() macro in header
                <stdarg.h> are different in this International Standard. The parameter parmN is the identifier of the
                rightmost parameter in the variable parameter list of the function definition (the one just before the ...).
                If the parameter parmN is declared with a function, array, or reference type, or with a type that is not com-
                patible with the type that results when passing an argument for which there is no parameter, the behavior is
                undefined.

                SEE ALSO: ISO C subclause 4.8.1.1.
                Ответить
            • Кстати пишут, что иногда va_end вызывать не нужно.
              Особенно если отправил данные в v*printf

              В каких случаях его все же нужно вызывать и для чего он реально служит? Да и жаль RAII тут никак не поможет...
              Ответить
              • я эти va_ использую один раз в жизни, чтобы на уютненьком посрать, поэтому нюансы мне мало интересны
                объяснение простое - ненужно
                Ответить
              • Стандарт C89 и личный опыт подсказывают, что Each invocation of the va_start and va_copy macros shall be matched by a corresponding invocation of the va_end macro in the same function.

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

                Отправка данных в v*printf не освобождает от ответственности, т.к. The vprintf function does not invoke the va_end macro.

                Можно ссылочку, где пишут что не нужно вызывать va_end?
                Ответить
            • ># if !defined _MSC_VER
              Способность вести компиляторозависимую стрельбу в ноги конечно поражает.

              >char tmp[1024]; // sorry if your string can be > 1023 chars - shit for msvc
              А что мсвц сделает?
              Только ты в коде ошибку допустил. Если стринги больше > 1023, то ноль в последний байт не запишется. Нужно было вручную его записать.
              Ответить
              • конкретно этот говнокод при стринге больше 1024 вернет -1 и соотв. эксепшен
                при стринге равном размеру буфера (1024) мелкомягкая реализация его заполняет целиком и возвращает 1024
                это 1024 потом уйдет в конструктор std::string и всё что нужно будет на месте
                Ответить
            • >va_list не работает с аргументами по ссылке
              А я то думал, почему у меня лаба (вроде в мсвц 6ке) не работала! У всех работало, а у меня нет. Я уж начал думать, что это я идиот. Оно и понятно, никто вокруг меня и не знал про существование ссылок...
              Ответить
            • Если уж на то пошло, то самый правильный printf в Nemerle:
              http://ideone.com/smICJ
              http://ideone.com/pLBql
              http://ideone.com/jjiYN
              http://ideone.com/wdfGC
              Ответить
              • "Михал Москаль — лидер команды и автор системы вывода типов..."
                вот так вот, не повезло один раз с фамилией - и ты изгой, компьютер твой лучший друг и всю жизнь за доширак тратишь на говно
                а был бы Кржыжщек - воспользовался преимуществами евросоюза, исправно работал бы как все сантехником, и не тратил всю жизнь на говн... oh wait...
                Ответить
                • И зачем это здесь? Я был о вас лучшего мнения.
                  Ответить
                  • что, говнокод уже не место для набросов?
                    Ответить
                    • Поставил минус в карму.
                      Ответить
                    • Неудачный наброс если честно, с переходом на личности людей, не сделавших вам ничего плохого.

                      P.S. А вот против набросов на неодушевленные сущности (языки, софт и т.п.), и наездов на присутствующих здесь (включая меня) ничего не имею.
                      Ответить
                      • >А вот против набросов на неодушевленные сущности (языки, софт и т.п.)
                        >языки
                        Вы мне конечно не поверите, но я тоже. :)
                        Ответить
                • >вот так вот, не повезло один раз с фамилией - и ты изгой, компьютер твой лучший друг и всю жизнь за доширак тратишь на говно

                  А с чего вы решили, что он питается дошираками? С чего вы решили, что он сейчас никто? Почему вы решили, что учавствование в разработки передового инновационного компилятора - это трата жизни на говно?

                  Это одна из самых сильных, но пока недооцененых, разработок среди языков и компиляторов. Возможностей его уровня нет ещё ни в одном языке. Даже Хаскелл стоит в стороне из-за его излишней узкоспециализированности, теоретизироанности и отсутствия важнейщих мейнстримовых возможностей.

                  PS: Это я вам говорю, который на языки всегда огрызается. Это что то, да значит.
                  Ответить
                  • > Возможностей его уровня нет ещё ни в одном языке
                    может там и мультиметоды есть
                    Ответить
                    • Тебе в лисп, а вообще в говноформе это есть даже в крестах.
                      Элсо, мультиметоды на .Нет языках очень просто реализуются через dynamic. Насчет dynamic в Немерле пока не знаю, возможно ещё не готов.
                      Ответить
                      • На самом деле есть одна красивая форма мультиметода в крестах, хоть и костыльная и только на 2 объекта макимум. См одну из перегрузок boost::apply_visitor. Красивее и проще пока не видел.

                        Элсо хватит троллить, в немерле мультиметоды легко эмулируются через паттерн матчинг.
                        Ответить
                        • Элсо в немерле способностей метапрограммирования хватит, чтобы написать аналог boost::apply_visitor на произвольное кол-во аргументов и более удобный, более безопасный и более гибкий.
                          Ответить
                          • Кстати зря смеёшься, Scala - это недоразвитая сестра Nemerle.
                            ps: Я роман тик и ухожу в сторону заката минуса.
                            Ответить
                          • Ты будешь визжать как девчёнка, когда индусы начнуть писать на Nemerle код, который тебе нужно будет поддерживать.
                            Ответить
                            • Ты так говоришь, как будто из-за того, что на меня могут напасть Америкосы, мне не нужно изобретать танк, в то время как уже есть мечи и они безопаснее, когда америкосы на меня все-таки нападут. Или по тойже причине не изобретать мирный атом.

                              Знаешь, что я тебе скажу? Ты консерватор (кстати один из самых передовых и продвинутых у нас на говнокоде).
                              Ответить
                        • > Элсо хватит троллить
                          Сложно удержаться. Всё так брызжут интузиазмом, когда вещают о Nemerle, хотя лично я ничего принципиально нового не увидел. Да, изящное сочетание ООП и метапрограммирования. Да, хороший вывод типов (судя по примерам, таки лучше, чем в Scala, хоть мне и не в лом лишний раз тип указать).
                          Всё это уже было в лиспе 30 лет назад.

                          Кстати, по поводу лиспов: кто-нибудь пробовал Racket? С виду вроде годная штука, стоит вообще смотреть?
                          Ответить
                          • >Всё это уже было в лиспе 30 лет назад.
                            Не было, ибо там не было статической типизации. Это совсем другой уровень гигиены макросов. Ну и понятно самый передовой вывод типов на данный момент среди языков в немерле.

                            >Кстати, по поводу лиспов: кто-нибудь пробовал Racket?
                            Только его и пробовал. Сравнить с другими не могу. Мне понравилось. А именно Scheme r5rs. Элсо ракетка много диалектов лиспа из коробки поддерживает.

                            >вывод типов (судя по примерам, таки лучше, чем в Scala
                            Самый слабый вывод типов среди функциональных языков.

                            >Да, изящное сочетание ООП и метапрограммирования.
                            Так вот высокая степень метапрограммирования позволяет иметь "песочницу для игры в куличики" больше чем в С++, но без костылей. Высочайший уровень создания DSL времени компияции, например антиинъекционная типобезопасная работа с бд (не очень понятно пока не попробуешь), ФП, ООП, АОП, ЛП, чистота местами, лень, declarative query, асинхронное программирование и Computation Expressions, генератор парсеров. Притом все это не через какието костыли, а реализовано в стандартной библиотеке макросами. Притом все очень легкое в обращении, не как в с++ - ошибка в шблонах - одевай говнолазный костюм и погружайся в пучины библиотеки шаблонов для выяснения обстоятельств. Банально тебе выдадут внятное сообщение об ошибке и ты сразу исправишь. Быстрая компиляция. Интеграция на высоте. Тот же гератор парсеров - написал граматику - везде где ошибся тебе красным до компиляции подчеркнули и ты сразу поравил, подведя мышкой к крассному подчеркиванию с последующим popup сообщения. Даже типы в обработтчиках генератора граматик проверяются, что для внешних костыльных утилит обычно нонсенс (для немерле они понятно не нужны). Все типы в коде видны под мышью. Даже формошлепа есть.
                            Ответить
                            • > там не было статической типизации
                              потому мой текст зелёный

                              У меня на самом деле тоже много претензий к современным языкам. К Scala, в частности. Например, удручает скорость компиляции (maven, например, не может в fsc) и потребление памяти (тот же Haskell кушает значительно меньше памяти и компилится заметно быстрее). С IDE тоже проблемы есть.

                              Common Lisp - мамонт, по нагромождённости и количеству ньюансов напоминающий c++. Инфраструктура очень мутная. Если с cabal разобраться довольно просто (и пользоваться им довольно удобно), то asdf на раз вызвает баттхёрт.

                              Лисперы вообще мне люто доставляют. Читаю на досуге руководство к emacs, ловлю лулзы. К примеру, там есть календарь, вычисляющий лунные фазы и время восхода/захода солнца, а также экспорт дат Грегорианского календаря в календари Майя и ещё 10 других, один другого древней.
                              Однако путный режим нумерации строк в буфере появился относительно недавно. Опять же, визуально отображать выделения прямоугольника (Ctrl-v в vim) даже последний emacs просто не может. Можно найти плагин, но и там нужно немного геммора.
                              Ответить
                              • Календарь Майа это же интересно и забавно, а кодить нумерацию строк это рутина и скукота. Вот и не пилят годами.
                                Ответить
                                • Вон в Nemerle своя система вывода типов (доку по ней уже скачал), в F# и младше - X-M.
                                  А какая система вывода типов в Хаскеле, чтобы про неё прочитать? System F? (Или я не в ту степь?)
                                  Ответить
                                  • В Хацкеле - Х.-М.
                                    Для функциональщины без богомерзкого ООП - самое оно.
                                    Ответить
                              • Мне Scala понравилась тем, что у неё вывод типов более предсказуемый, чем у Nemerle или даже у ML-группы языков в целом. Ты более или менее сразу знаешь где нужно уточнить тип, чтобы понять в каком месте кода ты допустил ошибку или в каком месте скала не смогла вывести тип. Конечно в Немерле необходимость уточнять типы чтобы все скомпилировалось почти отсутствует. Но вот чтобы найти место ошибки - это бывает не просто (забыл например из тупла где-то извлечь). Бывает указывает на совсем другую точку в коде. К этому нужно или привыкнуть или пользоваться очень мощным выводом типов с осторожностью. Я на пример пока ещё не привык и делаю так: Юзаю полный вывод типов, но как только закодил какуюто функцию недостаточно внимательно и получаю не понятную для моего текущего уровня ошибку - банально проставляю в её параметрах типы (иногда ещё где-то) и все становиться на свои места и я твердо вижу место ошибки (Например извлечь забыл из кортежа). Благо компилировать код из-за хорошей интеграции не нужно и все ошибки подчеркиваются сразу и видны при подводе мышью. Ну и как исправил - убираю проставленные типы. Хотя это конечно я делаю глуповато...

                                В скале мне очень понравились примитивы/паттерны (или что это?) синхронизации и многопоточной работы. Говорят увидев их, ими даже Интел заинтересовалась.
                                Ответить
                                • Ещё в немерле в режиме без скобок иногда скобки в многострочных лямбдах всеже указывать приходиться... Бага компилятора и исправлять её похоже никто не собирается, тк мл-подобная индентация не очень модна. Ну и отсутствие возможности типов для обобщенных функций - это не приятно. Немерле то конечно все выведет, но в отличии хаскела или ОСамл и младше (F# таккой же как немерле в этом плане) - придется указать, что функция не конкретная, а обобщённая. Но и это понятно почему, тк F# и Nemerle на базе .NET, а там своя система типов, поэтому typeclasses нет. Ну и понятно, ситуация намного сложнее, чем во всех этих языках (типа хаскела или ОКамл), тк есть перегрузка функций. А в Nemerle ещё и неявные преобразования, типа повышения типов и тд.

                                  Так о чем это я? Что-то мы отошли от темы. Conclusion: NemerleGovno.
                                  Ответить
                                • > В скале мне очень понравились примитивы/паттерны (или что это?) синхронизации и многопоточной работы.

                                  Это ты о чём? Может, я что пропустил? Там из коробки вроде только акторы идут, stm отдельно в akka вместе с продвинутыми акторами.
                                  Ответить
                                  • Scala многопоточное программирование:
                                    См. Глава 15
                                    Абстракции для многопоточности

                                    http://ru.wikibooks.org/wiki/Scala_в_примерах

                                    Не то чтобы мне сильно понравилось, но например вот это.
                                    Ответить
                              • Common Lisp — мой родственник?
                                Ответить
              • Кстати на с++11 можно реализовать правильный printf через variadic templates.
                Ответить
                • Былобы интересно взглянуть хотябы на сырую наброску простейшего safePrintf, например на
                  http://liveworkspace.org/
                  Поддерживает как variadic templates, так и constexpr, так и boost.
                  Таки я бы даже если это реализовывал, то протащил бы в буст, а потом и в стандарт.

                  Это будет как выглядеть?
                  Как то так?
                  printf<'Hell', 'o %s', '!, %d'>("World", 1000);
                  , как это было в boost::mpl::string?
                  Можно попробовать через constexpr + vt, но внутри реализации это будет выглядеть как будто влазишь на скалу без альпинистского снаряжения.
                  Ответить
                  • С проверкой типов в рантайме - совсем несложно. Пачка специализаций под разные типы, каждая из которых умеет вываливать куски строк, и только свой %, кидая экцепшн при некорректном типе, затем рекурсивный вызов с оставшимися аргументами.

                    С проверкой типа во время компиляции - а оно надо? Есть же стримы.
                    Ответить
                    • >Есть же стримы.
                      Они плохо локализуемы, плохо читабильны, да и вообще громоздки, да и темболее не проверяют типы. А в принтфе указал ты, что нужен %d и он придет. Это как джавды два. Как говорил Тарас, с оглядкой на Аду, лишняя проверка никогда не бывает лишней.

                      >С проверкой типов в рантайме - совсем несложно.
                      Менее компиляторопереносимый велосипед через vt? Не нужен. Более переносимый уже реализован в boost::format.

                      >С проверкой типа во время компиляции - а оно надо?
                      Крестушки, как и линуксоиды, очень любят говорить: У нас нет, поэтому оно никому не нужно. Гнилая философия я вам скажу.
                      Ответить
                    • >С проверкой типа во время компиляции - а оно надо?
                      Это как с динамически типизированными языками. Вот почему появились статически типизированные языки? Именно чтобы не тратить время: не писать лишних тестов и избежать лишних отладок. Жаль будет, если после последней поспешно слепленной срочной заплатки что-то сработает не так у заказчика.

                      printf мне, как закоренелому сишнику, больше нравиться своей крткостью, естественностью, простотой и легкостью локализации.
                      Ответить
    • Где копипаста?
      Ответить
    • показать все, что скрытоvanished
      Ответить

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