Ответы пользователя по тегу C++
  • Bitmap, hBitmap как загрузить сохраненный bmp?

    wataru
    @wataru Куратор тега C++
    Разработчик на С++, экс-олимпиадник.
    Надо воспользоваться Gdiplus::Bitmap. Он умеет читать из файла.
    Дальше из него можно получить HBITMAP, если надо. А можно и дальше Gdiplus::Bitmap передавать.

    HBITMAP LoadHbitmapFromFile(const std::wstring& filename)
    {
        Gdiplus::Bitmap* bitmap = Gdiplus::Bitmap::FromFile(filename.c_str(), false);
        HBITMAP result = NULL;
        if (bitmap)
        {
            bitmap->GetHBITMAP(Gdiplus::Color(255, 255, 255), &result);
            delete bitmap;
        }
        return result;
    }
    Ответ написан
    5 комментариев
  • Не работает простой код хотя он правильный в чем может быть проблема?

    wataru
    @wataru Куратор тега C++
    Разработчик на С++, экс-олимпиадник.
    Вы уверены? У меня точно такой же код выводит числа от 1 до 10. Скорее всего вы программу нескомпилировали, или запускаете какой-то другой код по ошибке.
    Ответ написан
    1 комментарий
  • Является ли безопасным отнять от указателя 1 и итерироваться по массиву [1,N], а не [0, N-1]?

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

    Every value of pointer type is one of the following:
    * a pointer to an object or function (in which case the pointer is said to point to the object or function), or
    * a pointer past the end of an object, or
    * the null pointer value for that type, or
    * an invalid pointer value.


    Т.е. arr у вас, вообще-то, invalid pointer value перед циклом.

    Плюс там же написано:
    Any other use of an invalid pointer value has implementation-defined behavior.


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

    Edit: немного не то написал. Так делать "не рекомендуется", а не "небезопасно". Оно генерирует непереносимый код. Если у вас на конкретном компиляторе с конкретными ключами работает, то, в общем-то, можно использовать. Но лучше не надо.
    Ответ написан
    5 комментариев
  • Vector не обновляется?

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

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

    И еще, очень глаз режет: правильно писать "symbol", а не "simbol".
    Ответ написан
  • Почему ближайшие точки определяются неправильно?

    wataru
    @wataru Куратор тега Математика
    Разработчик на С++, экс-олимпиадник.
    Есть еще вот такое решение. Выводится так: задаем обе прямые параметрически (точка + t или u, помноженная на вектор вдоль прямой). Получаем выражение для квадрата расстояния между точками как функцию от t и u. Ищем ее минимум, приравняв к 0 частичные производные. Там получаются 2 линейных уравнения.

    Vector3 a = axis2.first - axis1.first;
    Vector3 v1 = axis1.second - axis1.first;
    Vector3 v2 = axis2.second - axis2.first;
    float v11 = Vector3::DotProduct(v1, v1);
    float v12 = Vector3::DotProduct(v1, v2);
    float v22 = Vector3::DotProduct(v2, v2);
    float av1 = Vector3::DotProduct(a, v1);
    float av2 = Vector3::DotProduct(a, v2);
    // Решаем систему методом Крамера:
    // t*v11-u*v12=av1
    // t*v12-u*v22=av2
    float d1 = -av1*v22+v12*av2;
    float d2 = v11*av2-v22*av1;
    float d = -v11*v22+v12*v12;
    float t = d1/d;
    float u = d2/d;
    point1 = axis1.first + v1 * t;
    point2 = axis2.first + v2 * u;
    Ответ написан
    Комментировать
  • В чем причина данной ошибки?

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


    У вас 2 раза определен class парсер::ВыражениеParser.

    Компилятор даже указал на оба определения: они оба в файле ВыражениеParser.h, но включенного 2 раза из разных исходников:
    In file included from ВыражениеVisitor.h:8,
                     from ВыражениеParser.cpp:6:
    ВыражениеParser.h:15:8: ошибка: повторное определение «class парсер::ВыражениеParser»
    ...
    In file included from ВыражениеListener.h:8:
    ВыражениеParser.h:13:8: замечание: предыдущее определение «class парсер::ВыражениеParser»


    Пока похоже, что вы там намудрили с include-guard'ами из-за чего один и тот же хедер включается несколько раз. Выкладывайте начало файла ВыражениеParser.h.
    Ответ написан
  • Как вывести буквы, которые используется наиболее кол-во раз?

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

    Первая задача решается просто - заведите массив счетчиков. Например, на 256 элементов. Для каждой буквы строки увеличивайте счетчик с индексом равным символу (помните, же, что char в C++ - это целочисленный тип?)

    Ну, вторая задача - это элементарное упраждение. Например, заведите переменную, в которой будете хранить индекс максимума. Пройдитесь по массиву счетчиков (от 0 до 255), и изменяйте этот индекс, если текущее значение больше максимального.
    Ответ написан
  • Почему -Wconversion разрешает передачу integer literal в char параметр?

    wataru
    @wataru Куратор тега C++
    Разработчик на С++, экс-олимпиадник.
    Ну вообще, char - integral type. Поэтому передавать туда числовую константу можно - это никакой не варнинг. Компилятор сам понимает, что она должна быть типа char и даже проверяет на переполнение и выдает warning, если что.
    Ответ написан
    2 комментария
  • Что можно убрать чтобы оптимизировать затраты памяти?

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

    Надо прочитать группы для каждого числа, развернуть эти списки, и складывать группу с группой. Будет у вас 2 указателя, как при слиянии двух массивов. Если первые группы в двух числах разной длины, то откусывайте от большей группы длину равную меньшей. Записывайте в ответ сумму групп, сдвигайте указатель в одном массиве, а во втором укоротите первую группу.

    Главная часть решения - это научиться складывать две группы цифр равной длины (плюс перенос). Вроде 7777 + 4444 +1 = 12222 - 4 двойки и 1 единица (помните, порядок у нас развернутый же). Тут можно всегда выделять в отдельную группу первую цифру из-за переноса. Отдельный случай будет, похоже, если цифры дают в сумме 9 и есть перенос (10000..000). А иначе вы получите что-то вида abbbbbbc в оставшихся цифрах. Главное, что при сумме нельзя группы распаковывать.

    В конце разверните группы и объедините подряд идущие группы для одинаковых цифр.
    Ответ написан
  • Почему в коде вызывается конструктор с initializer_list, а не с intами?

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

    Если вы хотите вызвать конструктор с числами, то вызывайте, внезапно, конструктор с числами:
    Any n(1, 15);
    Ответ написан
  • В чем разница 2ух кодов?

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

    Попробуйте ввести эти же 2 длинных числа, но поменять их местами, чтобы первое было коротким. Все работает?

    Сразу вижу 2 проблемы, вообще не обрабатывается случай num1.size() <= num2.size(). Во-вторых, в конце, где вы нормализуете число, если там окажется 11, где-то, то вы оставите в этом разряде 0, а не 1, как надо. Правда, при сумме двух чисел там 11 получится за длиной максимального числа не может появиться, ибо туда может прийти только +1 от переноса. Но код все-равно логически неверен.
    Ответ написан
    Комментировать
  • Как я могу конвертировать число в символ?

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

    На c++ можно делать так:
    (char)(x+'0')

    Этот код преобразует цифру x в символ, ей соответствующий. Лучше, правда приводить тип через static_cast.

    Еще можно воспользоваться всякими to_string, будет даже читабельнее, но медленнее.
    Ответ написан
  • Как найти последовательность букв через графы?

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

    Тогда постройте граф на n*m*l вершин. Каждая вершина соответствует тройке (x, y, k) и означает, что мы как-то походили по полю и оказались в координате (x, y), при этом набрав первые k символов искомой строки. Переходы в графе тут такие: от каждой вершины можно пойти в 4 соседние по координатам, а количество символов увеличивается на 1, если в следующей вершине читается следующая буква строки. Т.е. переходы вида (x, y, k) -> (x+1, y, k + (s[k] == grid[x+1][y] ? 1 : 0)); (x, y, k) -> (x, y+1, k + (s[k] == grid[x][y+1] ? 1 : 0)) и еще 2 на минус (если x,y не у стенки поля, естественно - некоторые переходы могут отсутствовать).

    Ищите кратчайшее расстояние из вершины (x0, y0, s[0] == grid[x0][y0] ? 1 : 0) в любую вершину с третим индексом равным l (т.е. любое место, где вы прочтете всю искомую строку). Поскольку в графе все ребра длины 1, можно запускать bfs. Граф строить и охранить не надо, можно эти 4 перехода вычислять неявно. Кладите в очередь тройки чисел, вынимайте их оттуда и вычисляйте до 4 соседних троек, которые гужно тоже сложить в очередь обхода в ширину. Удобно завести 2 костантных массива на 4 элемента, которые будут хранить приращения по x и по y в каждую их четрех сторон. Тогда не будет много дублируемого кода.

    Еще понадобится, таки, массив на n*m*l для хранения расстояния, или хотя бы пометок о том, что вершина уже в очередь была положена.
    Ответ написан
    2 комментария
  • Как в ировом движке на C++ распаралерить функции Update и Render?

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

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

    Можно гуглить "имя функции example" и тогда вы найдете в интеренете готовый код, работающий с этими функциями.
    Ответ написан
    Комментировать
  • Функция _kbhit в C++?

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

    Но тут ситуация другая. Майкрософт что-то намудрили cо стандартами и названиями. Чую тут какую-то долгую и запутанную историю полную костылей и заплаток. Я так понял, что _kbhit, это winapi функция, а kbhit - это сишная функция в стандартной библиотеке. Вторая просто вызывает первую. Но нельзя было сделать две функции с одинаковыми названиями, поэтому эти winapi-шные функции оставили с _ в названии.
    Ответ написан
    1 комментарий
  • Почему выражение (-1ll) в ассемблерном коде MSVC равно ff ff ff ff?

    wataru
    @wataru Куратор тега C++
    Разработчик на С++, экс-олимпиадник.
    Уловка в системе процессорных комманд: 48 c7 45 08 - позволяет загрузить в 64-битную ячейку памяти 32 битное число, автоматически расширяя его до 64 бит.

    Смотрите список кодов x64:
    0x48 - означает, что следующая комманда работает с 64-битами.
    0xC7 - mov immediate (данные в команде)
    Дальше идут флаги, указывающие как интерпретировать аргументы, что куда адресовывать и т.д.

    Но важно, что команда C7 работает с r/m16/32/64 данными, а аргумент у нее может быть только imm16/32 (третий столбец). Т.е. она принимает или 2 или 4 байта, в зависимости от обвеса, а записывать может до 64 бит. Сравните это с коммандой 0xB8 в той же таблице, она уже может принимать 64 бита.

    Если аргумент меньше ячейки памяти, то он расширяется (sign extended) до нужного размера (бит знака копируется влево до упора). Это позволяет записать числено равное значение в более битную ячейку. ведь 32-битное число 0xFFFFFFFF - это -1 в дополнительном бинарном коде, а 0xFFFFFFFFFFFFFFFF - это тоже -1 в дополнительном 64-битном коде.

    Компилятор использует вот эту команду, а не 0xB8, потому что сама команда короче, а исполняется так же быстро. Меньше кода, больше всего помещается в кеш и все работает быстрее, да и exe-шник меньше получается.
    Ответ написан
    2 комментария
  • Правильно ли я понимаю правила arithmetic conversions?

    wataru
    @wataru Куратор тега C++
    Разработчик на С++, экс-олимпиадник.
    Верно. Можно вставить исходник на сайте C++ insights и посмотреть, какие типы там где используются.
    Ответ написан
    Комментировать
  • Почему утверждается, что int32_t имеет ширину точно 32 бита, если он является всего лишь псевдонимом int, который может быть больше 32 бит??

    wataru
    @wataru Куратор тега C++
    Разработчик на С++, экс-олимпиадник.
    Смотрите документацию. Там действительно утверждается, что int32_t должен иметь размер ровно 32 бита ("exactly").

    Где вы взяли, что int32_t - это псевдоним int?
    Подозреваю, что там, где вы это видели, куча #ifdef и проверок архитектуры.
    Возмножно, на вашей системе, где int итак имеет 32 бита так оно и есть. При компиляции на другую архитектуру внезапно может оказаться, что int32_t - нифига не псевдоним к int.
    Ответ написан
    3 комментария