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

    −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
    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
    #include <iostream>
    #include <regex>
    #include <strstream>
    double calc(const double& a,const double & b,char op)
    {
        switch(op)
        {
            case '+':
                return a+b;
            case '-':
                return a-b;
            case '/':
                return a/b;
            case '*':
                return a*b;
        }
    }
     
    std::string calc(const std::string & ex )
    {
        double a{},b{};
        char op{};
        std::stringstream str;
        str << ex;
        str >> a >> op >> b;
        return std::to_string(calc(a,b,op));
    }
    std::string parse_first(const std::string & in)
    {
        std::string res;
        std::regex re("\\(\\d+(\\*|\\/|\\+|\\-)\\d+\\)");
        std::sregex_token_iterator begin(in.begin(),in.end(),re,0);
        while(begin != std::sregex_token_iterator())
        {
     
            std::string temp = begin->str();
            std::regex r("(\\(|\\))");
            temp = std::regex_replace(temp,r,"");
            std::string calced = calc(temp);
            r.assign(begin->str());
            res = std::regex_replace(in,re,calced);
            ++begin;
        }
        return res;
    }
     
    std::string parse_second(const std::string & in)
    {
        std::string res = in;
        std::regex re("\\d+(\\.\\d+)?(\\*|\\/)\\d+(\\.\\d+)?");
        std::sregex_token_iterator begin(in.begin(),in.end(),re,0);
        while(begin != std::sregex_token_iterator())
        {
            std::string calced = calc(*begin);
            std::regex r(begin->str());
            res = std::regex_replace(in,r,calced);
            ++begin;
        }
        return res;
    }
     
    double calculate(const std::string & in)
    {
        std::string res = parse_second(parse_first(in));
        std::stringstream final;
        final << res;
        double result{},second{};
        final >> result;
        char op;
        while ((final >> op >> second ))
        {
            result =calc(result,second,op);
        }
        return result;
    }
     
    int main(int argc, char *argv[])
    {
        std::string in;
        std::getline(std::cin,in);
        std::regex re(" ");
        in =std::regex_replace(in,re,"");
        std::cerr << calculate(in) << std::endl;
        return 0;
    }

    Посчитал выражение)

    Запостил: Koshak90, 30 Января 2017

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

    • Нахуа пишут const double& ?
      Ответить
      • Других граблей мало. А тьфу, я думал, что ОП это вернул :)

        Думают, что так дабл передастся быстрее.
        Ответить
        • чтоб литералы юзать по ссылке)
          Ответить
        • Если double занимает больше чем указатель, то может помогает?
          Ответить
          • Ну только если его там не юзают, тупо дальше по ссылке передают...
            Ответить
          • Плавающий питух через отдельный стек передается, нет?
            Ответить
            • Хотя в данном случае все равно компилятор сам сделает как быстрее, заинлайнив половину.
              Ответить
            • Где как, от соглашения зависит. Где-то - через обычный стек, где-то - через стек/регистры fpu, где-то - через векторные регистры.

              З.Ы. Регистры fpu в виде стека где-то кроме x86 встречаются?
              Ответить
              • Более того, на одном процессоре и в одной ОС может быть по-разному в зависимости от ко-ко-конпелятора.

                Вот тут был ватнокомовский пример соглашения, принятого компилятором High C, который не использует плавучий стек для результата: http://govnokod.ru/22058#comment368738

                Да и сам Ватноком не всегда его использует.
                Ответить
              • а разве меня, как программиста на языке высокого уровня, должно волновать то что там компилятор нагенерил.
                Ответить
                • программистов на яп высокого уровня вообще нихера не волнует
                  Ответить
                  • Нет, их волнует переписать всё на языках высокого уровня.
                    Ответить
                    • а потом успевают покушать пока парсится их любимый xml
                      Ответить
                    • В эпоху DOS была шуточная программа exe2c, которая дизассемблировала экзешник, а потом каждую инструкцию ассемблера заменяла сишным оператором. Например, это:
                      mov ax, bx
                      заменяла на это:
                      ax = bx;
                      где выше по коду было объявлено
                      int ax, bx;

                      В результате любая программа превращалась в сишную с несколько завышенными требованиями, если, конечно, удавалось дизассемблировать без глюков.

                      В принципе, можно написать аналогичную программу, которая каждую ассемблерную инструкцию заменяет на выражение на Питоне.
                      Ответить
                      • И это чудесно отражает разницу между языками высокого уровня и кодом высокого уровня.
                        Ответить
                      • прогнать её рекурсивно и занять всю существующую цифровую память
                        Ответить
                        • Кстати интересная идея. Вдруг наоборот какие-нибудь странные аттракторы найдутся.
                          Ответить
                          • Особенно интересно каждый раз компилировать со включенной оптимизацией.
                            Ответить
                            • > Особенно интересно каждый раз компилировать со включенной оптимизацией.

                              Гипотеза Адамса-Кэрролла: exe2c | g++ -O3 является сжамающим отображением с неподвижной точкой
                              main:
                                      mov     eax, 42
                                      ret
                              Ответить
                              • > сжамающим
                                Зожамающим.
                                Ответить
                              • Вот только линкер прилинкует crt1.o с кодом типа такого (для простоты не реальный код, а суррогат):
                                _mainCRTStartup:
                                    call _init_some_runtime_variables ; тут заполняем argc и argv для функции main
                                    call _main
                                    call _finalize_something ; тут возвращаем операционной системе значение из eax
                                    ret
                                end _mainCRTStartup

                                Точка входа-то не в main, а в стандартной библиотеке.
                                Ответить
                                • > прилинкует crt1.o
                                  А ты попроси его всякую нинужную хуиту не линковать.
                                  Ответить
                                  • Царям не нужен стандартный рантайм. Царь для каждой задачи пишет рантайм сам.
                                    Ответить
                                    • > Царям не нужен стандартный рантайм.
                                      Дык ты рантайм только что декомпилировал из асма в си. Зачем тебе ещё один?
                                      Ответить
                                      • Чтобы занять всю память. Другого обоснования не вижу.
                                        Ответить
                            • ...Код, изначально содержащий UB.
                              Ответить
                • Я тоже так думаю.

                  Потому когда мои программы тормозят или работают не так, как нужно, я вызываю специального низкоуровневого программиста чтобы он мне их починил.
                  Ответить
                  • Потому что низкоуровневые программисты - это такие аникеи, типа заправщиков картриджей.
                    Ответить
                    • Да.

                      Мои инструменты это фреймворки и средства разработки (С)
                      Ответить
    • Нахуа пишут double a{} ?
      Ответить
      • Чтобы там оказался 0, а не мусор.
        Ответить
        • Так его начальное значение нигде не используется.
          Ответить
          • Царь?
            Ответить
          • проще всё заблаговременно занулять, чем потом выискивать ошибки из-за неинициализированных переменных
            Ответить
            • Палка о двух концах. Есть альтернативное мнение, что такая инициализация заметает проблемы под ковёр - конпелятор уже не может подсказать про неинициализированную переменную, в дебаге её уже не заполнят мусором и т.п. И прога будет жить и считать хуйню...
              Ответить
              • #ifndef DEBUG
                #define PTR_INITIALIZER nullptr
                #else
                #define PTR_INITIALIZER reinterpret_cast<std::nullptr_t>(uintptr _t(1));
                #endif

                Не проверял, но суть, я думаю, ясна
                Ответить
            • В идеале, хотелось бы заполнять сразу правильным значением, а не нулём. Но если результат возвращают побочным эффектом, как в том же s >> a, то это невозможно...
              Ответить
              • иди в функциональныеязыки
                Ответить
                • засунул твой функциональный язык себе в очко, проверь.
                  Ответить
    • case '/':
          return a/b;

      А как насчет деления на 0?

      std::regex re("\\(\\d+(\\*|\\/|\\+|\\-)\\d+\\)");
      std::regex re("\\d+(\\.\\d+)?(\\*|\\/)\\d+(\\.\\d+)?");

      Засуньте свои [вырезано цензурой] рыгекспы сами знаете куда
      Ответить
      • Программист на Перле может писа́ть на любом языке, как на Перле.
        Ответить
      • а что не так с делением на ноль? Тут же плавающий питух, там половина спецификации про всякие наны с бесконечностями.
        Ответить
        • например чтобы не продолжать вычисления, если в ходе них на каком-то этапе получается NaN, бесконечность
          Ответить
          • NaN или бесконечность - ошибка в частном случае, а не в общем. По факту, надо проверять результат выполнения на валидность там, где NaN/inf недопустимы, нежели рисовать костыли для обхода в случаях, где они допустимы
            Ответить
          • Если это критичный по производительности код то возможно, там еще с денормализованными стоит как-то бороться, которые не только при делении возникают, но в калькуляторе на регекспах не вижу проблемы в том что он сначала досчитает выражение а потом выведет NaN (а в случае бесконечности так вообще правильный ответ).
            Ответить
      • мдааа ну ты и нубец
        Ответить
        • нубец наяривает твое очко, проверь.
          Ответить
    • Какой strstream? sstream же.
      Ответить
    • - Я так раньше никогда не делала. Мне понравилось. А тебее? - сказала она после того, как я влил в неё свой заряд и, уставший, уселся прямо на ковролин на полу кабинета.
      Ответить

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