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

    @Mercury13
    Программист на «си с крестами» и не только
    Потому что map — это функциональное соответствие. Одному ключу соответствует одно значение.
    Или используйте multimap. Или варьируйте ключ, а не делайте жёсткой единицей.
    Ответ написан
    Комментировать
  • Почему строка конвертируется в неправильное число?

    @Mercury13
    Программист на «си с крестами» и не только
    Ваш текст представляет собой число, превосходящее диапазон int. В таком случае ваша реализация atoi выводит максимум возможного.
    Можно использовать:
    • sscanf long long
    • atoll (C++11)
    • stoll (C++11)
    • from_chars (C++17)
    Ответ написан
    1 комментарий
  • Как сделать, чтобы конструктор при определённых условиях не компилировался — а не сваливал на runtime?

    @Mercury13 Автор вопроса
    Программист на «си с крестами» и не только
    Вот действующий код.
    Хоть он на 20, простейшими define’ами (consteval → constexpr, constinit → пустота) можно собрать его и на 17.
    #include <iostream>
    #include <array>
    #include <string>
    
    enum class FromRawMem { INST };
    enum class NoValue { INST };
    
    #define consteval constexpr
    
    
    class Char4
    {
    public:
        using CppArray = std::array<char, 4>;
        constexpr explicit Char4(NoValue) : fBuf { { 0, 0, 0, 0 } } {}
        consteval Char4(const char (&x)[5]) : fBuf { { x[0], x[1], x[2], x[3] } } {}
        constexpr Char4(const Char4&) = default;
        Char4(FromRawMem, const char* data) { fBuf.asInt = *reinterpret_cast<const uint32_t*>(data); }
        constexpr const CppArray& toAr() const { return fBuf.asAr; }
        CppArray& toAr () { return fBuf.asAr; }
        constexpr std::string_view toSv() const { return { fBuf.asAr.data(), 4 }; }
    
        /// @return  byte-order dependent integer value
        /// @warning
        ///    DO NOT save toRawInt() as Intel, Motorola or any numeral system (decimal etc).
        ///    You MAY save it as raw memory, or use it for optimization.
        constexpr uint32_t toRawInt() const { return fBuf.asInt; }
        constexpr const char* data() const { return fBuf.asAr.data(); }
    private:
        union {
            std::array<char, 4> asAr;
            uint32_t asInt;
        } fBuf;
    };
    
    constexpr inline bool operator == (Char4 x, Char4 y) { return x.toRawInt() == y.toRawInt(); }
    constexpr inline bool operator != (Char4 x, Char4 y) { return x.toRawInt() != y.toRawInt(); }
    constexpr inline bool operator == (Char4 x, std::string_view y)
            { return y.size() == 4 && x.toRawInt() == *reinterpret_cast<const uint32_t*>(y.data()); }
    constexpr inline bool operator != (Char4 x, std::string_view y)
            { return !operator == (x, y); }
    constexpr inline bool operator == (std::string_view x, Char4 y)
            { return operator == (y, x); }
    constexpr inline bool operator != (std::string_view x, Char4 y)
            { return !operator == (y, x); }
    
    
    /// Size of enum class, no generic implementation.
    template <class Ec>
    constexpr size_t enumSize();
    
    namespace detail {
        /// Jut does not compile if arguments contain assignments
        constexpr int enumDummy(...) { return 0; }
    
        template <typename T, std::size_t...Is>
        consteval std::array<T, sizeof...(Is)>
        make_array(const T& value, std::index_sequence<Is...>)
        {
            return {{(static_cast<void>(Is), value)...}};
        }
    
        template <std::size_t N, typename T>
        consteval std::array<T, N> make_array(const T& value)
        {
            return make_array(value, std::make_index_sequence<N>());
        }
    }
    
    #define DEFINE_ENUM_SIZE(Name) \
        template <> constexpr size_t enumSize<Name>() { return static_cast<int>(Name::NN); }
    
    #define DEFINE_ENUM_N(Name, ...)  \
        enum class Name { __VA_ARGS__ };   \
        template <> constexpr size_t enumSize<Name>() { \
            enum Internal { __VA_ARGS__ , NNNNNN };  \
            detail::enumDummy(__VA_ARGS__);  \
            return NNNNNN; }
    
    
    enum class DummyElem { INST };
    enum class IncompleteArray { INST };
    enum class FillArray { INST };
    enum class PairwiseTempInit {INST };
    
    
    namespace detail {
        namespace array {
    
            template <auto K, class V>
            class KeyValue {
            public:
                static constexpr auto index = K;
                V && v;
                consteval KeyValue(V && aV) : v(aV) {}
            };
    
            // checkOneForRepeat
            template <class Ec>
            consteval void checkOneForRepeat() {}
    
            template <class Ec, Ec Only>
            consteval void checkOneForRepeat() {}
    
            template <class Ec, Ec First, Ec Second, Ec ... Rest>
            consteval void checkOneForRepeat()
            {
                static_assert(First != Second, "Repeating array keys!");
                checkOneForRepeat<Ec, First, Rest...>();
            }
    
            // checkForRepeat
            template <class Ec>
            consteval void checkForRepeat() {}
    
            template <class Ec, Ec Only>
            consteval void checkForRepeat() {}
    
            template <class Ec, Ec First, Ec Second, Ec ... Rest>
            consteval void checkForRepeat()
            {
                checkOneForRepeat<Ec, First, Second, Rest...>();
                checkForRepeat<Ec, Second, Rest...>();
            }
    
            template <class Ec, Ec ... args>
            consteval void checkKeys()
            {
                checkForRepeat<Ec, args...>();
            }
    
        }
    }
    
    template<auto K, class V>
    consteval auto kv(V && v) { return detail::array::KeyValue<K, V>(v); }
    
    
    template <class T, class Ec>
    class EcArray
    {
    public:
        static constexpr auto Size = enumSize<Ec>();
        using CppArray = std::array<T, Size>;
        using Elem = T;
        using iterator = Elem*;
        using const_iterator = const Elem*;
        constexpr CppArray& toAr() { return fBuf; }
        constexpr const CppArray& toAr() const { return fBuf; }
        constexpr Elem* data() { return fBuf.data(); }
        constexpr const Elem* data() const { return fBuf.data(); }
        constexpr size_t size() const { return Size; }
        constexpr iterator begin() { return fBuf.begin(); }
        constexpr iterator end() { return fBuf.end(); }
        constexpr const_iterator begin() const { return fBuf.begin(); }
        constexpr const_iterator end() const { return fBuf.end(); }
        constexpr const_iterator cbegin() const { return fBuf.begin(); }
        constexpr const_iterator cend() const { return fBuf.end(); }
    
        constexpr EcArray() = delete;
        constexpr EcArray(NoValue) {}
        constexpr EcArray(const EcArray&) = default;
        constexpr EcArray(EcArray&&) = default;
    
        EcArray& operator = (const EcArray&) = default;
        EcArray& operator = (EcArray&&) = default;
    
        template <class U>
        constexpr EcArray(NoValue, const U&& x) : fBuf {x } {}
    
        template <class ... Args>
        consteval EcArray(Args&& ... x)
            : fBuf { x... }
            { static_assert(sizeof...(Args) == Size, "EcArray size mismatch"); }
    
        template <class U, Ec K, class V, class ... Args>
        consteval EcArray(
                PairwiseTempInit, U&& temp,
                detail::array::KeyValue<K, V> first,
                Args&& ... rest)
            : fBuf { detail::make_array<Size, T>(temp) }
        {
            static_assert(sizeof...(Args) + 1 == Size, "EcArray pairwise size mismatch");
            detail::array::checkKeys< Ec, K, (std::remove_reference_t<decltype(rest)>::index)... >();
            initPairwise(first, rest...);
        }
    
    private:
        CppArray fBuf;
    
        consteval void initPairwise() {}
    
        template <Ec K, class V, class ... Args>
        consteval void initPairwise(
                detail::array::KeyValue<K, V> first,
                Args&& ... rest)
        {
            fBuf[static_cast<size_t>(K)] = T { first.v };
            initPairwise(rest...);
        }
    };
    
    
    DEFINE_ENUM_N( Letter, A, B, C )
    
    extern const EcArray <Char4, Letter> names2;
    
    //const EcArray <Char4, Letter> names { "alph", "brav", "char" };
    
    constinit const EcArray <Char4, Letter> names2
        { PairwiseTempInit::INST, Char4 { NoValue::INST},
          kv <Letter::A> ( "alp1" ),
          kv <Letter::B> ( "bra1" ),
          kv <Letter::C> ( "cha1" ) };
    
    
    int main()
    {
        std::cout << "Hello World!" << std::endl;
        return 0;
    }
    Ответ написан
    Комментировать
  • Как создать проект с++ на основе готового кода?

    @Mercury13
    Программист на «си с крестами» и не только
    У меня завелось сразу, хоть и с предупреждениями. Разумеется, проект приходится делать своими силами — и раз уж я использую Qt, сделал вот такой. Прокомментирую его по строчке.
    # Эти четыре строчки Qt установил сам, когда я через интерфейс сказал: нужен проект без Qt.
    # Я только заменил C++11 на 17, едва увидел make_unique.
    TEMPLATE = app
    CONFIG += console c++17
    CONFIG -= app_bundle
    CONFIG -= qt
    
    # Минимальная программа на MinGW требует трёх DLL’ек,
    # и для простоты развёртывания я прикрыл две из них.
    QMAKE_CXXFLAGS += -static-libgcc -static-libstdc++
    QMAKE_LFLAGS += -static-libgcc -static-libstdc++
    
    # Установлено через интерфейс
    SOURCES += \
        olcExampleProgram.cpp
    
    HEADERS += \
        olcPixelGameEngine.h
    
    # Как только дошло до ошибок линкера, я стал смотреть, чего не хватает.
    # А не хватает многого.
    LIBS += -lopengl32 -lgdi32 -lgdiplus -ldwmapi -lshlwapi
    
    # Это третья DLL’ка, которая нужна (была) минимальному проекту на MinGW.
    LIBS += -static -lpthread


    К сожалению, это преимущество Си и бич Си++ — сборка файлов в проект идёт неязыковыми мерами, и компиляторы Си первыми появлялись на машинах, где нет ничего, кроме ассемблерных утилит (линкера, библиотекаря). Систем сборки в мире даже больше, чем компиляторов.
    Ответ написан
    Комментировать
  • Как избавиться от явного задания типа в вариативном шаблоне (двухмерный массив, инициализируемый строчками)?

    @Mercury13 Автор вопроса
    Программист на «си с крестами» и не только
    #include <iostream>
    #include <array>
    
    #define consteval constexpr
    
    class Char4
    {
    public:
        using Array = char[5];
        using CppArray = std::array<char, 5>;
        consteval Char4(const char (&x)[5]) : fData { x[0], x[1], x[2], x[3] } {}
        constexpr std::string_view toSv() const { return { fData.asAr, 4 }; }
    private:
        union Ch {
            struct asInts {
                char a, b, c, d;
            };
            char asAr[4];
        } fData;
    };
    
    template <size_t N>
    class CArray4
    {
    public:
        using CppArray = const std::array<Char4, N>;
        constexpr size_t size() const { return N; }
        const Char4& operator [] (size_t i) const { return fBuf[i]; }
    
        template <class ... Args>
        consteval CArray4(Args&& ... x)
            : fBuf { x... }
        {
            static_assert(sizeof...(Args) == N, "CArray size mismatch");
        }
    private:
        CppArray fBuf;
    };
    
    
    namespace {
        CArray4<3> names { "alph", "brav", "char" };
    }
    
    
    int main()
    {
        std::cout << names.size() << std::endl;
        std::cout << names[2].toSv() << std::endl;
        return 0;
    }
    Ответ написан
    Комментировать
  • Что лучше unsigned int или long void?

    @Mercury13
    Программист на «си с крестами» и не только
    Что лучше: сóрок пя́ток или пятóк сорóк? © Винни-Пух
    unsigned int — это тип, поддерживающий положительные числа минимум до 65535 (а в современных реалиях — до 4 млрд)
    long void — нет такого типа в Си++.

    Да, я догадываюсь, вы хотите разницу между unsigned int и unsigned long. Unsigned long поддерживает не менее 4 млрд и в большинстве соглашений соответствует unsigned int (но иногда может давать 1,8·1019 — например, в Unix).

    Если вы пишете под конкретный процессор и конкретную ОС — пишите как угодно.

    Для простейшей кроссплатформенности x86/x64 Windows/Mac/Unix я вообще не рекомендую использовать long, используя int и long long. Для индексов в массиве (и прочего добра, чья длина зависит от длины процессора) используйте size_t и ptrdiff_t.

    Для широкой кроссплатформенности лучше использовать (u)int32_t (если важна арифметика переполнений или точное количество байтов), (u)int_fast32_t, (u)int_least32_t (если важно, чтобы хранило не менее N байтов).
    Ответ написан
    Комментировать
  • Инициализация элемента к нулю?

    @Mercury13
    Программист на «си с крестами» и не только
    1, 3. Просто совпадение, обычно потому, что компиляторы в отладочном режиме всё инициализируют нулями (проще отлаживать). На это нельзя рассчитывать, пиши HWND window = nullptr.
    2. Лучше написать std::string str;, да и всё. Можно рассчитывать, что будет пустая строка.

    Почему 1,3 плохо, а 2 хорошо? Потому что HWND и HRESULT — синонимы для встроенных типов (не то указатель, не то число того же размера), а у них конструктор по умолчанию ничего не делает. А string — нормальный себе объект.
    Ответ написан
    4 комментария
  • Как решить даную проблему?

    @Mercury13
    Программист на «си с крестами» и не только
    Тут всё просто: вы попытались разыменовать NULL-указатель.
    Надо хоть проверить, что наша нестандартная функция (с КиберФорума?) вернула.
    Ответ написан
    Комментировать
  • Почему выполнение программы ускоряется?

    @Mercury13
    Программист на «си с крестами» и не только
    Потому что у вас неэффективный алгоритм вычисления НОД, работающий на вычитании, а не на делении с остатком.
    Естественно, НОД(1,6) = НОД(1, 6−1=5) = НОД(1, 5−1=4) = НОД(1, 4−1=3) = НОД(1, 3−1=2) = НОД(1, 2−1=1) = НОД(1, 1−1=0) = 1
    НОД(2,6) = НОД(2, 6−2=4) = НОД(2, 4−2=2) = НОД(2, 2−2=0) = 2
    С арифметическим переполнением никак не связано. Просто даже в результате переполнения получились немаленькие числа.

    Как надо: НОД(1,6) = НОД(6, 1%6=1) = НОД(1, 6%1=0) = 1
    Аналогично для НОД(6,2) — в общем, сходится довольно быстро.
    Ответ написан
    Комментировать
  • Насколько работает линкер GOLD в MinGW и почему Invalid character?

    @Mercury13 Автор вопроса
    Программист на «си с крестами» и не только
    В 2021 используйте LLD.
    Ответ написан
    Комментировать
  • Существует ли библиотека Zip с потоковой записью?

    @Mercury13 Автор вопроса
    Программист на «си с крестами» и не только
    В конце концов перешёл на собственный порт MiniZip.
    Ответ написан
    Комментировать
  • Что означают фигурные скобочки и то что в них написано в векторе с++?

    @Mercury13
    Программист на «си с крестами» и не только
    Это так называемый «универсальный инициализатор» Си++11. Иногда это действительно initializer_list, но не сейчас. Здесь он эквивалентен вызову конструктора
    std::vector<char>(data.get(), data.get() + size)
    Ответ написан
    Комментировать
  • Как выводить переменную в MessageBox?

    @Mercury13
    Программист на «си с крестами» и не только
    Собственно, Александр Ананьев всё сказал.
    А я хочу дополнить.
    1. Вы решили заложиться на компиляцию ANSI/Unicode, но (LPCTSTR)L"Account Details" неправильно сконвертируется в ANSI. Правильно _T("Account Details"). Хотя двадцать два года спустя на компиляцию ANSI, думаю, можно и забить?
    2. MessageBox не предполагает выбора — зачем функции возвращать int?
    Ответ написан
  • Не понимаю задачу, немогу решить,объясните решение?

    @Mercury13
    Программист на «си с крестами» и не только
    Ваш код решает одну задачу, постоянно выводя 38 — и ту через какую-то задницу.
    Во-первых, надо ВВЕСТИ информацию, а не пережёвывать цифры 12 и 126 непонятно каким раком.
    Во-вторых, вам надо получить x = n % 50. Если он 0, то и вывести 0 — иначе вывести 50 − x.
    Ответ написан
    Комментировать
  • Vector - объявление элементов, в чем разница между двумя способами?

    @Mercury13
    Программист на «си с крестами» и не только
    Первый способ: создаётся initializer_list, вызывается конструктор. Наиболее эффективен для простых тупых объектов.

    Второй способ эквивалентен push_back(string("vec1")) и сильно полагается на оптимизацию передаваемых параметров. Наименее эффективен.

    Третий способ гарантированно не создаёт промежуточные объекты (вызывает конструктор string(const char*) уже на месте). Вместе с reserve(3) наиболее эффективен для управляемых объектов.

    UPD. 2 и 3 для string() не очень сильно различаются из-за эффективного переноса. А вот для более крупных объектов 3 лучше.

    UPD2. Начиная с Си++20, 1 лучше, но только из-за того, что Си++ научился делать полноценные string’и при компиляции — то есть управляемый объект string обзавёлся некоторыми чертами тупого.

    UPD3. Ни один компилятор пока constexpr string пока не поддерживает. Но ведь ни у кого стабильного 20 пока нет, правильно?
    Ответ написан
    9 комментариев
  • Как создать изображение из массива uint8_t?

    @Mercury13
    Программист на «си с крестами» и не только
    Дело не в этом. Массив 16·8 (вместо 32×32) и такая картинка — вероятно, формат 1-битный.
    Попробуйте Format_Mono или Format_MonoLSB.
    Ответ написан
  • Как переписать данный код?

    @Mercury13
    Программист на «си с крестами» и не только
    Я бы предложил поискать в коде ошибку, есть большое подозрение — первым множителем так и просится size. Ну или деление size %/ msize — невозможно сказать. Ну или условием будет не меньше, а больше или больше-равно. Но будем работать как есть.

    int v = msize / size;
    if (i < msize % size) ++v;
    int teqportion = msize * v;


    Почему подозреваю ошибку? Тут очень похоже на сильно поломанное округление вверх или вниз до кратного, в зависимости от условия.
    Ответ написан
    Комментировать
  • Как исправить ошибку в коде?

    @Mercury13
    Программист на «си с крестами» и не только
    1. Op= излишня, такая конструкция сама себя присвоит. С деструктором аналогично.
    2. Op+ — лучше пользоваться исключениями.
    3. Странное у вас устройство матриц — и не совсем константные, и менять нельзя.
    4. A[i][j] = i; — возможен выход за пределы массива.
    5. Если вывод матриц многострочный — подобный вывод не слишком удачный.
    Ответ написан
    Комментировать
  • Аргумент типа char не совместим с параметром типа const char*. Как исправить?

    @Mercury13
    Программист на «си с крестами» и не только
    Если вы узнали, что символ — цифра, просто вычтите из него '0'.
    meow[i] = gug[i] - '0';

    if (digit == true) не рекомендую писать, надо просто if (digit).
    Ответ написан
    Комментировать