Задать вопрос
Ответы пользователя по тегу C++
  • Можно ли обратиться к полю дочернего класса через указатель на базовый?

    wataru
    @wataru Куратор тега C++
    Разработчик на С++, экс-олимпиадник.
    Если вы точно знаете, что это именно экземпляр дочернего класса, то можно скастовать к дочернему через dynamic_cast, или вернуть скастованный указатель на дочерний класс через какой-нибудь виртуальный метод Derived* GetDerived(). Без какого-либо преобразования к дочернему классу - не получится. Не упоминать этот дочерний класс - тоже. Только если вы это поле/метод выведите в виртуальный метод базового класса.
    Ответ написан
    Комментировать
  • Как вернуть до пяти типов из одной функции?

    wataru
    @wataru Куратор тега C++
    Разработчик на С++, экс-олимпиадник.
    Надо возвращать указатель на базлвый класс. Ну и, один из 5 экземпляров надо создавать через new.
    Ответ написан
    8 комментариев
  • Нужно ли здесь выравнивание на стеке?

    wataru
    @wataru Куратор тега C++
    Разработчик на С++, экс-олимпиадник.
    Раз вы просто копируете через memcpy, то никаких проблем не должно быть.
    А еще, вы уверены что std::swap сам эту оптимизацию уже не применяет? Зачем вы какие-то свои велосипеды строите?
    Ответ написан
  • 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 комментарий