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

    @res2001
    Developer, ex-admin
    Заверните весь код в input.cpp в namespace input {}
    namespace добавляет к символам в объектом файле имя namespace, но т.к. у вас определения в input.cpp не включены в namespace, то в объектном файле эти символа будут без добавления имени namespace, поэтому и undefined reference.
    Ответ написан
    Комментировать
  • Можно ли изменить размер типа int?

    @res2001
    Developer, ex-admin
    1. Размер всех типов всегда кратен 8 битам. Просто потому, что минимально адресуемый размер памяти в современных процессорах - это 1 байт. Так что 31 или 33 сделать не возможно. Теоретически можно сделать, например, 24 или 40, но смотри следующий пункт.
    2. Все базовые типы С/С++ однозначно проецируются на типы данных, поддерживаемые процессором. Поэтому реально использовать только типы, которые поддерживаются железом. А их не так много и все они, скорее всего, уже есть среди базовых типов С/С++.

    Да можно использовать вариант с битовыми полями или библиотеки для длинных чисел и т.п., но вычисления в этом случае будут медленные, т.к. все операции придется реализовывать программно. Кроме того, если взять битовые поля - там вы можете определить поле размером в 31 бит, но переменная все равно будет занимать 32 бита в памяти (см п.1).
    Ответ написан
    Комментировать
  • Почему побайтовый сдвиг даёт разные результаты?

    @res2001
    Developer, ex-admin
    Читайте тут до прояснения раздел "Bitwise shift operator.
    Смысл в том, что если вы знаковое число сдвинули влево так, что старшим разрядом стала 1, то в результате получится отрицательное число. При сдвиге вправо знакового числа, освобождающиеся слева разряды заполняются битом знака (а не нулем), поэтому результат сдвига отрицательного числа так же будет отрицательным (а положительного - положительным:). Если сдвигать вправо беззнаковое число, то свободные биты будут всегда заполнятся нулями.
    Кстати, на сколько помню, по стандарту знаковость char не определена (может быть как знаковым так и беззнаковым). Вам с вашим примером не повезло, char оказался знаковым. Зато это дало возможность немного глубже понять сдвиги.
    Ответ написан
    6 комментариев
  • Как исправить AccessViolation при чтении указателя, считанного при помощь CArchive?

    @res2001
    Developer, ex-admin
    Не заню, что там в CArchive и вообще MFC давно не брал в руки, но предполагаю, что нужно использовать такой вариант:
    Fruit fruit;
    ar >> fruit;

    Для сериализации/десериализации вызывается метод Serialize вашего же класса, т.е. сам CArchive не создает сериализуемые классы. Следовательно вы должны передать операции >> ссылку на существующий класс, а не указатель. ar просто перезапишет содержимое класса, точнее не ar перезапишет, а ваш же метод Serialize.
    Ответ написан
  • Как написать простой калькулятор?

    @res2001
    Developer, ex-admin
    Например:
    atoi(ex.c_str())+atoi(ex.c_str())
    это выражение 2 раза преобразует в число одну и ту же строку, а затем складывает эти 2 одинаковых числа.
    Так что "не дублирует", а выполняет то что написано у вас в коде.

    Вам нужно сначала разделить строку на "токены", т.е. на операнды и операции.
    Если вы на этом этапе расчитываете обрабатывать только простейшие действия, то вводите строку и разбиваете ее на 3 токена. Затем операнды преобразуете в числа и после этого уже выполняете действие.
    Ответ написан
    Комментировать
  • Книги по сетевому программированию на c++?

    @res2001
    Developer, ex-admin
    Не нужно зацикливаться на С++, т.к. все сетевое API операционной системы на Си. Изучайте просто сетевое программирование. Когда разберетесь, то просто возьмете сетевую библиотеку для плюсов и будете ее использовать. Как правило, подобные библиотеки просто оборачивают Си интерфейс ОС в классы.
    Так же рекомендую книгу Стивенса. Но она старая (последнее издание 2007 года) и в продаже вы ее сейчас не найдете. Электронная версия есть. Не смотря на возраст книга вполне актуальна. Подобные основополагающие технологии изменяются довольно не торопливо.
    Ответ написан
    Комментировать
  • Какая IDE удобнее и проще для плюсов?

    @res2001
    Developer, ex-admin
    qtcreator - хорош
    Eclipse - довольно тяжел для понимания, тормозит на больших файлах или когда открыто много файлов (Java дает о себе знать). Но если планируешь программировать для embeded, то полезно научиться с ним работать, т.к. многие IDE предоставляемые производителями железа основаны на Eclipse.
    С clion не приходилось сталкиваться.
    Ответ написан
    1 комментарий
  • Член класса/структуры типа uint8_t * или int8_t *, оптимизация?

    @res2001
    Developer, ex-admin
    Если нет необходимости в подобной локальной переменной, то не нужно "кэшировать".
    На уровне ассемблера все обращения к памяти происходят через регистры, так что в любом случае адрес из указателя будет записан в регистр и этот регистр будет индексироваться.

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

    Часто удобно использовать локальную переменную, только потому, что указатель (ссылка) лежит где-то в третьей вложенности внутри класса - проще его сразу достать и дальше использовать короткую запись. Но это удобно программисту, а компилятору пофиг.

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

    С restrict можно поиграть, но в чистом С++ его нет, на сколько я знаю, но можно включить расширения в gcc/clang и, возможно его можно будет использовть в плюсовом коде. Но применяйте его лучше сразу к локальному bufferу, а не к this.

    Напоследок: подобного типа код выполняется достаточно быстро, оптимизировать тут особо нечего, есть смысл заморачиваться только если это очень-очень горячий код в вашем приложении. Ну и в плане оптимизации для подобных случаев лучше поискать варианты, как обойтись без копирования данных, чем надеятся, что restrict вам сильно поможет.
    Ответ написан
  • Выделение текста между двумя запятыми C++?

    @res2001
    Developer, ex-admin
    Потому что второй параметр в substr - это не конечная позиция, а количество символов. Ощути разницу.
    Ответ написан
    Комментировать
  • Почему мой вектор не работает со строками?

    @res2001
    Developer, ex-admin
    С clon все в принципе нормально. Можно конечно добавить std::move, но проблема не в этом.
    Проблема в том, что у тебя массив arr размером length - 1, а temp - length. А в clon() ты пытаешься копировать length элементов из arr, поэтому происходит выход за пределы массива.
    В PushBack делай инкремент length, только после того как вызовешь clon первый раз, но до второго вызова.

    Жаль немецкий убрал, было забавно :-) Но так гораздо привычней и понятней.
    Ответ написан
    Комментировать
  • Как выделить подстроку с числом с фиксированной точкой?

    @res2001
    Developer, ex-admin
    В string то же можно обращаться к отдельно взятому символу с помощью оператра индексации.

    Все просто: В цикле проходишь по строке ищешь "+" или "-" или "." или любую цифру.
    Если нашел что-то из этого списка, то натравливаешь на строку, начиная с этой позиции функцию strtod - она сконвертирует строку в double и вернет позицию первого не цифрового символа в строке. Полученное от strtod число вывести на экран. Продолжаешь поиск дальше, начиная с позиции, которую вернула strtod и так до конца искомой строки.
    Ответ написан
    2 комментария
  • Как отсортировать дробную и целую часть числа в C++?

    @res2001
    Developer, ex-admin
    Целую часть можно получить с помощью floor(v)
    Дробную: (v - floor(v))
    Для сортировки используйте стандартный sort.

    Кстати, отсортировать вы можете массив (он у вас уже есть в памяти), когда говорят про поток, то это нечто потенциально бесконечное, порции данных из потока вы получаете частями и обрабатываете их.
    Соответственно, если у вас действительно поток, то надо строить из его данных дерево. Для этого можно использовать стандартный map. Данные будут укладываться в дерево по мере поступления с одновременной сортировкой. Получить из дерева отсортированный список можно просто обходом дерева с помощью итератора.
    Данные в дереве сортируются по ключу. Для ключа можно использовать примерно такую конструкцию: floor(v) + (1 - (v - floor(v)))
    Ответ написан
    3 комментария
  • Правильно ли я понимаю работу программы?

    @res2001
    Developer, ex-admin
    Правильно понимаете.

    Цикл for (int i = count-1; i < count; i++) всегда из одной итерации, так что смысла в нем нет. Оставьте просто одно выделение памяти для последнего элемента массива А (сам цикл уберите).
    В конце вы не освобождаете память - это утечка. В реальных проектах подобное поведение плохо заканчивается.
    Ответ написан
    1 комментарий
  • Как сымитировать потерю пакетов?

    @res2001
    Developer, ex-admin
    Например во FreeBSD в штатном фаерволе ipfw есть такая штука как dummynet - специально для целей тестирования. Там можно настройками задавать скорость и процент потерь. Можно очень хорошо отлаживать сетевые приложения, если сделать фряху с подобным фаерволом шлюзом между клиентом и сервером вашего приложения. Подобную сетку запросто можно поднять на виртуалках.
    Ответ написан
    Комментировать
  • Как передать массив в функцию С++ ( пишет no matching function to call)?

    @res2001
    Developer, ex-admin
    Написал опус на вопрос, который вы удалили, хорошо сохранился в буфере обмена :-) а то было бы обидно.

    Ваш массив пожно просто привести к указателю, по старинке (int*)a или используя касты.

    Но у вас тут на самом деле 2 проблемы.
    Первая - обращение к элементам массива в average используя [i][j]. Вторая - VLA.
    По первой проблеме:
    В С/С++ оператор индексации (array[i]) выполняет следующее действие: *(array+i).
    Отсюда должно быть понятно, что раз array у вас это int*, то после array[i] вы получите int, от которого уже нельзя взять второй индекс, т.к. это просто 1 int, а не массив.

    Отсюда есть несколько выходов:
    1. дурацкий (самый долгий по исполнению и затратам памяти): использовать динамический массив массивов
    Выглядит примерно так:
    int **array = new int*[rowCount];
    for(int i=0; i < rowCount; ++i)
       array[i] = new int[colCount];

    Как видите array превратился в двойной указатель, теперь каждый элемент в первом измерении - это указатель на одномерный массив. Всего у вас получается rowCount + 1 выделений памяти. Не забудьте столько же раз вызвать оператор delete.
    В average теперь передавайте int** и у вас будет работать оператор [][], т.к. первая индексация уже будет возвращать int*.
    Не рекомендую использовать этотт способ.

    2. Вычислять индекс массива вручную (не использовать индексацию):
    *(array + i*colCount + j)
    Это такой хардкорный стиль. Но зато работает быстро и масштабируется на массивы любой размерности без особых проблем.

    3. использовать std::vector<std::vector<int>> - это то же самое, что и вариант 1, но закамуфлированный под вектор :-)

    Вторая проблема это VLA (Variable Length Array).
    Статические (автоматические) массивы в С++ вы можете определять, только константным размером (размером известным на этапе компиляции).
    У вас же размерность массива динамическая (вводится пользователем во время выполнения программы). Отсюда следует, что вы должны использовать динамические массивы, выделенные с помощью new.
    В стандарте С++ нет VLA. VLA есть только в Си и то начиная с С99.
    Ваша функция task3 компилируется, только потому что в gcc/clang по умолчанию включены расширения. В расширения входит так же и возможность использовать VLA. Если задать опциями более строгое соответствие стандарту С++, то функция не соберется.
    И кстати, например в микросовтовский компилятор VLA до сих пор не завезли.

    Но если уж у вас есть VLA, то вы можете преобразовывать указатель в VLA массив с помощью такой кучерявой конструкции:
    int (*array2)[colCount] = (int(*)[colCount]) array;

    В этом случае обращаться к элементам массива можно как обычно через двойную индексацию: array2[i][j]
    Когда-то делал тест на эту тему: https://ideone.com/4i6lRw
    Кстати, если в average сначала передать размерности, и последним параметром массив, то по идее массив можно сразу объявить двумерным, используя ранее переданные размерности:
    void average(int rowcount, int colcount, int aarray[rowCount][colCount])

    Это то же VLA.

    Вообще не рекомендую в С++ использовать VLA, т.к. программа становится не переносимой и зависимой от компилятора.
    Ответ написан
    4 комментария
  • Стоит ли учить Boost в 2021 году?

    @res2001
    Developer, ex-admin
    Вполне востребованная библиотека.
    Но учить не стоит. Стоит знать, какие возможности она предоставляет и как ее исопльзовать в своем проекте. Сделать пример с какими-нибудь достаточно сложными компонентами буста, например asio.
    Ответ написан
    Комментировать
  • Как удалить наименьшую цифру из числа?

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

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

    Другой вариант - встроить веб сервер в приложение. Думаю можно найти какой-то готовый веб сервер в виде библиотеки С/С++ и использовать эту библиотеку (из того что приходит на ум - libonion). Можно написать самому какой-то урезанный вариант веб сервера с минимальным функционалом. Для этого можно использовать какой-либо библиотечный HTTP парсер или опять же написать его самому.
    Ответ написан
    Комментировать
  • EventLoop, потоки и блокировки, как правильно блокировать?

    @res2001
    Developer, ex-admin
    Что касается ImageMemoryCache: в методе get вы возвращаете ссылку на элемент мапы. Блокировка с мапы снимается при выходе из get, но вызывающий код имеет ссылку и может с этим объектом делать все что угодно.
    Параллельно вы можете вызвать clear, который удалит элемент на который осталась ссылка в другом потоке.

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