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

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

    Во-первых, он не компилируется. У вас там названия переменных кое где из двух слов состоят (А в других местах те же переменные с '_' идут - явно кто-то ошибся при перепечатывании текста).

    Во-вторых, тут подход немного через пятую точку. Не нужна вам строка из алфавита. Чтобы получить случайный символ, можно случайное число от 0 до 25 прибавить к 'a' - ведь символы в C++ - это целочисленные переменные, хранящие ASCII коды букв. B вот дизайнеры этих кодов были довольно умные дяденьки, поэтому английский алфавит идет там по порядку одним блоком.
    Ответ написан
    Комментировать
  • Сокращение функций в си++?

    wataru
    @wataru Куратор тега C++
    Разработчик на С++, экс-олимпиадник.
    3 комментария
  • Не фиксируемое количество аргументов 1 типа в c++?

    wataru
    @wataru Куратор тега C++
    Разработчик на С++, экс-олимпиадник.
    На выбор: std::initializer_list, variadic arguments, variadic templates.

    Примеры по ссылкам есть. Последнее - вообще оверкилл, и в вашем случае вообще не нужно. Советую использовать initializer_list.
    Ответ написан
    1 комментарий
  • Как реализовать приоритетную очередь с функциями extractMax и add, которая поддерживает одинаковые элементы?

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


    Если нумерация массива идет с 1, то два ребенка элемента i будут 2*i и 2*i+1. У вас же нумерация с 0, т.ч. у вас дети - 2*i+1 и 2*i+2.

    Первое условие достигается правильной расстановкой строгого и нестрогого неравнества в условиях в алгоритме.

    Похоже, проблема в том, что у вас нумерация с 0 и, если новый элемент оказывается итак максимальным, вы вернете индекс 0, вместо нужного 1. Если вы элемент вниз просеиваете, то у вас там +1 стоит в res.first, но изначально у вас-то там 0.

    Далее, вы вектор неправильно используете. Вы делаете reserve и потом работаете с пустым вектором, как-будто он фиксированного размера. Вам надо делать resize вместо reserve. Или еще лучше, вместо вашей переменной size вы используйте arr.size(). При изменении размера массива делайте pop_back() и push_back().
    Ответ написан
    8 комментариев
  • Ошибка в конструкторе при передаче массива c++?

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

    Вот так работает:
    int data[] = {90, 90};
    Array<int, 3> arr (data);


    Ну не может компилятор по Array<int, 3> arr { 90,90 }; догадаться, что {90, 90} - это числа в массиве, адресс которого надо передать.

    Кстати, у вас тут ошибка: Array вы создали на 3 элемента и копируете 3 элемента, а данных задали только 2.
    Ответ написан
  • Почему неправильно решает задачу?

    wataru
    @wataru Куратор тега C++
    Разработчик на С++, экс-олимпиадник.
    Небольшое замечание: можно код сильно ускорить, применяя математику. Можно взять все номера букв по модулю 26, тогда a=1, ... y=25, z=0. Тогда операция будет - умножение на 2 и взятие по модулю 26 (для 'a' все также выдаст 'b', для 'z' все так же выдаст 'z'). До этого можно додуматься, потому что вот это вот "вычитание 26" - ну очень похоже на операцию взятия по модулю 26.

    Применение этой операции 2024 раза равносильно умножению на 2^2024 по модулю 26. Воспользовавшисть теоремой эйлера, это равносильно умножению на 2^(2024 % 12) = 2^8 = 128. Далее, умножение на 128 по модулю 26 равносильно умножению на 24.

    Т.е. можно умножать один раз на 24 вместо 2024 умножений на 2 (и в конце взять по модулю 26).
    Ответ написан
    Комментировать
  • Как сделать скрин на C++?

    wataru
    @wataru Куратор тега C++
    Разработчик на С++, экс-олимпиадник.
    На винде? Кроме gdi+ можно ещё через directx (гуглите dxgi duplicator) или через windows graphics capture api. Но последние 2 не работают в старых системах.

    Если же вам только посмотреть на несколько пикселей, то можно и в gdi+ делать скриншот лишь маленькой части, или вообще ничего не копировать и смотреть на цвет пикселей в экранном DC.
    Ответ написан
    1 комментарий
  • Как получить случайные числа в C++?

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

    srand устанавливает состояние генератора псевдослучайных чисел. В качестве seed вы там используете количество миллисекунд, которое целую миллисекунду одинаковое, поэтому состояние генератора у вас в каждой функции rand_offer одно и то же - поэтому числа и генерируются одни и теже. sleep(1) лечит проблему потому, что следующий вызов посчитает другое значение count_ms.
    Ответ написан
    Комментировать
  • Таблица истинности С++. Почему здесь разные результаты?

    wataru
    @wataru Куратор тега Математика
    Разработчик на С++, экс-олимпиадник.
    ( x == z) || (!x || (y && z)) == 0 означает ( x == z) || ( (!x || (y && z)) == 0 ).
    Приоритет у сравнения выше, чем у ||, которое, по идее, есть лишь часть считаемого выражения. Поэтому у вас полечается не "выражение == 0" а "выражение1" или "выражение2 == 0".
    Возьмите все ваше выражение в скобки и все заработает.

    Во втором куске кода у вас 2 отдельных выражение сравнивается с 0 и скобочки у вас там расставлены правильно.
    Ответ написан
    1 комментарий
  • Как реализовать операторы в классе математического вектора?

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

    Вектора можно перемножать. Скалярное или вектороное произведения. Чаще скалярное ставят на operator*, а векторное на какое-нибудь operator^

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

    wataru
    @wataru Куратор тега C++
    Разработчик на С++, экс-олимпиадник.
    {
      thread gameThread(game_loop, ref(star_pleced), ref(staircase_placed), ref(c), ref(t_placed), ref(r_placed), ref(p_placed), rows, cols, ref(map));
      thread monsterThread(monster_move, ref(map));
      gameThread.join();
      monsterThread.join();
      refresh();
    } while ((c = getch()) != '0');


    Этот код запускает потоки (они один раз исполняются) потом ждет их завершения. И это в цикле.
    Проблема в том, что на каждой итерации этого цикла вы будете ждать, пока monster thread спит.

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

    Потоки должны быть запущены один раз и работать в фоне. Тот, который каждую секунду что-то делает, должен внутри содержать цикл и работать бесконечно, на каждой итерации засыпать на 1 секунду.
    Ответ написан
    Комментировать
  • Как исправить ошибку -nan(ind) в С++?

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

    Другая опасность в вашем коде: логарифм отрицательных чисел. Закомментируйте log в вашем выражении, если результат где-то отрицательный - функцию в этом значении x тупо не вычеслить - оно вне области определения.
    Ответ написан
  • Возможна ли гонка данных при отправке их на сокет?

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

    Вот эта часть кода, что по вашему делает? Почему sendto возвращает количество байт, а не код ошибки?

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

    Это связано с тем, что сокеты работают на низком уровне и не гарантируют сохранение порядка отправленных данных. Когда два приложения отправляют данные одновременно, они могут перемешиваться в процессе передачи по сети и приходить в произвольном порядке.


    А это очередная галлюцинация ГПТ. Забудьте эти слова - они не имеют ничего общего с реальностью.

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

    wataru
    @wataru Куратор тега C++
    Разработчик на С++, экс-олимпиадник.
    После while (collision && try_counter <= 100); вставьте:
    if (try_counter > 100) break;

    Добавьте отладочный вывод в каждый цикл - посмотрите, а в каком же цикле оно висьнет-то.
    Вам еще понадобиться try_counter в цикл по монстрам (while (map[py][px] != ' ')).

    А вообще, очень странный цикл вот:
    do
            {
                center_y = ry + (r_size_y / 2);
                center_x = rx + (r_size_x / 2);
            } while (map[center_y][center_x] != ' ');


    Тут явно какая-то ошибка, потому что center_x и center_y на каждой итерации получатся одинаковые и цикл или сразу закончится, или повиснет.
    Ответ написан
  • Возможно ли избежать ошибку чтения в массиве если алгоритм задействует ячейку которой нет?

    wataru
    @wataru Куратор тега C++
    Разработчик на С++, экс-олимпиадник.
    Для игры "жизнь" есть несколько вариантов:
    1) Увеличить поле на 2 клетки по каждому измерению, поле будет храниться с 1, а индексы 0 и n+1 - всегда будут пустыми. Потребление памяти это почти не увеличит, а код упростит.
    2) Если соседние клетки считаются циклами, то можно границы области 3x3 пересечь с полем:
    for (int nx = max(0, x-1); nx < min(x+2, n); ++nx) {
      for (int ny = max(0, y-1); ny < min(y+2, n); ++ny) {
        if (nx == x && ny == y) continue;
        // {nx, ny} - сосед в поле, обрабатываем его.
      }
    }

    Можно код чуть ускорить, предподсчитав границы.
    3) Более читаемый, но чуть более медленный метод - явно проверять, а не за границей ли соседняя клетка:
    for (int nx = x-1; nx <= x+1; ++nx) {
      for (int ny = y-1; ny <= y+1; ++ny) {
        if ((nx == x && ny == y) || nx < 0 || ny < 0 || nx >= n || ny >= n) continue;
        // {nx, ny} - соседняя клетка.
      }
    }


    Я бы просто раздул поле - так код сильно проще.

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

    wataru
    @wataru Куратор тега C++
    Разработчик на С++, экс-олимпиадник.
    Вы случайным образом генерируете координаты комнаты в цикле, пока вам не повезет выбрать полностью пустое место (while (collision == true);).

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

    Вам надо полностью переделать подход к генерации комнат. Или разрешите им пересекаться, или требуйте чтобы комнаты по прощади занимали сильно меньше всего пространства. Далее, если у вас очень много попыток было сделано, а вы так и не нашли пустое место для комнаты - надо перезапустить всю генерацию заново. Вы там try_counter уже считаете, но никак на него не реагируете.

    Еще можно сделать немного по другому - вместо случайного выбора места и потом проверки на пересечение, найдите все места, куда комнату можно впихнуть и из их списка выбирайте случайное одним rand(). Тут уже не будет цикла, завершающегося только когда вам повезло. Но тут тоже может быть проблема, что мест для размещения новой комнаты вообще нет. Или перезапускайте с нуля расстановку комнат, или требуйте, чтобы они были маленькие. Еще можно их ставить в порядке от больших к маленьким.
    Ответ написан
    2 комментария
  • Не могу, понять как компьютер перемещает свой знак?

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


    Вот этот код ставит фигуру в текущую клетку: board[move] = computer;
    Двумя строчками ниже этот ход откатывается: board[move] = EMPTY;

    found = winner(board) == computer; - этот код присваивает булевой переменной found значение выражения winner(board) == computer.
    Ответ написан
    9 комментариев
  • Что быстрее индексы или указатели?

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

    Практический совет - лучше писать через индексы, ибо так понятнее и больше шансов что компилятор там все наоптимизирует (например, он сможет векторизовать работу через какие-нибудь SSE инструкции процессора).

    Совет по бенчмарку - если памяти не хватает, стоит по одному достаточно большому массиву пройтись 10000 раз. А лучше использовать готовые фреймворки для измерения скорости, вроде того де gbenchmark.

    Еще, иногда полезно посмотреть на ассемблерный выхлоп. Вот, например, что происходит при -O3 опции компилятора. Он генерирует вообще идентичный код для обеих функций (развернув циклы)! И даже при -O2 оно одинаковый код выдает.

    Без оптимизаций код разный, но там все не так как вы думаете. Вместо инструкции mov eax, dword ptr [rax + 4*rcx] в варианте с индексами используется инструкция mov eax, dword ptr [rax] для указателей. Это самое "складывание с указателем массива" вообще не отдельная операция - а вариант адрессации в инструкции mov. Они могут вообще одинаковое количество тактов занимать, это надо мануал по конкретной архитектуре процессоров читать.
    Ответ написан
    Комментировать
  • Как обеспечивается совместимость динамических библиотек при ликовке в рантайме?

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

    wataru
    @wataru Куратор тега C++
    Разработчик на С++, экс-олимпиадник.
    Вообще, работу с указателем на base тоже надо переписать через memcpy. Потому что это UB. Вдруг выравнивание у массива не такое, как у структуры Base. Без memcpy тут никак. Другого способа разместить 2 структуры в памяти подряд компактно - нет.

    Edit: конечно, можно объявить вашу стоуктуру где поля base и S1 идут рядом, но там будет какой-то padding. Работать с этим как с сериализированным массивом байт - нельзя.
    Ответ написан
    1 комментарий