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

    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 комментария
  • Почему tellg() неявно приводится к int при инициализации int, но не может быть сложенным с int?

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

    Если смотреть описание возвращаемого типа, то там есть operator+ с каким-то streamoff, а с int - ничего нет. Там, правда, не указано, что есть опретор преобразования к int, так что это, наверно, тоже лучше не использовать.
    Ответ написан
    Комментировать
  • Калькулятор C++ как убрать 1.33333e+06 подобные результаты вычисления?

    wataru
    @wataru Куратор тега C++
    Разработчик на С++, экс-олимпиадник.
    Выводить в фиксированном виде:
    std::cout << std::fixed;  // Меняем формат вывода вещественных чисел 
    std::cout.precision(10);  // Сколько вы там хотите знаков после запятой выводить.
    double e = 1.3333e6;
    std::cout << e;  // 1333300.00000000000;
    Ответ написан
    1 комментарий
  • Как убедиться что атомарные операции будут выполнены точно правильно?

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

    В стандартной библиотеке самое близкое к этом - std::condition_variable.

    Платформо зависимое решение может быть эффективнее. Какие-нибудь WaitForSingleObject/CreateEvent в винде, например.
    Ответ написан
    Комментировать
  • Как мониторить изменения буфера обмена?

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

    Рекомендуется использовать Clipboard Format Listener. Надо будет вызвать AddClipboardFormatListener и потом обрабатывать сообщение WM_CLIPBOARDUPDATE. Гуглите эти слова (+ example), и найдете кучу готовых примеров в интернете.
    Ответ написан
  • Не знаете как можно исправить ошибки на с++?

    wataru
    @wataru Куратор тега C++
    Разработчик на С++, экс-олимпиадник.
    Вам надо описать конструктор Ball без параметров. Например:
    Ball() x(0), y(0), r(0), vx(0), vy(0) {}

    Потому что new Ball[n] Создает n объектов, но конструктора по умолчанию (без параметров) у класса Ball нет. Обычно его генерирует компилятор сам, но только если вы не указали никаких своих конструкторов. А new не знает, какие числа передавать в качестве x, y, r и т.д.

    Смотрите правило трех.
    Ответ написан
    Комментировать
  • Как конвертировать steady_clock::time_point в system_clock::time_point и наоборот?

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

    Вообще, если вам надо эти двое часов переводить в друг друга, то вы что-то не так делаете.
    Ответ написан
    Комментировать
  • Как сделать перестановку с повторением в C++?

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

    Вот есть статья на хабре, даже с кодом, правда на go.

    Но сам алгоритм там простой, без труда переведете на си++.
    Ответ написан
    9 комментариев
  • Ошибка вывода списка C++?

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

    Ошибка об этом и говорит, что никто не реализовал оператор << для списка.

    Если вы хотите выводить список, вам надо руками реализовать этот вывод. Циклом пройдитесь по всем элементам и выводите их, разделяя пробелами или чем вам там надо.

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

    wataru
    @wataru Куратор тега C++
    Разработчик на С++, экс-олимпиадник.
    Figure** figure_colletion = new Figure * [this->collection_size];


    Вот тут в конструкторе вы заводите локальную переменную (с тем же именем, что и член класса) и что-то с ней делаете. Она "затенняет" член класса. А вот figure_colletion, к которому вы обрашаетесь в методе select_new_figure() - это уже член класса, который вы нигде не выделили и ничем не заполнили.

    Поэтому любой уважающий себя стиль форматирования кода подразумевает, что члены класса должны быть приватными и как-то по особому именоваться (например, заканчиваться на "_", или начинаться с "p") тогда бы вы этой ошибки не совершили. Еще можно включить предупреждения при компиляции.

    И еще, писать в методах this-> перед каждым обращением к члену класса не обязательно.
    Ответ написан
    1 комментарий
  • Как получить адрес памяти переменной в массиве, а не адрес индекса массива?

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

    Edit: и вы через массив к исходному line никак не обратитесь, только если не смените тип массива на Figure*
    Ответ написан
    Комментировать
  • Как сделать динамическую подгрузку кода?

    wataru
    @wataru Куратор тега C++
    Разработчик на С++, экс-олимпиадник.
    C++ - компилируемый язык. Соответственно, вы содержимое строки в нем никак не исполните, только если не напишите свой интерпретатор или не скомпилируете код в строке как-то подобно JIT. Можно подключить библиотеку с какой-нибудь Lua и код на Lua исполнять. Или подгружать в специально выделенную память скомпилированный заранее (или библиотекой) машинный код и передавать управление ему (но это надо знать ассемблер, про страницы памяти, API операционной системы и все такое. Это очень сложно). Вообще, C++ - не лучший выбор для динамической подгрузки кода.

    defineCode(std::cout << 13 << std::endl); // work
    Работает, потому что тут макрос просто подставляет код в скобках вместо себя и он компилируется и выполняется.

    defineCode(stringLine); заменяется просто на stringLine, что есть бессмысленное выражение, вырезаемое еще на этапе компиляции.
    Ответ написан
    Комментировать
  • Как работать с большими числами в C++?

    wataru
    @wataru Куратор тега C++
    Разработчик на С++, экс-олимпиадник.
    Если числа такие большие, что ответ никуда не влезает, то надо писать длинную арифметику. Цифры числа храните в массиве, складывайте/умножайте в столбик. Удобно хранить числа развернутыми. Гуглите "длинная арифметика" - найдете и код с примерами и кучу статей.

    Но вам это, скорее всего, и не надо. В комбинаторных задачах часто все сокращается и можно получить ответ не считая очень большие числа.

    Ваш код так ужасен, что я не могу понять, что вам там надо подсчитать в итоге, но уже брасается в глаза, что у вас там считается число сочетаний. Во-первых, можно считать (n-k+1*k+2*..*n)/k!, что уже дает более мелкие числа.

    Потом, можно считать треугольником паскаля. Можно даже считать только одну строку, домножая и деля на одно число - тоже не получая в процессе чисел больше ответа.

    Если bills не больше 64, то все влезет в стандартный unsigned long long.

    Примеры дальше в вашей задаче точно не нужны, но для кругозора опишу и их.

    Если в задаче более сложная формула, то можно хранить числа в виде их факторизации на простые числа. Поддерживайте массив в котором будете хранить степени всех простых чисел до некоторого максимального. При умножении прибавляйте, при делении вычитайте. В конце все оставшееся перемножте.

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