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

    wataru
    @wataru Куратор тега Математика
    Разработчик на С++, экс-олимпиадник.
    Функция генерирует все разбиения числа n на слагаемые не больше maxx. Ддя этого ыункуия перебирает, а какое же максимальное число будет в разбиении (цикл по i), берет это число и рекурсивно разбивает оставшуюся часть. Обратите внимание, в качестве maxx в рекурсии передается i. Ведь именно это было максимальное число в перебираемом разбиении. Значит следующее не может его превышать.

    Вся эта сложность с максимальным числом сделана, что бы не перебирать перестановки слагаемых. Ведь 4=1+2+1 можно по идее получить тремя способами, меняя порядок. Генерируя слагаемые в не возрастающем прядке, мы избавляемся от таких дубликатов.
    Ответ написан
    Комментировать
  • Почему не получается вывести из файла данные с помощью переопределенного оператора вывода?

    wataru
    @wataru Куратор тега C++
    Разработчик на С++, экс-олимпиадник.
    Внимательно читайте свой код:
    std::ofstream out("/home/artem/Рабочий стол/EntryFile/NewFile");
    std::ifstream  in("/home/artem/Рабочий стол/EntryFilee/NewFile");


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

    wataru
    @wataru Куратор тега C++
    Разработчик на С++, экс-олимпиадник.
    Сначала перемешайте слова. Возьмите массив длины NUM_WORDS чисел и заполните его изначально индексами от 0 до NUM_WORDS-1. Перемешайте. Потом сделайте цикл по словам, который будет загадывать слово с индексом вот из этого массива. Внутри while(true) будет спрашивать пользователя, пока он не угадает. Т.е. вот этот ваш код весь выносится в отдельную функцию и вместо случайной генерации choice, получает его в качестве параметра. Можно через возвращаемое значение сообщать о том, что пользователь попросил выйти.

    И еще, чтобы перемешать случайно слово/массив индексов надо делать вот так (а не так, как у вас):
    for(int i = 0; i < length; ++i) //меняет буквы местами
        {
            int prev = (rand() % (i+1));
            char temp = jumble[prev];
            jumble[prev] = jumble[i];
            jumble[i] = temp;
        }


    Надо не менять местами два случайных символа, а менять i-ый со случайным предыдущим. А то у вас не все перестановки генерируются одинаково равновероятно.
    Ответ написан
    1 комментарий
  • Чем обусловлены различия в работе со строками и другими массивами?

    wataru
    @wataru Куратор тега C++
    Разработчик на С++, экс-олимпиадник.
    Различия обусловнены тем, что строки - особый вид массивов. Весьма частый и использующийся повсеместно. Плюс, в отличии от обычных массивов, в строках есть нулевой завершающий байт. Поэтому некоторые вещи стандартом Си были добавлены в язык отдельно для строк. Как, например, инициализацию const char* строковым литералом, или инициализацию массива с рассчетом его размера (учитывая нулевой символ в конце). Оно же потом перекочевало в Си++.
    Ответ написан
    Комментировать
  • Как реализовать опциональные колбэки?

    wataru
    @wataru Куратор тега C++
    Разработчик на С++, экс-олимпиадник.
    Тут похоже ошибка в архитектуре. Логичнее было бы сделать чтобы Lane::Place(Unit *) вызывало какие-то методы у Unit, если это надо для конкретной реализации Lane (Эта логика будет в виртуальном методе, переопределенном в конкретных реализациях интерфейса).

    Или Unit::OnPlaced(Lane*) всегда вызвает какие-то методы у Lane и вот они могут сказать, что Unit-у не надо ничего делать.

    Ну, или раз вам вот так хочется сделать, то пишите шаблонный метод Unit::OnPlaced(T*), И ручками прописывайне инстанциировки с кокретными SkyLane, GroundLane и т.д. Ну и "дефолтную" реализацию пропишите пустую - вообще ничего не делающую для типа T*
    Ответ написан
    Комментировать
  • C++ Как посчитать сколько из данных чисел кратны числу n и заканчиваются на 1?

    wataru
    @wataru Куратор тега C++
    Разработчик на С++, экс-олимпиадник.
    Число кратно n, если остаток от деления на n равен 0. Получить остаток можно, воспользовавшись оператором деления по модулю: x%n. Сравнение с 0 делается оператором сравнения ==.

    Число заканчивается на 1, если последняя цифра равна 1. Цифру можно получить, взяв остаток от деления на 10 (см. оператор % выше). Надо этот результат сравнить с 1.

    Чтобы выполнялись оба условия, надо объединить их оператором логического И (&&).

    Чтобы подсчитать числа, в которых выполняются условия выше - надо пройтись по ним циклом (или 5 раз написать похожий код). Там надо через if проверить условие и, если оно выполняется, увеличить счетчик (можно вот так: ++cnt;

    В код переводите сами, это же ваше задание по изучению C++.
    Ответ написан
    Комментировать
  • Почему delete вызывает ошибку?

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

    Тут вы выделяете память под ровно один символ. Строку туда читать не получится никак (не забывайте, что вам еще байт для нулевого символа в конце строки нужен).

    Вторая ошибка:
    char* m = "Renault"

    Тут используется значение аргумента по умолчанию, где у вас строковая константа. Тут не происходит копирование строки, просто в переменную m сохраняется адрес вот этой вот константы, которую компилятор куда-то в памяти проложения засунет. Вы не выделяли эту память, поэтому попытка сделать delete на ней - неопределенное поведение, что в данном удачном случае приводет к крэшу.

    У вас вообще проблема тут - marka может указывать на выделенную вами в Input() память, а может указывать на переданную из вне память. Кто ее удалять должен-то? Так же в Input() вы можете переписать переданный в конструкторе указатель. А надо ли было его удалять классу?

    Я бы сделал в конструкторе всегда копирование переданной строки. Тогда можно будет передавать туда и строковые константы и использовать вот такое вот значение по умолчанию.
    Ответ написан
    Комментировать
  • Как правильно оформить присваивание значения возвращаемого из функции C++?

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

    Возвращаемое функцией значение является временным значением. В него нельзя писать, но его можно читать. Оно const. И его нельзя передавать в описанный вами оператор копирования.
    Ответ написан
  • На сколько корректна такая реализация?

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

    А дальше надо поменять иерархию ваших классов.
    С такими циклическими зависимостями, конечно, можно что-то даже скомпилировать (в каждом cpp включать другой хедер, в интерфейсе второй класс передавать только как указатель. Или у вас в одном файле сначала сделать оба прототипа, forward declaration второго класса перед ними, потом реализации). Но это будет запутанно и сложно.

    Подумайте, а так ли вам надо в snakeUpdate передавать GameField? Можно, например, из Snake возвращать ее координаты или что там влияет на Update и потом их передавать какому-то методу в GameField. Сейчас ваш snakeUpdate вообще ничего из Snake не задействует - его можно наружу вывести, но это, наверно, еще в разработке. Не надо без крайней необходимости создавать усложненную структуру зависимостей классов. Решите, какой класс будет более важным, и пусть не ему передается второй класс, а второй класс наоборот дергает какие-то его методы.
    Ответ написан
    1 комментарий
  • Фабричный метод. Как создать рефлексивно по имени поля класс, наследуемый от абстрактного?

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

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

    Пример можно посмотреть вот тут. Там CreateEncoderInternal делает практически то, что вам надо. Только там не константное поле command проверяется, а проверяется, что заданный формат есть в статическом списке в текущем классе.

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

    wataru
    @wataru Куратор тега C++
    Разработчик на С++, экс-олимпиадник.
    Не зачем, а почему. Так получилось. В те времена, когда C созадавался, технологии были не настолько развиты. Первый компилятор даже, по-моему, и код-то оптимизировать особо не мог. Предложенная вами compile-time директива слишком сложна. Даже в C++ что-то подобное завезли только совсем недавно.

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

    Еще одна причина - это кросс-платформенный код. Ну вот вызов какой-то функции winapi просто не скомпилируется под linux, потому что ее там тупо нет. Значит надо сказать компилятору вот тот кусок вообще игнорировать. Если это делается на том же этапе, что и сама компиляция, да и с тем же синтакисом, то возникает проблема - в синтаксисе-то ошибка под linux. Как-то разбираться, что эта ошибка не критичская и весь кусок кода можно тупо выкинуть - это компилятору сложно, да и опасно это. Поэтому нужен именно какой-то предварительный этап, который не может использовать тот же самый синтаксис.
    Ответ написан
    Комментировать
  • [OpenGL]Почему получается такая фигура?

    wataru
    @wataru Куратор тега C++
    Разработчик на С++, экс-олимпиадник.
    Вы точно этот код запустили? Пока очень похоже, что просто одна вершина не рисуется в коде.
    Ответ написан
  • [OpengGL] Почему вращается ось, а не фигура?

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

    Если хотите вращать только фигуру, то сначала через glTranslate перенесите ее центр в ноль, потом вращайте и задавайте координаты вершин (относительно центра!).
    Ответ написан
    9 комментариев
  • Как подключить файл?

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

    В хедере вы декларируете функцию и включаете этот хедер в начало вашего С++ файла, приведенного в вопросе.
    Другой С++ файл будет реализовывать функцию (и тоже включать хедер). Потом какая-то система сборки или IDE скомпилирует оба файла и соберет из получившихся объектных файлов одну dll-ку. Или вы руками скомпилируете каждый из двух C++ файлов и потом отдельным вызовом слинкуете все.

    Вы, видимо, предполагаете просто тупо написать код функции в файле и включить его в тело функции через #include. Вообще говоря, это даже скомпилируется, но это такой лютый говнокод получается, что так делать никогда и ни при каких обстоятельствах нельзя. Сообщения об ошибках будут со съехавшими номерами строк, сам файл с кодом будет некорректным С++ кодом, поэтому любой редактор не сможет вам ни подстветить его, ни понять какие там есть штуки, чтобы показывать их вам в подсказках. Такой подход не обобщается на более чем пару файлов - вы потом сами запутаетесь что где и куда включено.
    Ответ написан
    Комментировать
  • Здравствуйте, почему возникает ошибка?

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

    Похоже get_parent возвращает ссылку на unique_ptr. По-моему тут лучше возвращать сырой указатель или ссылку на объект. зачем вам тут unique_ptr вообще?

    Но, игнорируя дизайн, ссылка на unique_ptr в принципе будет работать. Проблема в том, что auto не выводит ссылочность. Поэтому переменная parent становится просто unique_ptr, который конструируется из ссылки копированием. Поэтому если вы напишите auto& parent = то все должно заработать.

    Вторая ошибка - .обращается к методам и полям класса unique_ptr, ведь переменная parent имеет тип unique_ptr<>. Чтобы обратиться к методам/полям хранимого класса надо использовать ->.
    Ответ написан
  • Почему один код выполняется быстрее другого C++?

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

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

    Поскольку второй код отбрасывает все копейки при прибавлении, то ему требуется больше итераций, чтобы дойти до y. На самом деле он может даже виснуть, если там получается прибавление 0.
    Ответ написан
    1 комментарий
  • Как ускорить работу скрипта?

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

    Ну или можно использовать std::unordered_map<std::string, int> вместо trie.
    Ответ написан
  • Почему возникает проблема "terminate called after throwing an instance of 'char const*'"?

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

    Обрабатывайте исключения (конструкция try..catch) где-нибудь в main, тогда можно будет вывести сообщение с ним связанное. Может станет понятнее, откуда оно было брошено. Или можно просто пискать в коде "throw" - скорее всего оно и срабатывает.
    Ответ написан
    Комментировать
  • Почему возникает ошибка?

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

    По второй ошибке: попробуйте написать LinearNavigation<T>::haveNext() там, где оно вызывается в isFullyConnectedQuad.

    Эта ошибка возникает из-за хитросплетения стандарта С++. Ну вот не ищет компилятор вот такие функции не завсящие от шаблонного аргумента по всем шаблонам. Замучается искать, на самом деле, если бы это было включено всегда.
    Ответ написан
  • Почему возникает эта ошибка?

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

    Подозреваю, что ошибка исправится, если в for сделать item ссылкой.
    Ответ написан
    1 комментарий