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

    @res2001
    Developer, ex-admin
    Листьями в дереве считаются узлы, у которых нет потомков.
    Потомки в коде задаются членами узла left и right, соответственно if(p->left == NULL && p->right == NULL), то узел - лист.
    Делаете проход по всем узлам и выводите только те узлы, где условие выполняется.
    Ответ написан
    Комментировать
  • Как думаете, с чем связана ошибка и как ее исправить?

    @res2001
    Developer, ex-admin
    Про size_t - если вы на 100% уверены, что у вас никогда не случится потеря данных при преобразовании из 8 байтного беззнакового size_t в 4 байтный знаковый int, то можете сделать явное преобразование типов (cast). Но гораздо правильней для размера (всего чего угодно) использовать size_t (а не int), как это давно уже делают в std.
    Про strncpy - в некоторых случаях она может быть не безопасной. Если вы на 100% уверены, что в вашем случае она точно безопасна, то можно забить на ошибку, объявить макрос, который указан в тексте ошибки и на этом проблема будет исчерпана. Но есть безопасные аналоги строковых функций у них к имени добавляется суффикс _s. В вашем случае безопасный аналог strncpy_s. Используйте безопасные функции. Безопасные функции немного медленней работают, за счет дополнительных проверок и т.п.
    Ответ написан
    6 комментариев
  • Можно ли создать пустую структуру, а потом её заполнить внутри функции?

    @res2001
    Developer, ex-admin
    В плюсах структуры это те же классы, но у них по умолчанию используется модификатор доступа public, а в классах private - это вся разница между ними.
    Напишите для структуры конструктор по умолчанию, в котором будете присваивать нужные значения членам структуры. После этого при объявлении любого экземпляра структуры:
    Date date;
    члены структуры будут принимать значения, заданные в конструкторе по умолчанию.
    Ответ написан
  • Почему не работает пузырьковая сортировка двумерного динамического массива?

    @res2001
    Developer, ex-admin
    1. В result в цикле сортировки вложенный цикл должен быть до y, а у тебя до х, так же как верхний цикл.
    2. Как писал mayton2019 для сортировки не хватает дополнительного цикла. Просто сделай сначала сортировку одномерного массива и поймешь зачем он. Сейчас у тебя только одна итерация сортировки для каждой колонки проходит.
    3. Посмотри внимательно сюда:
    int temp = Arr[i][j + 1];
    Arr[i][j] = Arr[i][j];
    Arr[i][j + 1] = temp;

    И пойми, что этот код ничего местами не меняет. А должен.
    Ответ написан
    2 комментария
  • Является ли такой способ выделения массива объектов на хипе идиоматичным?

    @res2001
    Developer, ex-admin
    Можно использовать std::malloc вместо new.
    Если класс полиморфный, то можно предварительно вычислять max из размеров всех детей и использовать это значение для выделения массива. Список детей должен быть заранее известен.
    Ответ написан
    1 комментарий
  • Как в деструкторе базового класса вызвать переопределённый метод?

    @res2001
    Developer, ex-admin
    Никак. Когда работает деструктор базового класса объект наследник уже не существует.
    Так что "чистите" наследник в деструкторе наследника, а базовый класс в деструкторе базового класса.
    Вот старинная статья на хабре, но, на сколько я знаю, и сейчас все работает так.
    Ответ написан
    Комментировать
  • Не получается вернуть строку. Как исправить?

    @res2001
    Developer, ex-admin
    1. Лучше бы вы использовали std::string, а не нативные ("сырые") строки.
    2. Нативные строки - это не строки в привычном для С++ смысле (и в смысле интерпретируемых ЯП). У них нет встроенных операций типа конкатенации, выделения подстрок и т.п. Все это реализуется функциями в стиле Си str*
    3. Если вы хотите вернуть сырую строку, то надо:
    3.1. Массив под строку выделять в динамической памяти (или передавать его как параметр в функцию и его заполнять). Сейчас у вас автоматический массив, а он исчезнет, как только отработает оператор return и строка по факту не вернется (хотя вернется указатель, но он будет указывать в место на стеке, в котором уже нет вашей строки).
    3.2. Возвращать char*. Сейчас тип возвращаемого значения в вашей функции char - а это один символ, а не строка.
    4. Размер строки явно будет больше, чем size байт. На сколько больше - нельзя сказать заранее. Поэтому обычно выделяют достаточно большой буфер с запасом, чтоб покрыть все возможные варианты и при добавлении в буфер очередной подстроки контролируют размер буфера - чтоб оставалось место для очередной добавляемого куска и завершающего нулевого символа. Строка может быть равна size только в случае, если все числа в массиве будут состоять из одной десятичной цифры. Да и в этом случае требуется дополнительный байт на нулевой символ. Так что минимальный размер буфера должен быть size+1, реально он должен быть еще больше.
    Ответ написан
    Комментировать
  • Как сохранить значения нескольких переменных в С++ 17?

    @res2001
    Developer, ex-admin
    Вы же из getInfo возвращаете вектор, вот и принимайте вектор. В нулевом элементе вектора будет normal_weight, в первом weight. Вместо вектора можно было бы использовать std::pair или std::tuple. Они хранят свои данные статически, а вектор выделяет динамический массив, что в вашем случае максимально избыточно.

    Другой вариант передавайте в getInfo ссылки, тогда не надо будет ничего возвращать, значения в main появятся сами собой :-) Сейчас у вас аргутменты getInfo не понятно какую роль выполняют.
    Ответ написан
  • Почему переопределение метода без virtual -- это не переопределение?

    @res2001
    Developer, ex-admin
    Переопределить можно в любом случае, хоть с virtual, хоть без.
    Но тут важно что вам надо от переопределенного метода. Если вам нужно использовать полиморфизм, то нужно ставить virttual, если нет - то нет.

    Например дополним ваш пример функцией:
    void func(struct A &a)
    {
      a.fn();
    }
    
    int main() {
      B b;
      b.fn();
      func(b);
    }

    И передадим туда ссылку на b. Будет напечатана А, т.к. методы fn не виртуальные.
    Если были бы виртуальные, то напечатается B - полиморфизм в действии.
    Ответ написан
    Комментировать
  • Как можно передать unsigned char[] PROGMEM в функцию?

    @res2001
    Developer, ex-admin
    void func(const unsigned char *array, size_t array_length);
    ...
    func(bfr, sizeof(bfr)/sizeof(bfr[0]));


    Не знаю, что такое PROGMEM, видимо это какой-то макрос, который навешивает какой-нибудь аттрибут для типа.
    Ответ написан
    Комментировать
  • Где изучать STL и Boost?

    @res2001
    Developer, ex-admin
    STL по сути часть языка, так что в любом учебнике по плюсам будут и основы STL.
    Boost - это такая расширенная версия STL, многие новшества перед тем как попасть в стандарт и соответственно в STL тестируются на Boost. Но в Boost содержится много того, чего нет в STL. У Boost своя хорошая документация, изучайте по ней и по примерам.
    Любые другие библиотеки изучаются по документации от разработчиков библиотеки. Если документации нет, бывает и такое, - по исходникам.
    Ответ написан
    Комментировать
  • Ввод текста с++?

    @res2001
    Developer, ex-admin
    Библиотека называется WinAPI.
    Видимо нужно найти нужное окно (по каким-то признакам) и начинать посылать туда сообщения о нажатии клавиш.

    Собственно к С++ эта задача особого отношения не имеет. Та же логика, видимо, была у вас и в питоне, только там все это уже было запрятано в готовую библиотеку. На плюсах может и есть такая готовая библиотека, но точно это не стандартная библиотека, надо искать что-то стороннее.
    Разных библиотек в исходниках и без на плюсах и Си очень много. Гуглите.
    Ответ написан
    Комментировать
  • Как вывести кириллицу в c++?

    @res2001
    Developer, ex-admin
    lololoshka_1991, Если совсем просто, то пиши исходники в кодировке cp866. Кодировка консоли по умолчанию как раз такая в русской винде. Но в этом случае и запускай программу руками из консоли, т.к. тот же MSVS может менять кодировку консоли при запуске программы из него.
    Так же кодировка консоли может меняться и командой в самой консоли. Например: chcp 1251
    В винде по умолчанию может быть 3 варианта кодировок с поддержкой кириллицы: cp866, cp1251, UTF8.

    Что бы сделать программу независимой от кодировки консоли, то придется заморочиться. Готового решения не встречал. По уму надо делать так: пишем исходники в UTF8, в программе узнаем кодировку консоли (WinAPI позволяет это делать), перед выводом весь текст перекодируем в кодировку консоли, после ввода весь ввод перекодируем в UTF8. Внутри программы работаем только с UTF8. Для хранения строк в программе использовать wchar_t, wstring и т.п. Функции перекодирования в WinAPI так же присутствуют.

    Кстати в плюсах есть метод std::basic_ios.imbue(), который позволяет задавать кодировку потока. Можно попробовать поиграть с этим. Но вообще менять кодировку консоли из программы - плохо, т.к. пользователь консольной программы может ждать ответ от запускаемой программы в конкретной кодировке. Это широко используется при написании батников и т.п. скриптов. Например большая часть виндовых команд корректно выводит текст не зависимо от того какая кодировка в консоли. Тот же dir, например.
    Ответ написан
    Комментировать
  • Как передать динамический массив в функцию?

    @res2001
    Developer, ex-admin
    sizeof(chars) в результате дает размер указателя (8 - для x64 систем, 4 - для х32 систем), а не размер строки. Чтоб получить размер строки надо его передать в функцию (str.size()) или вызвать strlen уже внутри.
    sizeof(*chars) всегда в результате равен 1, т.к. размер char по стандарту 1 байт.

    Вам не нужно 2 цикла. Я так понимаю, вы хотели различать четное и не четное количество символов в строке.
    Но если количество элементов четное, то мы должны обработать все элементы массива при этом количество итераций цикла будет strlen(chars)/2. А если количество элементов не четное, то центральный элемент мы пропускаем и количество итераций будет то же strlen(chars)/2, за счет того, что тут используется целочисленное деление и остаток от деления отбрасывается.

    В функцию можно передавать ссылку на объект string, а не сырой массив (c_str()). string позволяет обращаться на прямую к каждому символу отдельно с помощью операции индексации (str[i], так же как и сырые массивы). При этом возвращать что-либо из функции не нужно, т.к. вы будете манипулировать непосредственно данными самого объекта и все изменения будут видны в main.
    Ответ написан
    Комментировать
  • Как упростить проверку на правильность круглых скобок?

    @res2001
    Developer, ex-admin
    Просто считайте количество открывающих скобок и количество закрывающих. Причем, если на закрывающей скобке количество открывающих <= количества закрывающих, то ее не учитываем (или учитываем в ошибках закрывающих скобок), т.к. нет парной открывающей.
    Ошибки по открывающим скобкам будут, если в конце количество открывающих > количества закрывающих, количество ошибок открывающих скобок в этом случае = количество открывающих - количества закрывающих.
    Количество правильных скобок == количеству закрывающих (т.к. не правильные закрывающие мы не считаем).
    Ответ написан
    Комментировать
  • Как исправить Error C4700: использована неинициализированная локальная переменная "x"?

    @res2001
    Developer, ex-admin
    Переменная x при определении не инициализируется. Впервые в коде встречается в этой строке:
    y = pow(x, k * 1) + fabs(pow(sin(x), 2) + sqrt(1 + pow(sin(x), 3)));

    Т.е. вы что-то пытаетесь вычислить используя данные из переменной х. Какое значение имеет переменная x в этом выражении? Т.к. вы не задаете значение переменной в программе до использования переменной, то переменная содержит любое произвольное значение, мусор.
    С переменной t все аналогично.
    Ответ написан
    Комментировать
  • Как исправить код?

    @res2001
    Developer, ex-admin
    Видимо препод хочет, чтоб программа могла работать с несколькими значениями А и N.
    1. Ввод A и N и расчет периметра выносите в отдельную функцию.
    2. В main делаете вечный цикл, где спрашиваете пользователя что-нибудь типа "Давай еще посчитаем (1 - да; 0 - нет)". Если пользователь вводит 1, то выполняете функцию из п.1, после ее выполнения снова спрашиваете пользователя. Если пользователь вводит 0 - break из цикла и завершение программы.
    Ответ написан
    Комментировать
  • Как считывать данные в файл?

    @res2001
    Developer, ex-admin
    cin и cout - это объекты классов потоков ввода и вывода в консоль. Объекты cin и cout объявляются автоматически, т.е. вам не нужно создавать эти объекты, они уже созданы внутри стандартной библиотеки.
    Есть в std классы ifstream и ofstream, которые являются потоками ввода/вывода в файлы. Объекты этих классов не создаются автоматически, но вы можете создать эти объекты вручную и указать при создании с каким файлом объект должен работать. Дальше заменяете все cin/cout на объекты классов ifstream/ofstream.

    Есть другой вариант. Вообще не менять программу, но при запуске перенаправлять потоки stdin/stdout в файлы, что-то типа такого:
    prog.exe <file_input.txt >file_output.txt
    В этом случае в программе объекты cin/cout автомтатически начинают использовать file_input.txt для ввода и file_output.txt для вывода.
    Ответ написан
    Комментировать
  • Почему не работает функция в с++ пытаюсь вызвать, а она не вызывается?

    @res2001
    Developer, ex-admin
    Вот это void BubbleSort(vector<int> v); не вызов функции. Это ее объявление. В коде предварительные объявления функций могут встречаться где угодно, синтаксически это верно, потому компилятор и не ругается. Но вызова не происходит, потому что его нет.
    Ну и учтите замечание 12rbah
    Ответ написан
    Комментировать
  • Как узнать размер массива, который был передан в шаблонную функцию?

    @res2001
    Developer, ex-admin
    Потому что при передаче в функцию статического/автоматического массива передается указатель, а не сам массив.
    8 - размер указателя на 64-битной платформе.
    Размер нужно передавать отдельным параметром, как писал mayton2019
    Ответ написан
    Комментировать