Задать вопрос
Ответы пользователя по тегу C++
  • Как упростить код?

    wataru
    @wataru Куратор тега C++
    Разработчик на С++, экс-олимпиадник.
    Ну вот ваше последнее описание и есть решение - храните 2 стека. Вы же храните 1 стек и лишь в определенном случае заводите второй стек tmp.
    Ответ написан
    Комментировать
  • Как извлечь элементы многобайтового массива как единое число?

    wataru
    @wataru Куратор тега C++
    Разработчик на С++, экс-олимпиадник.
    Лучше так делать не надо. Это UB - нарушение всяких strict aliasing, выравниваия и вообще от порядка байт в машине зависит. Лучше руками собрать ULL по частям, вроде
    for (int i = 0; i < 8; ++i) result |= byte_array[i+1] << (8ULL*i);
    или
    for (int i = 0; i < 8; ++i) result |= byte_array[i+1] << (8ULL*(7-i));


    На худой конец, если очень узкое место, надо делать memcpy из массива в &result.
    Ответ написан
    Комментировать
  • Почему явная специализация невозможна?

    wataru
    @wataru Куратор тега C++
    Разработчик на С++, экс-олимпиадник.
    Проблема вызвана использованием шаблона rewrite из шаблона search.

    Если вы перенесете специализацию шаблона rewrite вверх, до специализации search, то все скомпилируется. Или надо где-то выше первого использования шаблона rewrite задекларировать специализацию (что ваш закомментированный код и делает).

    Вызвана эта ошибка стандартом.
    Надо, чтобы специализация шаблона была задекларирована до любого использования:
    Specialization must be declared before the first use that would cause implicit instantiation, in every translation unit where such use occurs:
    Ответ написан
    1 комментарий
  • Уменьшается ли используемая память программы?

    wataru
    @wataru Куратор тега C++
    Разработчик на С++, экс-олимпиадник.
    Не гарантированно, но в некоторых случаев компилятор действительно сможет переиспользовать место на стеке под переменную a для какой-то новой локальной переменной, когда a выйдет из зоны видимости. Но чаще это место просто будет пустым до конца функции и никакой экономии памяти вы не получите.

    Но вообще, делать так для экономии памяти никогда, категорически не рекомендуется. Код становится менее читаем а экономите вы на спичках. Это локальные переменные - они на стеке. Их много можно выделить только рекурсией или большими массивами (ну не объявите вы в коде миллион локальных переменных). В обоих случаях, если стека не хватает - надо или избавлятся от рекурсии/больших массивов изменением логики, или выносить их в кучу.

    Использование фигурных скобок для ограничения зоны видимости переменной действительно используется на практике, когда вам надо ограничить время жизни переменной и добиться вызова деструктора в определенное время. Так делают, например, когда захватывают мютекс в многопоточных программах - специальный класс-обертка в конструкторе его хватает, в деструкторе освобождает. И иногда не надо держать мютекс во всей функции, а только в определенном месте. Допустим, дальше идут долгие вычисления, не требующие мютекса. Тут логично мютекс освободить. Но это должно встречаться редко. Если вам в функции надо несколько раз такое проворачивать, то надо ее отрефакторить и разбить на части.
    Ответ написан
    Комментировать
  • В чём отличия языка Си и С++? Зачем нужен Си?

    wataru
    @wataru Куратор тега C++
    Разработчик на С++, экс-олимпиадник.
    По учебнику, фундаментальных отличий три: классы, шаблоны и исключения. По факту там еще целый ворох мелких различий и это два вообще разных языка, хоть и слегка похожих.

    C сейчас используется в основном там, где легаси (куча старого кода в проекте уже на C), или где очень жесткие требования к легкости окружения исполнения языка (микроконтроллеры всякие).
    Ответ написан
    2 комментария
  • Корректно ли в C++ называть стек статической памятью?

    wataru
    @wataru Куратор тега C++
    Разработчик на С++, экс-олимпиадник.
    Стек стоит рассматривать как отдельную категорию. И статической памятью его называть точно не стоит.
    Хотя бы потому, что для работы с ним есть специальные команды процессора.
    Плюс, он хоть и выделяется программе при загрузке, в отличии от статических данных, обращаться к данным в нем можно не всегда - а только ниже по стеку вызовов.
    Ответ написан
    Комментировать
  • Скажите как можно исправить тайм лимит в коде?

    wataru
    @wataru Куратор тега C++
    Разработчик на С++, экс-олимпиадник.
    Сумму на отрезке надо делать хитро: в каждой вершине поддерживайте счетчик, сумму значений всех вершин в поддереве, а так же минимальное и максимальное значение в поддереве.

    Рекурсивно спускайтесь, если текущее поддерево целиком лежит в запросе - возвращайте известную сумму.
    Иначе запускайтесь слева или справа только если отрезок там пересекается. Или можно просто возвращать 0 вместо этих проверок, если все вершины в поддереве не попадают в отрезок (меньше левой границы запроса или больше правой). Такой подход найдет сумму за O(log n) а не за O(n).
    Ответ написан
  • Более общее свойства дерева поиска?

    wataru
    @wataru Куратор тега C++
    Разработчик на С++, экс-олимпиадник.
    Что за last_key? Почему дерево считается неправильным, если самая левая вершина равна numeric_limits<int>::min()

    Эта задача, в отличии от предыдущих двух ваших вопросов - простая. Тут не надо писать балансированное дерево поиска, а надо тупо проверить, что заданное дерево хорошее.

    Отличие от прошлой задачи, упомянутой в вопросе - только в том, что теперь ограничения в каждом поддереве не L < key < R, а L <= key < R. Т.е. отличие от кода в конце вопроса, по идее, должно состоять только в одном знаке <= вместо <

    Есть, правда, дополнительная проблема, что числа могут быть очень большие и, например, надо было бы в самом начале передавать numeric_limits<int>::max()+1 в качестве правой границы. Но тут можно решить эту проблему просто заменив тип параметров max_key, min_key на long long. Или изменить их смысл на "ключи в этом поддереве могут быть с L по R включительно". Тогда при переходе к левому сыну надо бы передавать tree[i].key-1 в качестве max_key. Но тогда надо аккуратно и не переполниться при numeric_limits<int>::min(). Но тут тогда нужна дополнительная проверка - любая вершина со значением numeric_limits<int>::min() не должна иметь левых детей.
    Ответ написан
    Комментировать
  • Что быстрее: создание вектора push_back или сначала объявление сколько в нем переменных, а потом заполнение?

    wataru
    @wataru Куратор тега C++
    Разработчик на С++, экс-олимпиадник.
    Сначала объявление будет быстрее. Тут всего одно выделение памяти, а при push_back их будет несколько (но не n, потому что vector умный и выделяет памяти с запасом).

    Но push_back не на порядок медленнее. В худшем случае в пару раз. И то и другое будет работать за O(n). Если у вас программа еще хоть что-то делает, кроме запихивания чисел в массив, то вы разницу особо и не заметите.

    Если только профайлер не показывает что вот это вот самое медленное место в программе, то заморачиваться не стоит.
    Ответ написан
    3 комментария
  • Множество с запросами?

    wataru
    @wataru Куратор тега C++
    Разработчик на С++, экс-олимпиадник.
    Ваше решение медленно считает сумму на отрезке. За O(n) - вы проходитесь по всему множеству. А все ваше рение будет O(n^2). Когда как это надо делать за O(log n) максимум. Ну посмотрите же на ограничения - n <= 10^5. Обычно n^2 работает ну до 10^4 максимум с огромным скрипом и натяжками.

    К сожалению, стандартными set'ами вы сумму на отрезке быстро не подсчитаете. Придется реализовывать сбалансированное бинарное дерево поиска, где в каждой вершине надо дополнительно хранить сумму всех значений в поддереве. Вот реализация дерева, но там сумма на отрезке не реализована. Однако, в статье расказанно, как это делать. Ищите на странице "на отрезке".

    Если бы числа в задаче был поменьше, то можно было бы использовать дерево отрезков. Это сильно проще реализуется. Но тут бы это потребовало массивы на 2*10^9 элементов.

    Edit: вообще, судя по нескольким вопросам от вас, у вас там задачи именно на реализацию бинарных деревьев поиска с дополнительными данными в вершинах. Вот если у вас следующая задача опять не пройдет по времени, то сначала убедитесь, что вы используете собственноручно написанное дерево поиска.
    Ответ написан
  • Почему код не проходит по тайм лимиту?

    wataru
    @wataru Куратор тега C++
    Разработчик на С++, экс-олимпиадник.
    С такими ограничениями надо менять алгоритм. У вас наивная реализация за O(nq). А надо реализовывать rope за O(q log n).

    Какими-то стандартными контейнерами это не сделать вообще никак.

    Советую реализовывать декартово дерево по неявному ключу. Это самая простая реализация будет. Ну, а дальше вам надо будет это дерево разрезать на три части двумя Split, две крайние объеденить, разрезать это в новом месте и слить уже 3 части с вырезанным куском в середине.
    Ответ написан
  • Как работает данный алгоритм проверки числа на простоту и какой у него Big O??

    wataru
    @wataru Куратор тега C++
    Разработчик на С++, экс-олимпиадник.
    Это вроде как решето Эратосфена (только с багами).

    Этот цикл по идее помечает составными все числа, делящиеся на i (которое к этому моменту вроде как простое). Таким образом все составные числа должны быть помечены в массиве a.
    Тут есть оптимизация: помечаются только те числа, для которых i - делитель не больше корня. Иначе бы цикл был не от i*i а от i. Эту оптимизацию можно делать, потому что у каждого числа обязательно есть простой делитель не больше корня, а значит и такой цикл пометит все составные числа.

    Сложность тут O(n log(log n)) - Доказательство смотрите в википедии.
    Ответ написан
    Комментировать
  • Как исправить код?

    wataru
    @wataru Куратор тега C++
    Разработчик на С++, экс-олимпиадник.
    Похоже проблема в непонимании параметров string::insert. Там передается индекс, в который и вставляется строка. Т.е. новые данные будут по этому индексу. Фактически, они вставляются перед символом на этой позиции.

    Оно уже делает ровно то, что вам надо, не нужно делать там k[i]-1 и разбирать отдельно случай k[i]==0.
    Ответ написан
    Комментировать
  • Почему вылазит link error(не видит вирутальные методы?)?

    wataru
    @wataru Куратор тега C++
    Разработчик на С++, экс-олимпиадник.
    Потому что шаблон.

    Надо или весь класс определять в хедере, или в array.cpp указывать компилятору генерировать инстанс шаблона с параметром, который нужен в другом cpp файле:
    using Array<int>;

    То же и для очереди.

    Происходит это потому, что компилятор генерирует шаблоны лениво - только когда они нужны. Вот, компилируя array.cpp он не видет вообще ни одного использования шаблона и не генерирует ничего. В каком-нибудь main.cpp у него есть объявление из array.h и использование шаблона. Он и генерирует объявления методов. Но определения-то нигде нет. Оно в array.obj должно быть по вашему замыслу, а там пусто.
    Ответ написан
    1 комментарий
  • Почему выбивает исключение на моменте деления изображения на равные блоки?

    wataru
    @wataru Куратор тега C++
    Разработчик на С++, экс-олимпиадник.
    Наверно, в коде еще есть ошибки, но вот тут:
    vector <double> variances;
    for (int i = 0; i < num_blocks; i++) {
        Scalar mean, stddev;
        meanStdDev(block[i], mean, stddev);
        variances[i] = stddev.val[0];
    }


    Вы записываете в пустой вектор variances по индексу i. Надо или делать push_back в вектор, или выделить его сразу размера num_blocks. Например, так:
    vector <double> variances(num_blocks);

    Еще перепроверьте, что у вас rows/cols не перепутано.
    Ответ написан
    Комментировать
  • Почему не считывает все нажатия вне event loop SFML?

    wataru
    @wataru Куратор тега C++
    Разработчик на С++, экс-олимпиадник.
    pollEvent возвращает сообщение из очереди, пока они там есть. В очереди их может оказаться несколько. Именно поэтому там цикл while. А код за циклом обрабатывает только одно - последнее - сообщение. Судя по наблюдаемому вами поведению, в очереди оказывается несколько сообщений.
    Ответ написан
  • Почему не работает GetPixel?

    wataru
    @wataru Куратор тега C++
    Разработчик на С++, экс-олимпиадник.
    GetPixel принимает сначала x, потом y. У вас там Height и Width не в том порядке переданы.

    Это будет ошибкой, если одна из сторон более чем в 2 раза больше другой. Это может быть, если у вас широкоформатный монитор.

    У вас там битмап сохраняется в sceen2.png - оно там что-то сохранило вообще? Иначе проблема может быть не GetPixel, а с самим хБитмапом.

    Edit:

    Еще проблема может быть с масштабированием. В результате GetSystemMetrics(SM_CYSCREEN) возвращает не то, что вам надо и BitBlt не срабатывает из-за слишком большого размера.

    Попробуйте вызвать SetProcessDPIAware.

    Еще может быть проблема, что вы SelectObject делаете 2 раза с одним и тем же membit. Надо во второй раз что-то другое подставлять, чтобы HBitmap освободить. Иначе оно, похоже, так и остается привязано к DC.

    Вот мой рабочий код:
    HBITMAP GameManager::GetScreenshot(HWND window) {
    	HDC hScreenDC = GetDC(window);
    	HDC hMemoryDC = CreateCompatibleDC(hScreenDC);
    	RECT window_rect;
    	GetClientRect(window, &window_rect);
    	int width = window_rect.right - window_rect.left;
    	int height = window_rect.bottom - window_rect.top; 
    	int result_width = width;
    	int result_height = height;
    	
    	HBITMAP hBitmap = CreateCompatibleBitmap(hScreenDC, result_width, result_height);
    	HBITMAP hOldBitmap = static_cast<HBITMAP>(SelectObject(hMemoryDC, hBitmap));
    	StretchBlt(hMemoryDC, 0, 0, result_width, result_height, hScreenDC, 0, 0, width, height, SRCCOPY);
    	hBitmap = static_cast<HBITMAP>(SelectObject(hMemoryDC, hOldBitmap));
    	DeleteDC(hMemoryDC);
    	DeleteDC(hScreenDC);
    	return hBitmap;
    }
    Ответ написан
    1 комментарий
  • Можно так сделать с interface?

    wataru
    @wataru Куратор тега C++
    Разработчик на С++, экс-олимпиадник.
    По уму, вам надо продумать ваш интерфейс. И тогда подобных извращений не понадобится. Дабавьте туда какой-нибудь способ для итерации по структуре данных для вывода. Или вообще сделайте метод ToString, который бы возвращал строковое представление внутренней структуры для вывода. Это все, естественно, виртуальные публичные методы, переопределенные в двух реализациях.

    То же и со вводом. Если надо как-то во внутренности очереди залезать и обычными push это не сделать, то, например, передавайте в метод CreateFromData() вектор введенных пользователем значений.
    Ответ написан
    Комментировать
  • Как сделать какую-нибудь многозадачность на ардуино?

    wataru
    @wataru Куратор тега C++
    Разработчик на С++, экс-олимпиадник.
    Можно поменять логику. Включили мотор и постоянно меряете расстояние. Как домеряли до 35см - остановились.

    Можно перед циклом один раз померять - решить, а надо ли вообще мотор включать. Внутри, чтоб электричество зря не жечь, можно даже между вычислениями расстояния сколько-то спать. Смотрите там из расстояния - если оно сильно больше 35 - спите подольше.
    Ответ написан
    2 комментария
  • Почему автодополнение не предлагает мне поля структуры?

    wataru
    @wataru Куратор тега C++
    Разработчик на С++, экс-олимпиадник.
    Вы хотите вернуть T. У Node - это член Data. Вот и возвращайте _node->data, или какой там у вас смысл у _node. Пока странно, вы наследуетесь от Array, но никак его не используете. По идее надо возвращать первый элемент в массиве.

    Да, еще, по английски правильно capaCity, а не capaSity.
    Ответ написан