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

    @res2001
    Developer, ex-admin
    Для винды придется делать отдельную реализацию, т.к.
    1. В консоли винды несколько русских кодировок (cp1251 и cp866, причем по умолчанию cp866).
    2. В консоли винды кодировку можно менять командой chcp из самой консоли на лету.
    Так что нормальная реализация должна узнать текущую кодировку и перекодировать весь выводимый текст в нее. Аналогично и с консольным вводом.
    Менять кодировку из программы - плохой вариант, хотя и вполне работающий.
    Ответ написан
    Комментировать
  • Как поделить на о в С++?

    @res2001
    Developer, ex-admin
    Если вы делите целые числа (short, int, long), то на компьютере вы в принципе не можете получить число с плавающей точкой в результате, т.к. выполняете целочисленное деление.
    Кроме того в процессоре целочисленное деление на ноль обычно вызывает аппаратное исключение. Оно может передаваться в приложение, может не передаваться, тут уже особенности платформы, runtime и т.п. Можете поэкспериментировать.

    Деление на ноль чисел с плавающей точкой стандартно дает в результате NaN - это не число (Not a Number). Любые дальнейшие операции с NaN будут давать в результате NaN.
    Современная стандартная библиотека позволяет настроить поведение так, что бы при делении на ноль чисел с плавающей точкой так же выбрасывалось исключение (std::fesetexceptflag()).

    Если вы хотите получить какое-то число близкое к нулю - реализуйте деление так как считаете нужным.
    Ответ написан
    Комментировать
  • Что такое Статический и Динамический массив?

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

    Память для динамического массива выделяется в динамической памяти (в куче) (new[]). Когда массив становится не нужным память должна быть освобождена (delete[]), иначе произойдет утечка памяти.

    В связи с вышеизложенными принципиальными отличиями, есть несколько следствий:
    1. Имя статического массива это не указатель. Это можно понять например сравнив, что возвращает sizeoff() для статического массива и для динамического. Хотя в некоторых ситуациях компилятор ведет себя так, как будто имя статического массива это указатель, например: можно передать имя статического массива в функцию, принимающую указатель.
    2. У динамического массива нет имени. Операция new[] возвращает указатель. Имя есть у указателя.
    3. Внимание! Оба варианта массивов имеют фиксированный размер. Изменять его нельзя!
    То что в std::vector вы можете укладывать кучу элементов постепенно, не указывая нигде предварительного размера является следствием того, что std::vector скрывает от вас всю работу, которую он при этом делает. При добавлении нового элемента, для которого нет места, он выделяет память для нового массива большего размера, копирует старый массив в новый, удаляет старый массив, добавляет новый элемент. Если идет интенсивная работа с push_back(), то это может ОООЧЕНЬ дорого стоить. std::vector - это удобно, но необходимо всегда помнить, за счет чего достигается это удобство. std::vector - это не динамический массив - это обертка над ним для более удобной работы с динамическим массивом.

    В языке Си (C99) есть такая штука как Variable Length Array (VLA) - это статический массив с изменяемым размером. Т.е. вы можете, например, в функции объявить int arr[N], где N будет передаваться в функцию как параметр.
    В стандарте С++ VLA нет! Но, например, тот же gcc с опциями по умолчанию разрешает его использования в С++ проектах. С опциями, заставляющими gcc более жестко следовать стандарту, он может запрещать использовать VLA в С++ проектах. Но не рассчитывайте, что все компиляторы будут так делать. Например микрософтовский компилятор в принципе не умеет в VLA (хотя я уже пару лет не проверял это).
    VLA может показаться классной штукой.
    Но, например, в ядре Линукс в свое время проводили целую компанию по выпиливанию VLA из исходников. Торвальдс высказывался негативно про VLA. Все это при желании можно нагуглить.
    Стоит помнить, что размер стека ограничен, а VLA то же выделяется на стеке. Кроме того выделение памяти для обычного статического массива это просто увеличение счетчика стека на константу (и все, одна операция сложения регистра с константой, а компилятор одной операцией выделяет память для всех переменных в текущей области видимости). С VLA все сложнее с выделением и удалением. Так же sizeof() для обычного статического массива это операция времени компиляции (при выполнении будет уже заранее известная константа), для VLA - это полноценный вызов функции.
    Ответ написан
    1 комментарий
  • Заинклудить из Windows.h только Sleep()?

    @res2001
    Developer, ex-admin
    MSDN говорит, что объявление Sleep() находится в файле synchapi.h. Так что можете подключать этот файл, а не глобальный Windows.h.
    Так же можно просто выдернуть объявление этой функции из synchapi.h и вставить его в свой код:
    void Sleep(DWORD dwMilliseconds);
    После этого можно использовать функцию. Главное не забудьте подключить виндовые библиотеки при сборке. Эта функция находится в Kernel32.lib.
    Ответ написан
    5 комментариев
  • Почему при компиляции проекта console application в dev c++ большой вес файла?

    @res2001
    Developer, ex-admin
    Используйте динамическую (а не статическую) линковку со стандартной библиотекой, возможно это уменьшит размер исполняемого файла. Но в этом случае клиенту придется тащить дополнительные библиотеки в виде отдельных файлов *.dll или в случае MSVC устанавливать runtime правильной версии.
    Ответ написан
    Комментировать
  • Почему некорректно находит произведение чисел?

    @res2001
    Developer, ex-admin
    Почему вы в функции с переменным количеством аргументов не используете стандартный механизм для работы с аргументами в подобных функциях (#include <cstdarg>)?

    Поставьте отладочный вывод в цикл, где выведите значение count, а заодно и *ptr и comp. То же самое можно быстро посмотреть в отладчике затратив минуты 3 на все. Выводите значение floatов с большим количество знаков после запятой (10-15).
    Вы будете удивлены тому, что во float 3.0 это не обязательно равно 3, ну и т.д. То же самое относится к любым типам с плавающей точкой.
    Передавайте первым аргументом uint32_t, вторым и следующим float. Тогда все будет нормально. Код, конечно, придется немного переделать.
    Ответ написан
    3 комментария
  • Как проверить переменную любого ссылочного типа на null?

    @res2001
    Developer, ex-admin
    По стандарту ссылка не может указывать на несуществующий объект (NULL), поэтому, если вы сделаете так:
    if (&refTypeParam == null)
    Компилятор запросто может выкинуть этот код в процессе оптимизации, т.к. условие по стандарту никогда не выполнится.
    Вещи типа этой:
    int &v = *(int*)NULL;
    это неопределенное поведение по стандарту. Но на сколько я знаю, такое вполне прокатывает.
    https://stackoverflow.com/questions/4364536/is-nul...
    Ответ написан
    1 комментарий
  • Как правильно организовать прием данных через WS?

    @res2001
    Developer, ex-admin
    или я что то не так понял

    Именно.
    Вы выбрали асинихронный инструмент, не понимая как он работает.
    ioc.run() - запускает цикл обработки асинхроных событий (event loop). Когда он завершается, то вы не сможете уже что-либо получать/передавать.
    Ваша задача добавить нужный вам код в обработчики событий (функции on_xxx()). Как это правильно делать смотрите документацию по библиотеке и возможно другие примеры использования.

    Я никогда не использовал boost.beast и WebSocket, но некоторый опыт асинхронного программирования есть, а принципы асинхронного программирования в любых библиотеках одни и те же.
    Ответ написан
    Комментировать
  • Многострочный литерал C++ u8"один"sv u8"два"sv: что можно убрать?

    @res2001
    Developer, ex-admin
    u8 говорит о том, что строка в кавычках будет в кодировке UTF8: https://en.cppreference.com/w/cpp/language/string_...
    sv - преобразует строку в string_view: https://en.cppreference.com/w/cpp/string/basic_str...
    А нужно оно или нет - решать вам, в зависимости от контекста.
    Ответ написан
  • Как оптимизировать мой код?

    @res2001
    Developer, ex-admin
    В свое время оптимизировал нечто похожее на Windows API. Там просто выводил все в контекст в памяти, а затем копировал этот контекст в контекст устройства вывода (окно). Думаю что-то подобное можно соорудить и в SFML.
    Так же может поможет другой подход - отключение отрисовки и включение ее после того как все будет нарисовано.
    С SFML никогда дела не имел, просто это достаточно общие подходы, на мой взгляд.
    Ответ написан
    Комментировать
  • Какие есть способы реализации системы внешних скриптов?

    @res2001
    Developer, ex-admin
    Питон так же используется для подобной схемы. Например в Танках, если не ошибаюсь, его используют.
    В браузерах и node.js используется JS - схема аналогичная.
    В Far manager - Lua.
    Ответ написан
    Комментировать
  • Проблема с двусвязным списком?

    @res2001
    Developer, ex-admin
    В del_node() происходит освобождение памяти, а затем в result вы обращаетесь к освобожденной памяти (второй цикл):
    p = p->next;
    Зачем в result первый цикл? И зачем в программе z?
    Ответ написан
    Комментировать
  • Какие книги по C++ актуальны на 21 год для обучения с нуля?

    @res2001
    Developer, ex-admin
    Для начала берите любую книгу для начинающих. Лафоре подойдет. Берите издание по свежее. Есть и другие книги подобного рода, конечно.
    Страуструп тяжел и не годится для старта.
    Саттер, Мейерс больше для продвинутых.
    C++ Templates для старта точно не нужен.
    Так же не плохо было бы начать что-то читать по алгоритмам.

    Сейчас проблема с изучением С++ в том, что с 2011 года начали регулярно появляться новые стандарты, в них появляются фишки, которых раньше не было, некоторые из них очень полезные. Толстые учебники не успевают переписываться под актуальные стандарты. Но это не большая беда.
    Базовым сейчас является стандарт С++11 (или С++14 - это дополнение к С++11), его применяют уже многие. Более поздние (17, 20) применяются реже, так что можно не гнаться за тем, чтобы в книге они были освещены. Базовые понятия в С++ в целом мало изменились с древних времен. Но кое-что добавилось.
    Кстати, проблема с поддержкой новых стандартов актуальна не только для книг, но и для компиляторов языка.
    После освоения базы и начала практической деятельности сможете дальше продвигаться в изучении языка, ориентируясь на свои реальные потребности.
    Главное в изучении - больше практики - не зацикливайтесь на книгах. В начале старайтесь делать задания из книг. Когда более-менее освоитесь, переходите к своим задачам/интересам.
    Ответ написан
    1 комментарий
  • Как из аналогового сигнала получить вольты?

    @res2001
    Developer, ex-admin
    Не знаю как там в ардуинах, но ...
    Думаю, что аналоговый сигнал подается на АЦП и в программе вы имеете дело уже с дискретным (оцифрованным) сигналом.
    Так вот, в АЦП, обычно существует пара коэффициентов (смещение нуля и масштаб), в документации к АЦП приводится формула как использовать эти коэффициенты с цифровым отсчетом сигнала, что бы получить вольты (кстати, АЦП не обязательно меряет именно напряжение). Обычно формула это что-то вроде: (X + offset)*scale. Но могут быть и другие варианты.
    Коэффициенты на всех АЦП разные. Даже на двух одинаковых АЦП они могут быть разные (и как правило они разные). АЦП калибруются на заводе и коэффициенты зашиваются в чип. В документации к АЦП должен быть описан способ получения этих коэффициентов. Если АЦП многоканальное, то коэффициенты могут быть разными для каждого канала.
    В библиотеке работы с АЦП, обычно присутствуют функции получения калибровочных коэффициентов и может быть даже получение уже преобразованного сигнала.

    Вообще если бы АЦП было идеальным, то преобразовать цифровой отсчет в вольты было бы просто. Например АЦП выдает 16 битные без знаковые отсчеты (т.е. на выходе АЦП числа от 0 до 65535, тип данных uint16_t), диапазон измерений допустим [-5; +5]В. Пусть uint16_t Х - цифровой отсчет, полученный от АЦП, тогда преобразовать его в вольты можно так: ((double)(((int32_t)X) - 0x7FFF)) / 0x7FFF ) * 5.0. При желании можно раскрыть скобки и получить те самые 2 калибровочных коэффициента для идеального АЦП.
    Но т.к. АЦП не идеальны и там присутствуют разнообразные погрешности и помехи, то и появляются те самые калибровочные коэффициенты. Формула преобразования остается примерно той же самой, но используются уже не точные числа, а подобранные коэффициенты.
    Ответ написан
    2 комментария
  • Какую версию стандарта учить/использовать в 2021 году?

    @res2001
    Developer, ex-admin
    Используют ту версию, которая принята в проекте. Обычно, в проекте уже приняты определенные правила, в т.ч. и по используемому компилятору, версии языка и т.п. Ты просто принимаешь эти правила и работаешь в проекте (или не принимаешь и не работаешь).
    Сейчас все используют минимум C++14. C++14 - это небольшой апгрейд над C++11, все значимые изменения были в C++11, так что литература по С++11 вполне подходит.
    Самые "продвинутые" используют С++17 и может быть кто-то уже и С++20.
    Хватает и старых проектов, где большая кодовая база, написана на старых стандартах языка до С++11.

    На самом деле основы языка изменяются мало. Вся ООП обвязка вполне актуальна со времен С++03, кое что добавили, но и старое то же работает.
    Ответ написан
    1 комментарий
  • Что означает void book::buybook()?

    @res2001
    Developer, ex-admin
    У функции объявленной как:
    void func(...);
    нет возвращаемого значения.
    То что функция в данном примере это метод класса значения не имеет.
    Ответ написан
    Комментировать
  • Есть ли какая нибудь функция из встроенных библиотек в с++ для проверки является ли строка числом?

    @res2001
    Developer, ex-admin
    Сконвертируйте строку в число с помощью strtod() (или любой функции из этой серии) и проанализируйте возвращаемое значение и значение второго параметра. По этой информации можно сделать любые нужные выводы.

    Еще есть isdigit() - но она проверяет символ только на цифры, а число может быть разным - например начинаться со знака или если дробное, то в нем будет разделитель дробной части, который может быть первым. Но в простых случаях ее может быть достаточно.
    Ответ написан
    Комментировать
  • Как правильно построить структуру проекта используя cmake?

    @res2001
    Developer, ex-admin
    Отлаживать библиотеку логичнее специально написанными для этого тестами. В этом случае библиотека будет представлять самостоятельный продукт. Ее можно будет устанавливать клиентам отдельно. А в основном продукте использовать find_package для поиска библиотеки.

    Если вам этого не надо, то вполне нормально включать каталог с исходниками библиотеки как подкаталог продукта и использовать add_subdirectory.
    Ответ написан
    Комментировать
  • Одномерные массивы C++ почему не вычисляет произведение отрицательных элементов массива М и максимальный элемент массива К?

    @res2001
    Developer, ex-admin
    С произведением все просто - вы инициализировали Dob_v нулем, а произведение любого числа с нулем = нулю. Вот у вас всегда нулевой результат. Инициализируйте Dob_v единицей.
    У вас путаница в двух последних циклах - разберитесь с закрывающими скобками - получается цикл по K вложен в цикл по M. Причем в цикле по К не правильное условие, т.к. К содержит всего 10 элементов.
    Ответ написан
    Комментировать
  • Где ошибка.....?

    @res2001
    Developer, ex-admin
    Функцию count реализуйте макросом:
    #define count(arr)     (sizeof(arr) / sizeof(arr[0])

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