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

    +6

    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
    83. 83
    84. 84
    85. 85
    86. 86
    87. 87
    88. 88
    89. 89
    90. 90
    91. 91
    92. 92
    #include <iostream>
    #include <conio.h>
    #include <clocale>
    using namespace std;
    int files; int disc_D(); int disc_E(); int disc_C();
    int resursefunction()
    {char s;
      cout << "Выберите диск" << endl;
      cout <<"1-D:\\" << endl;
      cout <<"2-C:\\" << endl;
      cout <<"3-E:\\" << endl;
      cout <<"0 - рабочий стол" << endl;
      cin >> s;
      if(s == '1') return disc_D();
      if(s == '2') return disc_C();
      if(s == '3') return disc_E();
      if(s == '0') return main();
      _getch();}
    int main()
    { char vibor;
      setlocale( LC_ALL, "Russian" );
      cout << "\t\t\t\tРабочий стол" << endl;
      cout << "\n\n";
      cout << "1-Управление ресурсами" << endl;
      cout << "2-Программы" << endl;
      cout << "3-Игры" << endl;
      cout << "4-Выход из системы" << endl;
      cin >> vibor;
      if(vibor == '1') resursefunction();
      _getch();
      return main();}
    int disc_D()
    { int res, a;
      char vv;
      cout << "D:\\" << endl;
      cout << "На диске" << endl;
      cout << "5 - папок" << endl;
      cout << files << " - файлов" << endl;
      cout << "1 - создать файл" << endl;
      cout << "2 - удалить файл" << endl;
      cout << "0 - назад" << endl;
      cin >> vv;
      if(vv == '1')
      {cout << "Введите сколько создать файлов"; cin >> a; res = files + a;
       res = files + a;}
      if(vv == '2')
      {cout << "Введите сколько удалить файлов"; cin >> a; res = files - a;
       res = files - a;}
      if(vv == '0') return resursefunction();
      files = res;
      return disc_D();}
    int disc_E()
    {
      int res, a;
      char vv;
      cout << "E:\\" << endl;
      cout << "На диске" << endl;
      cout << "7 - папок" << endl;
      cout << files << " - файлов" << endl;
      cout << "1 - создать файл" << endl;
      cout << "2 - удалить файл" << endl;
      cout << "0 - назад" << endl;
      cin >> vv;
      if(vv = '1')
      {cout << "Введите сколько создать файлов"; cin >> a; res = files + a;
       res = files + a;}
      if(vv == '2')
      {cout << "Введите сколько удалить файлов"; cin >> a; res = files - a;
       res = files - a;}
      if(vv == '0') return resursefunction();
      files = res;
      return disc_E();}
    int disc_C()
    {int res, a;
      char vv;
      cout << "C:\\" << endl;
      cout << "На диске" << endl;
      cout << "5 - папок" << endl;
      cout << files << " - файлов" << endl;
      cout << "1 - создать файл" << endl;
      cout << "2 - удалить файл" << endl;
      cout << "0 - назад" << endl;
      cin >> vv;
      if(vv = '1')
      {cout << "Введите сколько создать файлов"; cin >> a; res = files + a;
       res = files + a;}
      if(vv == '2')
      { cout << "Введите сколько удалить файлов"; cin >> a; res = files - a;
       res = files - a; }
      if(vv == '0') return resursefunction();
      files = res;
      return disc_C();}

    Еще нашел на форумах. К сожалению форматирование пришлось убить, иначе оно не помещалось целиком

    Запостил: pelmenka, 23 Декабря 2013

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

    • Саспенс! Никогда не знаешь, сколько ещё можно поработать с программой пока она не свалилась с переполнением стека!

      И подключать conio.h только из-за _getch() — говноедство
      Ответить
      • А что, функциональненько. Цикл через хвостовую рекурсию.

        На гцц не должно вылететь, он умел в tail-call optimisation.
        Ответить
        • > На гцц не должно вылететь
          Только с включенной оптимизацией.
          Ответить
          • А зачем выключать оптимизацию, ну кроме отладки?
            Ответить
            • Ну конечно. Пускай в отладке падает. Не в релизе же.
              Ответить
            • Логика работы программы, зависящая от ключей оптимизации, — это так по-царски...
              Ответить
              • К сожалению есть случаи, когда иначе никак:
                /* disable system clock prescaler */
                CLKPR = 1 << CLKPCE;
                CLKPR = 0;
                Вот этот простенький код без оптимизации работать не будет. Т.к. вторая запись в регистр CLKPR должна произойти не позже 4 тактов после установки в нем бита CLKPCE, а avr-gcc на -O0 генерит такое дерьмище, что оно не успевает положить 0 за эти 4 такта... Можно, конечно, переписать этот фрагмент на асме, но лень.
                Ответить
      • Ой, да ладно, типичная laba1.cpp же.
        Хотя нет, атипичная, рекурсия всё-таки.
        Ответить
        • Атипичная, это когда оператор , в тернарке.
          Ответить
    • На диске ц всегда 5 папок? ;)
      Ответить
      • Windows, Users, ProgramData, Program Files и Порно
        Ответить
        • "Новая папка" же
          Ответить
        • А как же Program Files (x86)?
          Ответить
          • Да Вы, дяденька, буржуй
            Ответить
            • Че еще доставляет в x86_64 винде, так это папки system:
              system - наследие от 16-битки
              system32 - 64(!) битные файлы
              syswow64 - 32(!) битные файлы
              Ответить
          • А нету. 32-битная система же.
            Ответить
            • Да вы, батенька, ретроград.
              Ответить
              • Ретроград — это тот, кто не признаёт ничего, кроме IBMBIO.SYS+IBMDOS.SYS+COMMAND.COM, ну и в крайнем случае директории DOS.
                Ответить
                • > IBMBIO.SYS+IBMDOS.SYS
                  А я вот их кроме как в книжке Нортона (или кого там) только видел. Мне уже достались только io.sys и msdos.sys в моем досе. Правда что в IBMBIO.SYS была большая часть того что сейчас в BIOS?
                  Ответить
                  • Все лгут. Это всего лишь фирменное название того же файла:
                    io.sys = ibmbio.sys = drbio.sys = ptsbio.sys = rombio.sys
                    msdos.sys = ibmdos.sys = drdos.sys = ptsdos.sys = romdos.sys

                    Предназначено для разжигания холиваров на тему, DOS какого производителя круче. Кстати, в MS-DOS 7.x-8.x, который встроен в Windows 95/98/Me всего один файл IO.SYS, а в Free DOS — только KERNEL.SYS, а второй (msdos.sys) разжалован за ненадобностью.
                    Ответить
        • Кто ж порно на Ц хранит? Придёт время переустановить виндовс, и всё, что нажито непосильным трудом, будет потеряно...
          Ответить
          • > Придёт время переустановить виндовс, и всё, что нажито непосильным трудом, будет потеряно...
            Зачем при этом форматировать диск? Достаточно же с любого Живого Компактного Диска просто удалить windows/program files и т.п.
            Ответить
            • Порно должно быть "летучим". Не нужно хранить порно поколениями. Нужно иметь папку, для временного хранения порно. Но сама папка должна быть постоянной
              Ответить
              • > поколениями
                И передавать по наследству от отца к сыну.
                Ответить
                • Сексуальные девиации передаются же
                  Ответить
                • «И сам же с ним посмотрю» © Lure of Chaos (http://habrahabr.ru/post/196270/#comment_6810230)
                  Ответить
            • > Зачем при этом форматировать диск?
              А вообще, эта традиция пошла из-за засранности диска и вирусов? Или из-за "халявной дефрагментации"?
              Ответить
              • Имхо, из-за того, что в те времена не было адекватных live cd. Удалить лишние папки было просто нечем...

                Ну я вот грузился с dos'овской дискетки, переименовывал windows, program files, docs & settings, затем ставил винду, и уже из винды выносил из тех папок лишнее... Но кому хотелось так извращаться? Вот и форматировали все к хуям.
                Ответить
                • В какие времена? У меня в начале 2000х был зарузочный CD в дос.
                  Ответить
                  • Ну вот эти досовские CD/дискетки, емнип, не могли толком вынести папки винды из-за слишком длинных путей. Поэтому я их и переименовывал.
                    Ответить
                    • А я вот дурак пытался копировать. Больше не пытался)))
                      Ответить
                    • Ну да, потому что переименование в отличие от копирования не глубокое. Все работало, хоть и было не настолько дружелюбным. Хотя сейчас далеко не у каждой Мани есть загрузочный DVD
                      Ответить
    • А вызов main в конце его самого никого не смутил?
      Ответить
      • См. первый коммент от Soul_re@ver. Он как раз об этой рекурсии.
        Ответить
        • Я про сам факт вызова main
          Ответить
          • > Я про, сам фанат вызова main
            Ответить
          • А чем тебе мейн не функция?
            Ответить
          • В сишечке и в крестах main по сути не является элементом языка (в отличие от Паскаля/Модулы/Ады, в которых есть специальные блоки инициализации), это просто функция. Особый статус main имеет только из-за того, что библиотечный модуль, на который нацелена точка входа в исполнимом файле, после инициализации среды вызывает main. Есть даже реализации библиотек, в которых в качестве стартовой вместо main вызывается другая функция.
            Ответить
            • Насколько помню, в стандарте ещё было, что return 0 можно в main опустить, он будет подразумеваться (чего в других функциях делать нельзя).
              Ответить
              • > чего в других функциях делать нельзя
                Можно ;) Ну правда в других функциях 0 не подразумевается, и вернет что-нибудь другое, что под руку попадется. Где-то здесь даже был пример возвращающего правильное значение (при -O2) кода из лабы:
                int bin_search(int min, int max, int val) {
                    int mid = (min+max)/2;
                    if (a[mid] == val)
                        return mid;
                    if (a[mid] < val) {
                        bin_search(mid, max, val);
                    } else {
                        bin_search(mid, max, val);
                    }
                }
                Ответить
                • UB - это "можно"? :)
                  Ответить
                  • А в C89, кстати, main без return'а тоже UB. Причем GCC неплохо его эмулирует. На стандартах повыше возвращается 0, а на C89 именно мусор.

                    Ну и если код никогда не дойдет до этой точки, то UB'а не будет. И некоторым людям нравится (мне не нравится), что кресты и сишка, в отличие от жабы не заставляет дописывать в таких случаях бесполезный return или throw...

                    Эту херню с возвратом 0 из main'а прикрутили в с99 и почему-то в крестах. Я честно не понимаю, зачем это нужно, особенно в крестах. Видимо совместимость с каким-нибудь говном мамонта.
                    Ответить
            • Если я не ошибаюсь можно компилятору любую функцию указать как точку входа. main - это дефолт
              Ответить
              • А стартовая точка это нифига не main(). В винде это WinMain(), в линухе это _start(). Вот эта истинная стартовая точка скрыта в сишной либе, и вызывает main().

                Т.е. ты конечно можешь сказать линкеру, что тебе нужна другая точка входа. Но получится совсем не то, что ты хотел :)
                Ответить
                • А разве нельзя указать, что эта мнимаю точка входа теперь не мейн а другая функция с подходящей сигнатурой?
                  Ответить
                  • Насколько я знаю - нет. Стандартная сишная либа всегда будет вызывать main(). Но ты ведь можешь написать main() и вызвать в нем нужную тебе функцию ;)
                    Ответить
                  • Можно. Но только нужно указывать не компилятору, а менять библиотеку.

                    В gcc вызов main() зашит в модуль crt1.o. Если заменить этот модуль на свой, то можно вызвать функцию с любой сигнатурой, с какой захотим.

                    Вот аналогичный пример из Watcom C (где-то в недрах clib3s.lib есть cmain386.obj):
                    __CMain:
                        push        ebp 
                        mov         ebp,esp 
                        mov         eax,dword ptr FLAT:__ASTACKSIZ 
                        add         eax,3 
                        and         al,0fcH 
                        mov         edx,dword ptr FLAT:__ASTACKSIZ 
                        sub         esp,eax 
                        mov         eax,esp 
                        add         eax,edx 
                        mov         dword ptr FLAT:__ASTACKPTR,eax 
                        call        near ptr FLAT:__CommonInit 
                        mov         eax,dword ptr FLAT:___Argv 
                        push        eax 
                        mov         edx,dword ptr FLAT:___Argc 
                        push        edx 
                        call        near ptr FLAT:main
                        add         esp,8 
                        push        eax 
                        call        near ptr FLAT:exit 
                        add         esp,4 
                        mov         esp,ebp 
                        pop         ebp 
                        ret


                    А вот пример из MSVC (где-то в глубинах libcmt.lib лежит модуль crt0.obj):
                    ___tmainCRTStartup:
                    ... начало отрезал ...
                    X$9:
                        push        0x00000001 
                        call        near ptr j^__cinit 
                        pop         ecx 
                        test        eax,eax 
                        je          X$10 
                        push        eax 
                        call        near ptr j^__amsg_exit 
                        pop         ecx 
                    X$10:
                        mov         eax,dword ptr __environ 
                        mov         dword ptr ___initenv,eax 
                        push        eax 
                        push        dword ptr ___argv 
                        push        dword ptr ___argc 
                        call        near ptr j^_main
                    ... дальше отрезано ...

                    P.S. В Борман Си аналогичный фрагмент в c0x32.obj.
                    Ответить
                • > А стартовая точка это нифига не main(). В винде это WinMain()
                  MS VS:
                  mainCRTStartup (or wmainCRTStartup)
                  WinMainCRTStartup (or wWinMainCRTStartup)
                  or
                  _DllMainCRTStartup
                  Ответить
                  • /ENTRY:function
                    Ответить
                  • Хм, а WinMain тогда, получается, вызывается из WinMainCRTStartup, который находится в либе, прилинковываемой к любой гуишной проге? Я просто не особо в курсе, как там это происходит.
                    Ответить
                    • MSVC 9.0, модуль wincrt0.obj из libcmt.lib:
                      ___tmainCRTStartup:
                      ... какая-то муть с инициализацией всякой хрени ...
                      X$7:
                          call        dword ptr `__imp__GetCommandLineA@0` 
                          mov         dword ptr __acmdln,eax 
                          call        near ptr j^___crtGetEnvironmentStringsA 
                          mov         dword ptr __aenvptr,eax 
                          call        near ptr j^__setargv 
                          test        eax,eax 
                          jge         X$8 
                          push        0x00000008 
                          call        near ptr j^__amsg_exit 
                          pop         ecx 
                      X$8:
                          call        near ptr j^__setenvp 
                          test        eax,eax 
                          jge         X$9 
                          push        0x00000009 
                          call        near ptr j^__amsg_exit 
                          pop         ecx 
                      X$9:
                          push        ebx 
                          call        near ptr j^__cinit 
                          pop         ecx 
                          cmp         eax,esi 
                          je          X$10 
                          push        eax 
                          call        near ptr j^__amsg_exit 
                          pop         ecx 
                      X$10:
                          call        near ptr j^__wincmdln 
                          test        byte ptr -0x3c[ebp],bl 
                          je          X$11 
                          movzx       ecx,word ptr -0x38[ebp] 
                          jmp         X$12 
                      X$11:
                          push        0x0000000a 
                          pop         ecx 
                      X$12:
                          push        ecx 
                          push        eax 
                          push        esi 
                          push        ___ImageBase 
                          call        near ptr j^`_WinMain@16`
                          mov         dword ptr -0x20[ebp],eax 
                          cmp         dword ptr -0x1c[ebp],esi 
                          jne         $LN36 
                          push        eax 
                          call        near ptr j^_exit 
                      $LN36:
                          call        near ptr j^__cexit 
                          mov         dword ptr -0x4[ebp],edi 
                          jmp         X$13 
                      ... дальше какая-то муть с обработкой исключений ...
                      Ответить
                      • > ... какая-то муть с инициализацией всякой хрени ...
                        В основном конструкторы статических объектов.
                        Ответить
                      • Стоп! У меня же исходник есть:
                        /*crt0.c - C runtime initialization routine
                        *
                        *       This is the actual startup routine for apps.  It calls the user's main
                        *       routine [w]main() or [w]WinMain after performing C Run-Time Library
                        *       initialization.
                        */
                        ... пропустил ...
                        /***
                        *mainCRTStartup(void)
                        *wmainCRTStartup(void)
                        *WinMainCRTStartup(void)
                        *wWinMainCRTStartup(void)
                        *
                        *       Function:               User entry called:
                        *       mainCRTStartup          main
                        *       wmainCRTStartup         wmain
                        *       WinMainCRTStartup       WinMain
                        *       wWinMainCRTStartup      wWinMain
                        *
                        */
                        
                        #ifdef _WINMAIN_
                        
                        #ifdef WPRFLAG
                        #define _tmainCRTStartup    wWinMainCRTStartup
                        #else  /* WPRFLAG */
                        #define _tmainCRTStartup    WinMainCRTStartup
                        #endif  /* WPRFLAG */
                        
                        #else  /* _WINMAIN_ */
                        
                        #ifdef WPRFLAG
                        #define _tmainCRTStartup    wmainCRTStartup
                        #else  /* WPRFLAG */
                        #define _tmainCRTStartup    mainCRTStartup
                        #endif  /* WPRFLAG */
                        
                        #endif  /* _WINMAIN_ */
                        ... пропустил ...
                        __declspec(noinline)
                        int
                        __tmainCRTStartup(
                                 void
                                 )
                        {
                        ... пропустил ...
                        #ifdef _WINMAIN_
                                    lpszCommandLine = _twincmdln();
                                    mainret = _tWinMain( (HINSTANCE)&__ImageBase,
                                                         NULL,
                                                         lpszCommandLine,
                                                         StartupInfo.dwFlags & STARTF_USESHOWWINDOW
                                                              ? StartupInfo.wShowWindow
                                                              : SW_SHOWDEFAULT
                                                        );
                        #else  /* _WINMAIN_ */
                                    _tinitenv = _tenviron;
                                    mainret = _tmain(__argc, _targv, _tenviron);
                        #endif  /* _WINMAIN_ */
                        ... пропустил ...
                        }
                        Ответить
    • >> char vibor;

      хорошо что не vizbor
      Ответить

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