• Как создать универсальный треугольник(наконечник стрелы), не только прямой x.x == y.x, но и под наклоном и т.д.?

    zagayevskiy
    @zagayevskiy
    Android developer at Yandex
    Кратко так - представь, что ты рисуешь треугольник в начале координат (0, 0). Поверни его вокруг начала координат (матрицей поворота), и затем смести его так, чтобы координаты конца отрезка совпали с координатами вершины треугольника. Для этого просто прибавь dx и dy.
    Ответ написан
    2 комментария
  • Android NDK Error: no matching member function for call to 'push_back'?

    @MarkusD Куратор тега C++
    все время мелю чепуху :)
    class rck{
    public:
        unsigned short x,y;
        void show();
        int tm=0;
        uint8_t type=0;
    };

    Вольное комментирование состояния кода
    Тут у нас большие проблемы с читаемостью кода. stdint соседствует с сырыми конструкциями модификации типа, методы вперемешку с полями, класс вместо структуры, использование запятой при объявлении полей, имена в одну букву и акронимы. Неинициализированные поля - распространенный источник ошибок.

    Лучше будет с молоду учиться правильно оформлять свой код. Например так.
    struct rck final
    {
    	uint16_t x = 0;
    	uint16_t y = 0;
    	int32_t tm = 0;
    	uint8_t type = 0;
    	
    	
    	void show();
    };

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


    У тебя объявлен, вроде бы, агрегатный тип с неявным конструктором по умолчанию, в котором выполняется инициализация только полей tm и type.

    rock.push_back({(uint16_t)(x*64),(uint16_t)(y*64),0,0});

    Тут перед обращением к push_back формируется фиктивный std::initializer_list<uint16_t> с двумя элементами внутри.
    В общем смысле, до полного списка аргументов нужно указать еще два аргумента. Тогда эту запись можно будет считать агрегатной инициализацией временного объекта типа rck.

    Такая форма агрегатной инициализации стандартизирована в C++11. До C++14 агрегатная инициализация отключается для типов, в которых присутствует инициализация полей по месту объявления (в коде это поля tm и type). Каждый следующий стандарт требования к агрегатной инициализации только ужесточает.

    GCC давно славится своей слабой поддержкой стандарта языка. Это означает что если код проходит трансляцию g++, это далеко не факт что он соответствует стандарту.
    NDK сегодня для сборки использует clang, который на данный момент считается максимально приближенным к стандарту транслятором.

    Все это должно дать понять что данный код не соответствует стандарту языка и не должен компилироваться. Подходящего конструктора от двух аргументов для типа rck не определено и тип не является агрегатным.
    То, что g++ смог собрать этот код, останется на совести g++.
    Еще одним важным моментом будет точное понимание, какой именно стандарт языка выбран для трансляции твоего кода.
    Ответ написан
    1 комментарий
  • Как пофиксить warning "Expression result unused" в C++ компилятора LLVM?

    Chronicler
    @Chronicler
    Программист
    Чтобы дождаться нажатия любой клавиши, традиционно используется std::cin.get()
    Ответ написан
    2 комментария
  • Возможно ли писать на C++ со вставками C?

    Chronicler
    @Chronicler
    Программист
    Можно и очень легко. Просто выделите в вашем проекте Си код в отдельный файл с расширением .c
    Ответ написан
    Комментировать
  • Что лучше использовать #include или LoadLibrary?

    @MarkusD Куратор тега C++
    все время мелю чепуху :)
    Вопрос, на самом деле, заключается не в выборе межу LoadLibrary и #include, а в выборе между явным и неявным связыванием.

    При неявном связывании компоновщик добавляет в PE-секцию импорта дополнительный блок импорта конкретно указанной библиотеки. Этот блок обрабатывается загрузчиком PE в момент подготовки к запуску процесса. Эта информация тебе уже должна быть знакома. К моменту передачи управления в точку входа процесса все неявно связанные библиотеки уже загружены и готовы к работе. Код процесса не нуждается в явном управлении загрузкой таких библиотек.

    Явное связывание выполняется полностью кодом процесса, для чего и применяется набор функций для работы с библиотеками. Явное связывание - это большая рутина. Но иногда без этой рутины никак.
    Поиск динамических библиотек при работе LoadLibrary[?] осуществляется в соответствии с определенным порядком. При этом, путями для поиска динамических библиотек можно управлять в ручном режиме, добавляя новые или замещая имеющиеся пути поиска.

    Директива препроцессора #include[?] лишь косвенно относится к вопросу. На самом деле к вопросу относится директива #pragma comment( lib )[?].
    Прагма работает только для cl - компилятора от Microsoft. Подключаемая таким образом статическая библиотека должна находиться в перечисленных Library Path, в настройках сборки проекта. Эта прагма является альтернативой прямого указания статической библиотеки в настройках сборки проекта.
    Эту директиву любят использовать в сторонних заголовках, код для которых поставляется только в бинарном виде, в статических или динамических библиотеках. Вместе с динамической библиотекой такого решения поставляется и библиотека статическая, в которой находятся инструкции для неявного связывания с динамической библиотекой. Результатом работы #pragma comment( lib ) с такой статической библиотекой будет неявное связывание твоего кода с указанной динамической библиотекой.

    Размер PE ощутимо растет при компоновке из статических библиотек.
    Явное и неявное связывание слабо влияют на размер PE, но явное связывание усложняет жизнь разработчика, т.к. поддерживать загрузку интерфейса библиотеки разработчику придется самому.
    Ответ написан
    Комментировать
  • Почему использование пространства имен std считается плохой практикой?

    Adamos
    @Adamos
    Например, потому, что в пространстве std хренова туча объявленных в библиотеке функций, про которые вы, возможно, даже не подозреваете. И можете назвать свою собственную функцию так же. Даже не подозревая, что при каждом ее вызове компилятор теперь сомневается, которую использовать - вашу или библиотечную. И решение в пользу библиотечной (например, потому, что вы ошиблись в аргументах) окажется для вас сюрпризом.
    Ответ написан
    4 комментария
  • Как ускорить решение на c++?

    @Mercury13
    Программист на «си с крестами» и не только
    Вы тут что-то ухитрились написать, но всё равно n². Потому и TL.

    Пусть для каждого поддона длина — большее из измерений, ширина — меньшее. Теперь условие «поддон А можно поставить на поддон Б» упрощается.

    Очевидно, что поддоны, которые нельзя поставить друг на друга, будут возрастать по одному измерению и убывать по другому. (Иначе мы сортанём по длине, по ширине тоже обнаруживаем неубывание — и, сюрприз, эти поддоны становятся!)

    Получаем список поддонов, которые не становятся ни на кого. Проще всего хранить его в виде set с сортировкой по длине, при этом ширина убывает.

    Нам приходит новый поддон. Упорядочиваем координаты, затем ищем в списке equal_range по длине.

    Для «БОЛЬШЕЙ» части списка [LOWER_bound, end): наш поддон можно поставить на все эти поддоны по длине, и только на первые из них — по ширине. Если l_b=end, или наш поддон не встаёт на *l_b — добавляем поддон в список. Но не сразу, а после проверки меньшей части.

    Для «МЕНЬШЕЙ» части списка [begin, UPPER_bound): все эти поддоны можно поставить на наш поддон по ДЛИНЕ, и только некоторый хвост [some_pallet, upper_bound) — по ширине. Находим этот кусок и исключаем из дерева.

    А теперь вопрос: как хакнуть наш set, чтобы можно было проводить поиск за log n и по длине, и по ширине?
    А для этого пишем свой объект-сравниватель, который можно переключать между двумя вариантами: length1<length2, либо width1>width2;

    P.S. Не очень понятно условие «один поддон становится на другой» — ни из описания, ни из примера. Мой алгоритм — length1 <= length2, width1 <= width2. Если, например, оба строго меньше (length1 < length2, width1 < width2) — то большая часть будет [u_b, end), меньшая — [begin, l_b), и из-за непересечения этих частей не обязательно добавлять в список отложенно.
    Ответ написан
    7 комментариев
  • Как решить данную задачу по курсовой на языке С++?

    wataru
    @wataru Куратор тега C++
    Разработчик на С++, экс-олимпиадник.
    Вам ДАНА матрица. Значит в программе надо
    1) прочитать числа N и M (заведите 2 переменные и прочитайте их, через cin)
    2) Завести N*M матрицу. В C++ стандартом для массивов является класс vector. Двумерный массив - это вектор векторов.
    vector<vector<int>> a(n);
    Это создаст вектор из n векторов, но они все будут пустые. Надо во время считывания ( у вас будет 2 вложенных цикла) перед считыванием i-ой строки i-ый вектор отресайзить вызвав a[i].resize(m). И далее можно будет читать a[i][j]
    3) Теперь, собственно, алгоритм. Найдите наибольший элемент. Для этого заведите 3 переменные - текущий максимум (можно инициализировать a[0][0]) и его координаты mx и my (инициализируйте нулями). Пройдитесь по матрице двумя вложенными циклами и, если текущий элемент больше максимума - перезапишите максимум и запомните текущие переменные циклов в mx и my.
    4) Теперь поменяйте местами 0-ую строку со строкой в которой максимум. Для этого одним циклом пройдитесь по столбцам (от 0 до M-1) и поменяйте местами a[0][j] и a[mx][j].
    5) Теперь то же самое, но по столбцам. Цикл от 0 до N-1 и меняйте элементы a[i][0] и a[i][my].
    6) В конце выведите матрицу двумя вложенными циклами.

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

    tsarevfs
    @tsarevfs Куратор тега C++
    C++ developer
    Используйте std::vector. Это массив который может расширяться во время работы программы. Обычно это хороший выбор вместо массивов почти во всех случаях. Смотрите методы push_back или resize.
    Ответ написан
    1 комментарий
  • Как создать папку с учетом имени пользователя c++?

    @MarkusD Куратор тега C++
    все время мелю чепуху :)
    Для современных версий ОС Windows в наборе WinAPI присутствует функция SHGetKnownFolderPath[?].
    Она позволяет получить путь к некоторым предварительно определенным папкам, набор которых описан абстракцией KNOWNFOLDERID[?].

    Тебе подойдет FOLDERID_Desktop для получения папки рабочего стола пользователя.
    При работе с этой функцией очень важно не забывать пользоваться функцией CoTaskMemFree[?] для освобождения памяти, переданной из функции через указатель ppszPath.

    Небольшой пример использования
    wchar_t* path_buffer = nullptr;
    if( FAILED( ::SHGetKnownFolderPath( FOLDERID_Desktop, KF_FLAG_DEFAULT, 0, &path_buffer ) ) )
    {
    	::CoTaskMemFree( path_buffer );
    	LOG_ERROR( LOG_CHANNEL, "Failed to get known directory; error - #{:08X}.", ::GetLastError() );
    	// terminate ...
    }
    
    std::wstring user_desktop_path{ path_buffer };
    ::CoTaskMemFree( path_buffer );
    
    // whatever with `user_desktop_path` ...
    Ответ написан
    Комментировать
  • В какой университет из этих лучше поступить?

    @Atrelya92
    Крушу некрушимое
    Закончила МАИ по специальности инженер. Слабая подготовка именно в IT-направлении, устаревшая программа обучения. Поэтому, если вы хотите чисто "зацепиться". вам подойдёт. Опять-таки за последние года три МАИ сильно вырос по многим показателям. И достаточно простая учёба открывает двери в понимание, в каком бы направлении ты хотел бы развиваться. И да, платить, смысла реально нет. Сейчас решает не корочка,а опыт работы и набор знаний.
    Ответ написан
    Комментировать
  • В какой университет из этих лучше поступить?

    @hairygeek
    В телеграмме есть группа sns_young, где сейчас очень активно обсуждают эти вопросы. Советую перенаправить свой вопрос туда
    Ответ написан
    Комментировать
  • Как работают побитовые операторы?

    0177 - это число в восьмеричной системе счисления = 0111 1111 в двоичной
    Допустим, n = 1111 1010 1010 в двоичной с.с.

    1 & 0 = 0
    0 & 0 = 0
    1 & 1 = 1

    тогда получаем:
    0000 0111 1111
    1111 1010 1010
    ---------------
    0000 0010 1010
    Ответ написан
    Комментировать
  • Как правильно передать в метод массив и получить обратно массив другого размера?

    @MarkusD Куратор тега C++
    все время мелю чепуху :)
    Тебе не нужны new и сырые указатели. Тебе нужен линейный контейнер с хранением элементов в непрерывном блоке памяти. Это будет или std::vector, или std::array.

    Для начала можно остановиться на векторе. Еще одним важным типом будет std::span[?] или gsl::span[?][S] если ты не можешь пользоваться C++20.

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

    Вот объвление твоей функции: gsl::span<float> Метод( gsl::span<float> values ).
    span - это не владеющий памятью тип, обозначающий участок непрерывной памяти с данными определенного типа. span очень легок и является value type - т.е. создан чтобы его передача по значению не приводила к ощутимым нагрузкам. span конструируется из std::vector, std::array, плоских массивов, std::unique_ptr<[]> и сырых блоков памяти.

    В своей функции тебе стоит работать с памятью values, считая попутно, сколько элементов ты обработал. А для возврата обработанного участка данных тебе будет достаточно вызвать subspan.

    Псевдокод
    std::span<float> Метод( std::span<float> values )
    {
    	size_t processed_count = 0;
    	for( float& element : values )
    	{
    		// ... обработка значений
    		// ... изменение processed_count
    		// ... условия обрыва цикла
    	}
    	
    	return values.subspan( 0, processed_count );
    }
    
    int main()
    {
    	std::vector<float> values{ 7.83f, 14.1f, 20.3f };
    	std::span<float> processed_values = Метод( values );
    	
    	for( const float& value : processed_values )
    	{
    		std::cout << value << ' ';
    	}
    	
    	return 0;
    }
    Ответ написан
    2 комментария
  • Почему я получаю неверный ответ?

    wataru
    @wataru Куратор тега C++
    Разработчик на С++, экс-олимпиадник.
    Вы говорите, что пытаетесь брать числа, чтобы "портить" меньшие биты, но ведь это может быть не так.
    Если у вас числа 4,4,4,4,5,6,1,1 - то выгодно брать именно 6, потому что оно сделает второй бит единицей, что никак невозможно сделать, взяв 5.
    У вас неправильное решение задачи.

    Правильное решение такое: Найдите самый старший бит, в котором нечетное количество единиц в массиве a.

    Если таких нет - то ответ Draw. Потому что, если в каком-то разряде единиц четное количество, и x из них достанется первому игроку, то второму достанется 2k-x, что будет иметь ту же четность, что и x. А значит в этом разряде итоговые значения отличаться не могут вообще. Как числа не распределяй, даже если игроки могут делать разное количество ходов.

    Теперь мы знаем, что в этом разряде различие точно будет. Потому что нельзя нечетное количество единиц распределить на 2 группы с одинаковой четностью. Победа определяется только этим разрядом, ведь он самый старший из различий. Теперь у нас есть 2k+1 чисел c 1 в этом разряде и n-2k-1 чисел с 0 в этом разряде. На биты дальше смотреть не надо - кто возьмет нечетное количество чисел из 2*k+1 - тот победил.

    Т.е. вам дальше надо решить совсем простую задачу: Дана пара чисел (i,j), i - нечетно, есть i нужных объектов и j ненужных, игроки по-очереди берут объекты. Кто возьмет нечетное количество нужных объектов - тот и победил.

    Тут для вывода решения можно написать динамическое программирование, которое для пары (i,j) - будет говорить, сможет ли игрок взять четное/нечетное количество нужных чисел, если их i, и еще есть j ненужных. При расчете перебирайте варианты, какой из типов объектов берется и смотрите, а сможет ли оппонент вам четность испортить на меньшей задаче.

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

    Мне лень решать дальше задачу, но похоже, что при i=1 ответ - WIN, при i>0 - ответ Win, если i+j=n - четно. Иначе - Lose.
    Ответ написан
    4 комментария
  • Проект для новичка?

    Посоветую просматривать вопросы по тегу
    C++
    данного ресурса, возможно пытаясь решить вопросы тега вы приобрете определенный опыт работы с данным языком.
    Ответ написан
    1 комментарий
  • Занимает ли переменная какую-нибудь память после ее объявления?

    15432
    @15432
    Системный программист ^_^
    Зависит от компилятора. Больше вам скажу, точно занимают память лишь статические переменные, любые другие могут быть регистровыми
    Ответ написан
    Комментировать
  • Занимает ли переменная какую-нибудь память после ее объявления?

    @majstar_Zubr
    C++, C#, gamedev
    1) не иденцифированная, а не инициализированная.
    2) в данном случае, память выделяется на стэке.
    Ответ написан
    Комментировать
  • Какой codestyle для написания методов допустим?

    maaGames
    @maaGames
    Погроммирую программы
    Не нормальна.
    Нехорошо давать те имена, которые уже присутствуют в области видимости, даже если "это компилируется".
    Не стоит забывать, что психованный маньяк, который будет читать твой код, знает где ты живёшь.
    Ответ написан
    Комментировать