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

    −19

    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
    93. 93
    94. 94
    #define BOOST_TEST_MODULE trololo
    #include <boost/test/included/unit_test.hpp>
    using namespace std;
    
    std::string gen(size_t l, int s = 1, int r = 10/*'\253'*/)
    {
      std::string res;
      res.reserve(l);
      for (size_t i = 0; i < l; ++i)
        res.push_back(/*'\1'*/'0' + (char)((i + s) % r));
      return res;
    }
    
    std::string readl(std::istream& st, size_t l, bool human = false)
    {
      std::string res(l, '\0');
      st.read((char*)res.data(), l);
      res.resize((size_t)(st.gcount()));
      if (human)
        return "'" + res + "'";
      else
        return res;
    }
    
    void sp(std::iostream& st, size_t pos)
    {
      st.seekp(pos);
      st.seekg(pos);
    }
    
    std::shared_ptr<std::iostream> makeStream(size_t bufSize = 8)
    {
      (void)bufSize;
      return std::make_shared<std::stringstream> (std::ios::in | std::ios::out | std::ios::binary);//comment it
      auto r = std::make_shared<std::fstream>();
      r->open("test.txt", std::fstream::in | std::fstream::out | std::fstream::binary | std::fstream::trunc);
      return r;
    }
    
    BOOST_AUTO_TEST_CASE(cross)
    {
      auto ss_=makeStream();
      auto& ss = *ss_;
      ss << gen(11);
      BOOST_REQUIRE((readl(ss, 11) == gen(11)));
      ss << gen(11);
      sp(ss, 0);
      BOOST_REQUIRE((readl(ss, 11) == gen(11)));
      sp(ss, 11);
      BOOST_REQUIRE((readl(ss, 11) == gen(11, 11)));
      BOOST_REQUIRE((readl(ss, 1) == std::string()));
      BOOST_REQUIRE(ss.eof());
      ss.clear();
      BOOST_REQUIRE(!ss.eof());
      sp(ss, 0);
      BOOST_REQUIRE((readl(ss, 0) == std::string()));
      BOOST_REQUIRE(!ss.eof());
      ss << std::string();
      BOOST_REQUIRE(!ss.eof());
      BOOST_REQUIRE((readl(ss, 0) == std::string()));
      sp(ss, 0);
      BOOST_REQUIRE((readl(ss, 100500) == gen(11) + gen(11)));
    }
    
    BOOST_AUTO_TEST_CASE(full)
    {
      auto ss_ = makeStream();
      auto& ss = *ss_;
      ss << gen(8);
      BOOST_REQUIRE((readl(ss, 8) == gen(8)));
      ss << gen(11);
      BOOST_REQUIRE((readl(ss, 11) == gen(11)));
      sp(ss, 0);
      BOOST_REQUIRE((readl(ss, 100500) == gen(8) + gen(11)));
    }
    
    BOOST_AUTO_TEST_CASE(parts)
    {
      auto ss_ = makeStream();
      auto& ss = *ss_;
      ss << gen(6);
      BOOST_REQUIRE((readl(ss, 6) == gen(6)));
      ss << gen(8);
      BOOST_REQUIRE((readl(ss, 8) == gen(8)));
      ss << gen(8);
      BOOST_REQUIRE((readl(ss, 8) == gen(8)));
      sp(ss, 0);
      BOOST_REQUIRE((readl(ss, 100500) == gen(6) + gen(8) + gen(8)));
    }
    
    BOOST_AUTO_TEST_CASE(seek)
    {
      auto ss_ = makeStream();
      auto& ss = *ss_;

    BOOST_REQUIRE((ss.tellg() == streampos(0)));
    BOOST_REQUIRE((ss.tellp() == streampos(0)));
    ss << gen(11);
    BOOST_REQUIRE((ss.tellg() == streampos(0)));
    BOOST_REQUIRE((ss.tellp() == streampos(11)));
    BOOST_REQUIRE((readl(ss, 100500) == gen(11)));
    BOOST_REQUIRE((ss.tellg() == streampos(-1)));
    BOOST_REQUIRE((ss.tellp() == streampos(-1)));
    BOOST_REQUIRE(ss.eof());
    ss.clear();
    BOOST_REQUIRE(!ss.eof());
    BOOST_REQUIRE((ss.tellg() == streampos(11)));
    BOOST_REQUIRE((ss.tellp() == streampos(11)));
    ss.seekg(11);
    ss.seekp(11);
    BOOST_REQUIRE((ss.tellg() == streampos(11)));
    BOOST_REQUIRE((ss.tellp() == streampos(11)));
    ss << gen(11,12);
    BOOST_REQUIRE((ss.tellg() == streampos(11)));
    BOOST_REQUIRE((ss.tellp() == streampos(11*2)));
    BOOST_REQUIRE((readl(ss, 11) == gen(11,12)));
    BOOST_REQUIRE((ss.tellg() == streampos(11 * 2)));
    BOOST_REQUIRE((ss.tellp() == streampos(11 * 2)));
    ss.seekg(5);
    BOOST_REQUIRE((ss.tellg() == streampos(5)));
    BOOST_REQUIRE((ss.tellp() == streampos(11*2)));
    BOOST_REQUIRE((readl(ss, 11) == gen(11, 6)));

    }

    Набил я значит юниттестик длякод на STL. Скорее всего код не верен, скорее всего я что-то не знаю, только вот не пойму в чём дело я что-то. :(

    http://rextester.com/LVWJU36102
    Вот этот вот код тест успешно проходит. Но стоит лишь закоментировать строку, оканчивающуюся на //comment it
    Тест тут же фейлится:
    http://rextester.com/NOSCE43184
    Комментируя эту строку ты заменяешь stringstream на fstream.
    Вот интересно мне, почему вдруг тест перестает работать?
    Что я не так делаю?

    Запостил: laMer007, 25 Октября 2016

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

    • #мой_крестофейл
      Ответить
    • меня так напригает когда куча капсных чтук да еще и повторяющихся
      Ответить
    • BOOST_REQUIRE(r->good());
      Ответить
      • Не угадал:
        BOOST_REQUIRE((r->is_open()));
        Ответить
        • Хотя нет, на рекстестере в этом дело, но в реальном проекте не в этом и падает там же(
          Ответить
          • failbit устанавливает, если flush() после ss << gen(11);
            Ответить
            • показать все, что скрытоНе мудрствуй лукаво, мой юный друк... Даже если ты постигнешь все тайны с++, всё равно ты останешься laMer***-ом.
              Ответить
              • По сути проблема там в том, что в fstream при записи в поток смещается и tellp и tellg. А в stringstream запись в поток не влияет на tellg. То есть tellp и tellg расцеплены. От чего это зависит и как задать потокам одинаковое поведение?
                Ответить
                • А никак. filebuf это враппер над FILE*, а сишные функции для работы со строками не дают одновременно джва курсора в один файл ставить. В документации даже написано что при переключении между чтением и записью нужно g/p seek делать, иначе UB.

                  stringbuf это полностью С++ конструкция, и работает она как ожидается.

                  Вообще потоки это странная вещь. fstream не является o/ifstream, внезапно. iostream вообще лучше использовать пореже, так как он может оказаться как очередью, где ввод попадает на вывод, так и объединением двух несвязаных потоков.
                  Ответить
                  • Может мне filebuf тогда реплейснуть на свою реализацию на основе другого файлстрима?

                    А вообще какому мудаку это вообще пришло в голову? Имя?
                    Есть же языки где все единообразно. А тут...
                    Зачем надо было делать общий интерфейс так, как-будто все единообразно?


                    Почему чуть ли не единственная иерархия с интерфейсами и виртуальными функциями стандартной библиотеки в крестах нарушает ООП-основополагающий принцип лисков?

                    Вопросы риторические. Зубы стучат в бессильной злобе. Однажды я определенно сопьюсь...
                    Ответить
                    • показать все, что скрытоТы просто ненавидиш все плюсовое
                      Ответить
                    • Потому что придумали её наркоманы в прошлом тысячелетии.

                      iostream и его потомков лучше вообще не трогать. У него куча проблем, его потомков нормально не представить при помощи С++ наследования, почти всё у него implementation-defined и т.д.
                      Ответить
                      • > Потому что придумали её наркоманы

                        Полностью согласен. Имена методов они придумывали в состоянии упячки. tellg, ага.
                        Я подозреваю, что виртуальное множественное навледование протащили в C++ специально для того, чтобы реализовать сраный iostream, который нафиг не нужен. В C++ вообще полно "случайных" фич: шаблоны сделали, чтобы вектор запилить, шаблоны шаблонов — чтобы замутить бесполезные аллокаторы, и т.п.

                        Зачем склеивать входной поток и выходной поток в один интерфейс? Понятно же, что огребёшь. В жабе вон нормально живётся с отдельными InputStream и OutputStream. Похожее разделение есть и в других языках. Почти всегда ты либо читаешь из стрима, либо пишешь в стрим, но не одновременно. Это же как есть в туалете.
                        Ответить
                        • > в состоянии упячки
                          От сишки ещё не отошли...

                          > входной поток и выходной поток в один интерфейс
                          Подброшу немного дров в костёр.

                          Имхо, попытка скрестить ужа с ежом случайный и последовательный доступ в одном интерфейсе - уже сама по себе фейл.

                          Истинным стримам (сокеты, пайпы и т.п.) атавизм в виде курсора только мешает. А random-access девайсы из-за курсора превращаются в однопоточное говно. Т.е. от курсора всем одни страдания. Если он где-то и нужен - то только в адаптере, превращающем random-access в sequential.
                          Ответить
                          • Ну вообще этот интерфейс хорошо моделирует всякие там крутящиеся диски, в которых чтение последовательное, а seek - не очень прозрачная операция. А девайсов с действительно случайным доступом тогда и не было наверное.
                            Ответить
                            • > всякие там крутящиеся диски
                              Ну не знаю как диски, но перфоленту или магнитофон он моделирует на все 146% (seek - перемотка).
                              Ответить
                  • показать все, что скрытоХаха ебучий костыль какой
                    Ответить
    • > однобуквенные переменные
      > нет скобок вокруг тела цикла и ифа
      Тебя кто так писать научил? Иди мыть рот с мылом.
      Ответить

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