Ответы пользователя по тегу C++
  • В каких случаях стоит создавать свои пространства имен?

    @User700
    Когда возникает система классов, констант, функций, возможно глобальных переменных и объектов, которая описывает сущности одной задачи или набора связанных задач и создаёт инструменты для их решения, для каких-либо действий с этими сущностями.
    Например, пространство имён, содержащее классы описания сокетов, IP-адресов, соединений, функции для создания соединения, принятия входящего запроса, отправки и принятия данных. Или другой пример: набор разных алгоритмов для работы с матрицами, определение типа "матрица" и "вектор" как стандартного или пользовательского с помощью using/typedef.
    Ответ написан
  • Как реализовать сжатие LZ77 на примере одной строки?

    @User700
    Что-то страное конечно. Какая-то глобальная переменная, потоки от строк... есть new, но нет delete ("утечка" памяти). Почему не ипользовать библиотечный лист? Также, c++ отличается от Java/Python -- при передаче по значению контейнера (в частности строки) он копируется (или перемещается, но при использовании доп. функций); так стоит делать если функции нужно собственное владение объектом, а не только считывание его данных. В обычном случае передают константную ссылку, пару итераторов, или легковесный объект-просмотрщик, в который может привестись контейнер. Кроме того, наверно нужно rfind вместо find чтобы искать с конца.
    Можно двумя способами. Ниже алгоритм по принципу автомата. А можно было бы с вложенным циклом.
    #include <iostream>
    #include <string>
    #include <string_view>
    #include <forward_list>
    #include <algorithm>
    
    using namespace std;
    
    struct CodeNode
    {
        unsigned char beg;
        unsigned char len;
        char ch;
    };
    
    bool push_shift (string& s, char c, size_t len)  // return true if first symbol were erased
    {
        if (s.size() < len) {s.push_back(c); return false;}
        move (next(s.begin()), s.end(), s.begin());
        s.back() = c; return true;
    }
    
    forward_list<CodeNode> LZ77 (string_view s, size_t win_len = 255)
    {
        forward_list<CodeNode> res; auto it = res.before_begin();
        string win, buf; win.reserve(win_len); buf.reserve(win_len);
        CodeNode next; size_t saved_win_len = 0;
        for (char c : s) {
            buf.push_back(c);
            size_t pos;
            next.ch = c;
    //cout<<win<<' '<<buf<<' '<<saved_win_len<<'\n';
            if ((pos = win.rfind(buf)) != string::npos) {
                next.beg = saved_win_len-pos; next.len = buf.size();
                if (  push_shift (win, c, win_len)  ) saved_win_len--;  //shift
            } else {
                it = res.insert_after(it, next); buf.resize(0);
                next.beg = 0; next.len = 0;
                push_shift (win, c, win_len);
                saved_win_len = win.size();
            }
        }
        if (next.len != 0) {next.len--; res.insert_after(it, next);}
        return res;
    }
    
    size_t LZ77length (const forward_list<CodeNode>& code) { // get length of original string
        size_t len = 0;
        for (const CodeNode& cn : code) len += cn.len+1;
        return len;
    }
    
    size_t LZ77size (const forward_list<CodeNode>& code) {  // get size of coded data
        return sizeof(CodeNode) * distance(code.begin(), code.end());
    }
    
    string LZ77decode (const forward_list<CodeNode>& code)
    {
        string res;
        res.reserve(LZ77length(code)); // can not be
        for (CodeNode cn : code) {
            for (size_t i = res.size()-cn.beg, e = i+cn.len; i != e; ++i)
                res += res[i];
            res += cn.ch;
        }
        return res;
    }
    
    ostream& operator<< (ostream& os, CodeNode cn) {
        return os << '<' << int(cn.beg) << ',' << int(cn.len) << ',' << cn.ch << '>';
    }
    
    int main()
    {
        string s;
        getline (cin, s);
        //s = "helolohelololololololololololololo"; // для тестирования
        auto code = LZ77(s,10);
        for (CodeNode cn : code) cout << cn << ' ';
        cout << endl;
        cout << LZ77decode(code) << '\n' << s << endl;
        //cout << s.size() << ' ' << LZ77size(code) << endl;
        return 0;
    }
    Ответ написан
  • Яндекс.Практикум C++ Что я делаю не так?

    @User700
    Зачем to_string? Элементы строки это символы. Для того, что-бы их сравнить, нужно, внезапно, сравнить два символа.
    Ответ написан
    1 комментарий
  • Как правильно реализовать шаблонный класс рациональных чисел в С++?

    @User700
    Здесь:
    template <class T> istream& operator>>(istream& stream_in, rat<T> &rvalue) {
      cout << "Enter rational value (a/b): ";
      stream_in >> rvalue.ch;
      stream_in.ignore();
      stream_in >> rvalue.zn;
      cout << endl;
      return stream_in;
    };

    Не должно быть привязки к cout. Работа только с потоком stream_in, т.к. данные не обзательно считываются с консоли, а такой оператор должен предполагать и считывание из файла. Приглашение ко вводу нужно делать "в main", или реализовать метод для ввода с приглашением, принимающий два потока. Перевод строки также после ввода не нужно делать.
    Основная проблема:
    Не совсем правильное решение, см. комментарии:
    public:
      template <class T1> 
      friend istream& operator>>(istream& stream_in, rat<T1> &rvalue); 
      template <class T1>
      friend ostream& operator<<(ostream& stream_out, const rat<T1> &rvalue);

    UPD:
    Правильное
    template <class T> class rat;
    template <class T> istream& operator>>(istream& stream_in, rat<T> &rvalue);
    template <class T> ostream& operator<<(ostream& stream_out,const rat<T> &rvalue);
    
    template <class T> 
    class rat{
      T ch, zn;
    public:
      friend istream& operator>> <T> (istream& stream_in, rat &rvalue); 
      friend ostream& operator<< <T> (ostream& stream_out, const rat &rvalue);
      //......
    };
    Ответ написан
    7 комментариев
  • Как пользоваться функцией EnumWindows?

    @User700
    Переменная buffer объявлена два раза. Делаете new без delete -- утечка памяти. Я бы этот момент реализовал наподобие такого:
    string title(length, '\0');
    GetWindowText(hWnd, (char*)(title.data()), length+1);

    И buffer тогда не надо.
    В некоторых стандартах data возвращает не конст. указатель, но проще явно привести (см. также const_cast).
    Но понятно ли, что это только колбэк для функции. Вы должны вызвать саму ф-ию WinAPI, передав ей свой колбэк.
    Ответ написан
  • Как в C++ передать функции("строку")?

    @User700
    Нужно const char*
    А так да, имя совпало со стандартным классом -- нехорошо
    Ответ написан
  • C++ ошибка линковщика, хотя если скинуть код в один файл то компилирует, как исправлять?

    @User700
    Если класс шаблонный, то он должен быть весь быть в h (или hpp), и подключаться. Иначе он не скомпилирует. Т.е. отдельный cpp с реализацией методов он просто не может скомпилировать отдельно, т.к. не знает что это за класс T, параметр шаблона подставляется на этапе компиляции; и при разных T всё перекомпилируется (поэтому иногда, например, вместо передачи функции или функтора в виде superfunc (FUNC&& func), где FUNC это функция или объект с оператором (), можно пердать например superfunc (std::function меньше int(int) больше func), т.е. сделать нешаблонным, но иметь накладные расходы на посредник std::function, но машинный код будетсгенирован один раз и будет универсальным)
    Ответ написан
    1 комментарий
  • Как поменять местами элементы массива?

    @User700
    Используйте тег код.
    Зачем это:
    max = a[i][j];
    if (a[i][j] = max)
    {
    a[i][j] = a[i][i];
    a[i][i] = max;
    }

    Просто найдите max -- макс. элемент и его индекс jmax. Зптем поменяйте [i,j] на [i,jmax]. См. std::swap и ссылки по запросу выше.
    Ответ написан
    Комментировать
  • Как сделать такой финт ушами с double?

    @User700
    Как-то так
    union double_bitfld_t {
     double dbl;
     struct {
      unsigned int mnt : 52;
      unsigned int exp : 11;
      unsigned int sgn : 1;
     } bits;
    };

    double_bitfld_t x;
    cin >> x.dbl;
    cout << (x.bits.sgn ? '+' : '-') << (1+x.bits.mnt/double(1<<52)) << "*2^" << (x.bits.exp-1023) << endl;

    Конечно нужно проверить, отладить
    Вместо "1+x.bits.mnt/double(1сдвиг52)" лучше как выше завести другую переменную и изменить порядок на 0, получив мантиссу как double
    Ответ написан
    1 комментарий
  • Есть разница, на низком уровне, между классом со статичными полями и глобальным экземпляром класса?

    @User700
    Скорее всего низкоуровневой разницы нет, если речь об одном глоб. объекте во втором случае:
    https://godbolt.org/z/YaWccvPx3
    Мне кажется, если это pool для аллокации памяти и т.д., то предпочтительно ближе ко второму варианту, т.к. можно создавать разные пулы одного типа в одной программе. Скорее даже лучше что-то вроде shared_ptr на pool у аллокатора...
    Ответ написан
    Комментировать
  • Как реализовать алгоритм Прима для графа в виде списка смежных вершин?

    @User700
    1) Полагаю оптимально предварительно отсортиоровать рёбра по весу от минимума.
    2) Нужно еще хранить множество вершин. Хорошо подойдёт для этого храниние в виде "битовой карты", т.е. массива бит (массива bool): std::vector от bool, назовём массив IN(n), т.к. всё равно придётся их добавить все. n это кол-во вершин (и размер массива).
    3) Также результат представится в виде множества рёбер. Можно также использовать список рёбер для представления оставного дерева.
    4) Алгоритм.
    Если n == 0, то возврат.
    IN[0] = true; v_count = 1.
    Пока v_count меньше n
    Ищем первое ребро из списка, которое соединяет вершины i и j (или наоборот!), при условии IN[i] & !IN[j]: добавляем его в список-ответ, IN[j] = true, ++v_count.

    ПС
    А это для чего такое?
    list* List = new list;

    Используйте std::forward_list
    Ответ написан
  • Почему в WinAPI вместо русского языка выводятся иероглифы?

    @User700
    MessageBox может подключиться как MessageBoxA, требующую однобайтную кодировку; или как MessageBoxW для юникода. Префикс L объявляет юникодную строку. При компиляции нет предупреждений о приведении типов? Возможно настроено на использование MessageBoxA. можете указать явно MessageBoxW. Хотя нет, при такой ошибке не компилировалось бы.
    Может быть дело в том, в какой кодировке компилятор понимает файл исходного кода:
    https://qna.habr.com/q/525512
    Ответ написан
    Комментировать
  • Как заполнить вектор в отдельной функции?

    @User700
    А зачем такая функция? Это одна [понятно что делающая] строчка в коде.
    vector<int> ae (int n) {
      vector<int> a(n);
      for (int& x : a) cin >> x;
      return a;
    }

    Или
    void ae (int n, vector<int>& a) {
      a.resize(n);
      for (int& x : a) cin >> x;
    }
    Ответ написан
    Комментировать
  • Почему WinAPI выполняет синхронную запись?

    @User700 Автор вопроса
    Возможно, дело в этом https://docs.microsoft.com/ru-RU/troubleshoot/wind...

    Расширение файла
    Еще одна причина синхронного завершения операций I/O — это сами операции. На Windows любая операция записи в файл, который расширяет его длину, будет синхронной.

    Примечание

    Приложения могут сделать ранее упомянутую операцию записи асинхронной, изменив допустимую длину данных файла с помощью функции, а затем выпустив SetFileValidData WriteFile .

    Надо пробовать

    Но еще остаётся неясным в чём проблема с незаписью последней порции в режиме FILE_FLAG_NO_BUFFERING даже с учётом выравнивания всего и вся на 512; возможно в вызове CancelIO в close (хотя перед этим есть ожидание wait).
    Ответ написан
    2 комментария
  • Как правильно передать указатель на массив внутри структуры в функцию С (Ардуино)?

    @User700
    Да, можно:
    а) передать указатель на uint16_t. В treyd обработывайте его как массив (известной из define длины)
    б) это си или си++? В последнем можно передать ссылку на сам тип uint16_t[число]. Возможно получится это сделать и как указатель на такой тип
    в) объявить тип структуры. есть такое понятие как указатель на поле структуры. Если она глобальная, то указатель на неё можно и не передавать в функцию, а там обращаться к ней непосредственно. Смогу показать на примере.
    Ответ написан
  • Редактирование файла C++?

    @User700
    В конец должно быть требуется записать 0. Malloc не обнуляет выделенную память?
    Найти подстроку strstr. Если найдено, копировать strcpy в выходной буфер или сразу в файл начало, затем замену и т.д. Затем копировать оставшийся конец. При работе с буфером следует предусмотреть realloc при переподнении. Если задача ограничена одним вхождением, одной заменой первого вхождения, можно изначально выделить буфер размером filesize + newsubstrlen - oldsubstrlen, перепестить (memmov или strmov, если последнее есть) конец строки и копировать memcpy строку в середину.
    А почему вывод не на си?
    Ответ написан
    1 комментарий
  • Как вывести данные структуры в табличном виде?

    @User700
    Скорее всего структура данных не соответствует задаче
    Ответ написан
    Комментировать
  • Почему программа не скомпилируется?

    @User700
    Потому что как минимум A это чисто виртуальный класс.
    Ответ написан
  • Можно ли конвертировать результат constexpr функции в строку?

    @User700
    А что делает макрос? Прибавляет ".data"? Тогда в коде лишняя точка с запятой внутри скобок. Но в этом случае должно работать. Почему не сделать оператор преобразование типа datastring к wchar_t*? Тогда и макрос не нужен.
    Кстати, можно использовать пользовательские литералы чтобы каждый раз не считать символы... хотя нет, это подошло бы для другого.
    Хм, а const int size = sz не отменит constexpr? При недостаточном уровне оптимизации
    Ответ написан