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

    @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
    Ответ написан
    Комментировать
  • Чем отличаются size_type, size_t, unsigned X?

    @res2001
    Developer, ex-admin
    size_type - это обычно typedef из других типов, который разработчик контейнера решил использовать в контейнере. Скорее всего это будет тот же size_t. Для данного конкретного контейнера логично использовать его size_type.
    Размер size_t привязан к размеру указателя, т.е. sizeof(void*) == sizeof(size_t).
    Как раз это и обеспечивает, то что size_t может индексировать всю возможную память (по байту) для конкретной архитектуры процессора. Размер size_t на х32 - 4 байта, на х64 - 8 байт. Размер указателя, в свою очередь, равен размеру адресной шины процессора.
    В общем случае для счетчиков элементов и т.п. вещей всегда используйте size_t. Но если вы точно знаете, что у вас вот в этом конкретном контейнере/массиве не может быть больше n-ого количества элементов (например массив фиксированного размера), то можно использовать тип меньшей разрядности, достаточный для индексации контейнера.
    Переменные счетчиков, индексов и т.п. обычно делаются беззнаковыми (size_t - беззнаковый), потому что обычно алгоритмически эти переменные никогда не принимают отрицательных значений. Так зачем терять лишний значащий разряд? Но это не всегда так, в каждом конкретном случае нужно делать свой выбор, универсальных решений нет.
    Бывает ли на практике размер контейнера таких размеров которые вмещаются в size_t? В базах данных запросто может быть таблица размером больше, чем помещается в 4 байтовый size_t. Максимальное значение 8 байтового size_t - это ооочень большое число. В практических задачах вряд ли найдется контейнер, вмещающий такое количество объектов (но всегда могут быть исключения). Но итерироваться или считать можно не только объекты в контейнере, можно считать например байты/сектора на диске или пакеты в интернете или контейнер может лежать в распределенной системе хранения размером в экзабайты или больше (сейчас это уже реально).
    Ответ написан
    2 комментария
  • В чем разница const char* и char const*?

    @res2001
    Developer, ex-admin
    Между const char * и char const * - разницы нет. Допустимо использовать обе записи.
    Но кроме самих данных, на которые указывает указатель, можно делать константным и сам указатель, как написал Adamos.
    Ответ написан
  • Какой компилятор выбрать для C++?

    @res2001
    Developer, ex-admin
    На винде микросовтовский компилятор, по ощущениям, лучше. Специально замеры не проводил, все субъективно. Причем не обязательно использовать студию, можете сидеть на том же CLion (или QtCreator) и собирать с помощью cl. Можно поставить вообще только MS Build Tools - туда как раз и входит компилятор без IDE. На счет лицензирования - вопрос интересный. Предоставляют компилятор бесплатно, но могут быть лицензионные ограничения на разработку коммерческого софта.

    На линукс gcc или clang.

    Разница между компиляторами, конечно, есть. Разные расширения, разная степень поддержки стандартов, особенно свежих. Могут отличаться возможности оптимизации и т.п. Например микрософт никогда не поддерживала стандарты Си и там много чего нет еще с С99. Стандарты С++ они официально поддерживают.
    Если вы пишите приложение используя только стандартизованные языковые возможности (без расширений компилятора), то, по идее, не должно быть проблем пересесть на другой компилятор в рамках одной ОС.
    Кстати в gcc по умолчанию расширения включены.

    Есть и другие компиляторы. Например у интел хороший оптимизирующий компилятор, но он стоит денег.
    Ответ написан
  • Почему считывается с файла только 1 слово, а не весь текст?

    @res2001
    Developer, ex-admin
    Не раскрыта тема о классе House. Не видя его трудно что-то сказать.

    Но могу предположить, что в House, например, поле address является std::stringом.
    А std::string хранит свою строку в динамической памяти и sizeof(std::string) в общем случае совсем не равен размеру хранящейся в нем строки. Записывая в файл sizeof(std::string) байт вы записываете грубо говоря только адрес памяти где лежит строка и размер строки, но не саму строку.
    Вам нужно делать нормальную сериализацию/десериализацию полей объекта House.
    Ответ написан
    4 комментария