Ответы пользователя по тегу C++
  • В чем проблема??

    @Mercury13
    Программист на «си с крестами» и не только
    Если упустить знак & вместо &&, в вашем коде три проблемы.
    1. Часть сравнений излишни: например, из тройки a >= b && a >= c && c <= b второе не нужно. Можно просто писать: c <= b && b <= a.
    2. Часть сравнений повторяется. Лучше было бы работать
    if (a >= b) {
       // куча сравнений
    } else {
       // ещё одна куча
    }

    3, самое главное. Может случиться, что ни одна ветка не сработает, и в переменных будет мусор! Непонятно, какова задача, так что не могу сказать, как исправить. Если независимо друг от друга отсортировать две тройки — зачем вы всё это делаете одним оператором?
    Ответ написан
    Комментировать
  • Как вставить значение строки как аргумент функции?

    @Mercury13
    Программист на «си с крестами» и не только
    1. В строковой переменной или строковом буфере собрать тело команды, экранируя параметры, если это нужно.
    2. Если это обёрнутый string, преобразовать в const char* — и пошёл.
    std::string command;
    char data1 = 'F';
    char data2 = 'C';
    command = std::string("color ") + data1 + data2;
    system(command.c_str());
    Ответ написан
    1 комментарий
  • Особености функций malloc/calloc/new?

    @Mercury13
    Программист на «си с крестами» и не только
    UPD2. Что значит «очищают данные»?

    а) Очищают данные = освобождают память. Сделать функцию, которая выделяет память в локальную переменную (и эта переменная, была бы уничтожена мусорщиком Java, вместе с выделенным массивом).

    1. Выяснить, сколько памяти свободно.
    2. Вызвать функцию.
    3. Выяснить ещё раз, сколько памяти свободно.
    4. Подождать пару секунд («мусорщик» точно сработал бы).
    5. Выяснить третий раз, сколько памяти свободно.
    Поскольку в C++ мусорщика нет, должно быть 1 > 3 = 5.

    Узнать кол-во памяти — дело непортабельное, на Windows и Linux свои функции, см. stackoverflow.com/questions/2513505/how-to-get-ava...

    UPD1. На Windows лучше использовать GetProcessMemoryInfo. В таком случае надо смотреть, сколько памяти программа съедает, и тогда 1 < 3 = 5. Поскольку внутренний менеджер памяти на своём уровне «закрысивает» немного памяти, лучше выделять много памяти, порядка мегабайта.

    б) Очищают данные = забивают их нулями (наверно, всё-таки это). Выделить буфер подлиннее (или кучу буферов по одному int) и убедиться, что там не нули. Желательно компилировать программу на разных настройках — например, в Debug программа может забивать данные нулями или чем-то вроде DEADBEEF, а в Release — выдавать мусор.
    Ответ написан
  • Как в C++ распределяется память?

    @Mercury13
    Программист на «си с крестами» и не только
    Это называется фрагментация памяти. Некоторые «мусорщики» (как в Java или C#) способны сдвинуть объекты и получить большой непрерывный отрезок.
    Менеджер памяти C++ дефрагментировать память не способен и выдаст нехватку памяти.
    В любом случае, массив — что в Java, что в C++ — будет занимать непрерывный отрезок памяти.

    Чтобы совмещать мусорные языки с системными интерфейсами, есть способы пометить структуру как неперемещаемую. Но это уже на стыке виртуальной машины Java/C# и системного кода, который пишется на Си(++).
    Ответ написан
    9 комментариев
  • Почему не сохраняет и не выводит последнее введенное число?

    @Mercury13
    Программист на «си с крестами» и не только
    Код while (cin >> val) подразумевает, что мы ждём конца консоли.
    Если консоль перенаправлена из файла — ну, с этим всё понятно.
    А если нужно сделать конец в настоящей консоли, нажмите Ctrl+Z.

    Код высчитывает количество введённых подряд одинаковых чисел; если мы вводим другое или заканчиваем поток — он выводит, сколько их было.
    Ответ написан
    Комментировать
  • Qmake not using precompiled headers?

    @Mercury13
    Программист на «си с крестами» и не только
    По документации Qt, нельзя.

    Зато можно исключить Си++ из предкомпиляции простым методом.

    // Add C includes here
    
    #if defined __cplusplus
    // Add C++ includes here
    #include <stdlib>
    #include <iostream>
    #include <vector>
    #include <QApplication> // Qt includes
    #include <QPushButton>
    #include <QLabel>
    #include "thirdparty/include/libmain.h"
    #include "my_stable_class.h"
    ...
    #endif


    doc.qt.io/qt-5/qmake-precompiledheaders.html

    Самому так пригодилось (правда, на MinGW, а не на MSVC).
    Ответ написан
    1 комментарий
  • Как реализовать наследование статического поля/метода, если это возможно?

    @Mercury13
    Программист на «си с крестами» и не только
    Первое. Объясни, для себя и для меня, что собой представляет объект Command?

    Моё видение — разделить объекты Command (введённая пользователем и разобранная строка) и Program (программа, реализующая команду). Также я нарисовал — хочешь, используй, хочешь, нет — объект Console (консоль ввода-вывода) и System (окружение программы вроде текущего каталога, переменных окружения, файловой системы).

    Я тут работаю со значениями и указателями, в терминах C++03, но, возможно, вас заинтересуют умные указатели C++11.

    std::string commandLine = console.getSomeCommandLine();
    Command command;
    std::string error;
    if (!command.parse(commandLine, error)) {
      console.err().writeln(error);
      return;
    }
    Program* program = system.findProgram(command.programName);
    if (!program) {
      console.err().writeln("Bad command or file name");
      return;
    }
    Console redirectedConsole = console.redirectStreams(command);
    program->exec(redirectedConsole, system, command.getArguments());


    Второе. Возвращай ссылки, это быстрее.
    const std::vector<std::string>& getArguments() const;
    const std::vector<std::string>& getOptions() const;
    Ответ написан
  • Почему не работает libcurl?

    @Mercury13
    Программист на «си с крестами» и не только
    Как ни странно, нужна версия libcurl с поддержкой HTTPS.
    Большинству таких версий в нагрузку нужны два файла OpenSSL — libeay32.dll, ssleay32.dll.
    Ответ написан
    Комментировать
  • Ошибка C++ Builder XE Unable to open file 'ODBCPROVIDER150.OBJ'. Кто-нибудь поможет?

    @Mercury13
    Программист на «си с крестами» и не только
    1. Этого файла не будет, он скрыт в файле с расширением lib. Найдём его. Если нет — значит, библиотека не была скомпилирована под Builder.
    2. Tools → Options → C++ Options → Paths and Directories → Library Path.
    Ответ написан
    Комментировать
  • Qt. Как использовать сигналы-слоты?

    @Mercury13
    Программист на «си с крестами» и не только
    Нет, мы заводим где-то новый слот и подаём сигнал в него.
    Есть два способа завести новый слот: либо унаследоваться от QObject или его наследника (удобно унаследовать главную форму), либо воспользоваться лямбда-функцией C++11. Поскольку все наши формы на стеке, проще всего написать лямбду.

    connect(&Button, &QPushButton::clicked, 
                &Base, [&]() {
            // тут код
        });


    В реальных проектах каждая форма является наследником от QWidget (или чего-то подобного) и хранит свои компоненты. А слоты — это функции в форме.
    Ответ написан
    7 комментариев
  • C++ Builder и ProgressBar. Как сделать постоянное отображение квадратика бегающего слева направо?

    @Mercury13
    Программист на «си с крестами» и не только
    Нужно дать возможность оконным сообщениям ходить и обрабатываться.

    Простой способ. Поминутное Application->ProcessMessages().
    Сложный способ. Вынести долгую операцию в поток.

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

    @Mercury13
    Программист на «си с крестами» и не только
    Что вы имеете в виду? Инициализировать и закрыть библиотеку по мере появления-исчезновения объектов? Вот мой код (работает с cURL, но понятно).

    В чём его смысл? Как только объект cURL требуется первый раз, инициализируем глобальный объект. Теперь, скорее всего, cURL будет разрушен с его деструктором. Но если в каком-то потоке объект cURL будет слишком долго жить — ничего, подождём.

    (Внимание, тут гонка, если одновременно потребуются два объекта cURL. Нам такое не нужно, но если вдруг — защитите по принципу Singleton’а.)

    namespace curl {
    
        std::atomic<size_t> nLib(0);
    
        class _Lib
        {
        public:
            bool isIn = false;
            ~_Lib();
        };
    
        _Lib lib;
    
        void addLib()
        {
            int q = ++nLib;
            if (q == 1) {
                lib.isIn = true;
                q = ++nLib;
                curl_global_init(CURL_GLOBAL_ALL);
            }
            //std::cout << "Added lib, now " << q << std::endl;
        }
    
        void releaseLib()
        {
            int q = --nLib;
            if (q == 0) {
                //std::cout << "Cleaned up lib" << std::endl;
                curl_global_cleanup();
            } else {
                //std::cout << "Released lib, now " << q << std::endl;
            }
        }
    
        _Lib::~_Lib()
        {
            if (isIn)
                releaseLib();
        }
    
    }
    
    curl::Curl::Curl()
    {
        addLib();
        fData.handle = curl_easy_init();
    }
    
    curl::Curl::~Curl()
    {
        if (fData.handle)
            curl_easy_cleanup(fData.handle);
        releaseLib();
    }
    Ответ написан
    Комментировать
  • Как перевести число в строку с++?

    @Mercury13
    Программист на «си с крестами» и не только
    Ошибка вот где.
    else {
                cout<<"False";
                return 0;
            }
        }

    Проверяет только первую цифру, и если она не 3 — сразу же говорит false.
    Ответ написан
  • Часто ли .net программисты сталкиваются в работе с с++?

    @Mercury13
    Программист на «си с крестами» и не только
    Существует версия C++ для .NET — называется C++/CLI. Но в целом нет нужды в управляемой мусорной среде писать на C++, языке, рассчитанном на старый добрый машинный код и который таскает в архитектуре кучу «хвостов» времён ассемблеров.
    Так что мой ответ — в 99% случаев нет.
    Ответ написан
    Комментировать
  • Можно ли сделать массив меток goto?

    @Mercury13
    Программист на «си с крестами» и не только
    Вы не представляете себе, так обычно и работает switch.
    prog21.dadgum.com/166.html
    Ответ написан
    5 комментариев
  • Как на C++ узнать количество передаваемых аргументов?

    @Mercury13
    Программист на «си с крестами» и не только
    Какие есть способы физически, на уровне машинного кода, передать переменное число параметров в подпрограмму?

    1. Автобоксинг в массив. Если к тому же тип элементов может быть любым — тогда будет массив «лёгких» или обычных variant’ов, или массив объектов на «куче». В Delphi для этого используется лёгкий variant (см. SysUtils.Format), в Java и других «мусорных» языках — объекты на куче. В Си++ нет.

    2. Автоматически развернуть такой вызов в кучу вызовов поменьше. См. вариативные шаблоны C++11 = variadic templates. В Си++ есть, штука тяжёлая, я с ней и сам знаком поверхностно и ничего толком рассказать не могу. Но вот кое-что набросал.
    #include <iostream>
    
    constexpr int countArgs() { return 0; }
    
    template <class Arg, class ... Args>
    constexpr int countArgs(const Arg& x, const Args& ... args)
    {
        return countArgs(args...) + 1;
    }
    
    int main()
    {
        std::cout << countArgs() << std::endl;
        std::cout << countArgs(1, 2, 3) << std::endl;
        return 0;
    }

    Может быть, и первый путь удастся завернуть в массив через вариативные шаблоны, но я не в курсе. А вот обрабатывать аргументы по одному — за милую душу!

    3. Использовать особые соглашения вызова и раскручивать стек, пока не попадётся какой-то маркер «больше параметров нет» (см. работу с формами cURL), или окольным путём узнать количество параметров (см. printf). Есть даже в Си (который не что иное, как «ассемблер высокого уровня»), штука очень системная и чреватая ошибками.

    4. Возможна ещё и такая фишка: физически оно устроено как printf, но обёрнуто в «лёгкий» вариативный шаблон, который защищает всё это добро от ошибок программиста.
    #include <iostream>
    #include <cstdarg>
    
    constexpr int countArgs() { return 0; }
    
    template <class ... Args>
    constexpr int countArgs(int x, Args ... args)
    {
        return countArgs(args...) + 1;
    }
    
    void outArgsInner(int count, ...)
    {
        va_list ap;
        va_start(ap, count);
        if (count > 0) {
            std::cout << va_arg(ap, int);
            for (int i = 2; i <= count; ++i) {
                std::cout << ' ' << va_arg(ap, int);
            }
        }
        va_end(ap);
        std::cout << std::endl;
    }
    
    
    template <class ... Args>
    inline void outArgs(Args ... args)
    {
        outArgsInner(countArgs(args...), args...);
    }
    
    int main()
    {
        outArgs();      // пустой тоже работает
        outArgs(1, 2, 3);
        // outArgs("a", 2, 3);   тут ошибка! — и верно, мы принимаем только int’ы
        return 0;
    }
    Ответ написан
    Комментировать
  • Как лучше задать табличную функцию с редкой областью определения?

    @Mercury13
    Программист на «си с крестами» и не только
    Если аргументы до 100, функция заранее известна и неизменна — чхайте на всё и делайте простым массивом. Именно так, таблицей переходов, внутри устроен switch. Всё, что я пишу ниже — для общего развития.

    Это называется «разреженный массив» (sparse array)

    1. Хэш-таблица (std::unordered_map).
    Преимущество: есть «в коробке», очень быстра.
    Недостаток: ест много памяти.

    2. Я также использую вот такой механизм.
    template <class T>
    class ChunkMap
    {
    public:
        // Data access
        //------------------------------------------------------------------------//
        /// @return  data at index t, or empty value
        T get(size_t t) const;
    
        //------------------------------------------------------------------------//
        /// Sets data at index t (empty value to erase)
        void put(size_t t, T x);
    
        //------------------------------------------------------------------------//
        /// Erases range [0..maxPlus)
        void eraseTo(size_t aMaxPlus);
    
        // Info
        size_t nChunks() const { return fChunks.size(); }
        bool isEmpty() const { return fChunks.empty(); }
    
        //------------------------------------------------------------------------//
        /// @return  the number that is beyond all chunks
        size_t ceil() const;
    
        //------------------------------------------------------------------------//
        /// @return  actual number of records in the map
        size_t size() const;
    
        //------------------------------------------------------------------------//
        /// @return  lowest value in the map; (0, empty) if empty
        std::pair<size_t, T> lowerValue() const;
    
        //------------------------------------------------------------------------//
        /// @return  highest value in the map; (0, empty) if empty
        std::pair<size_t, T> upperValue() const;
    
        //------------------------------------------------------------------------//
        /// @return  (t1, v), t1 <= t;  (0, empty) if none
        std::pair<size_t, T> lowerOrEq(size_t t) const;
    
        template <class Body> void loop(const Body& r) const;
        template <class Body> void loopFrom(size_t aMin, const Body& r) const;
    
        //------------------------------------------------------------------------//
        ///  Loops all data. Body is bool-convertible.
        ///  Return true → go on.
        ///  Return false → stop and return false.
        template <class Body> bool loopBool(const Body& r) const;
    
        void clear() { fChunks.clear(); }
    
        constexpr static T emptyValue() { return std::numeric_limits<T>::max(); }
        static bool isEmptyValue(const T& x) { return (x == emptyValue()); }
    
        constexpr static unsigned chunkSize() { return Chunk::SIZE; }
    
    private:
        struct Chunk
        {
            enum { SIZE = 8 };
            Fix1d<T, SIZE> data;   // мой шаблон, массив фиксированного размера с проверкой на выход за границы
    
            Chunk();
            bool isEmpty() const;
            std::pair<size_t, T> lowerValue(size_t aKey) const;
            std::pair<size_t, T> upperValue(size_t aKey) const;
        };
        typedef std::map<size_t, Chunk> Chunks;
        Chunks fChunks;
    };

    Можно делать и на unordered_map при желании, но мне нужна lowerOrEq().

    Преимущество: экономия памяти, если есть несколько значений рядом.
    Недостаток: больше расход памяти (ненамного).

    3. Вот ещё есть реализация на Java.
    https://android.googlesource.com/platform/framewor...
    Преимущество: серьёзная экономия памяти.
    Недостатки: когда массив велик (тысячи заполненных элементов), снижается скорость доступа. Большие расходы на чистку мусора.
    Ответ написан
    Комментировать
  • Как обрабатывать события в Qt?

    @Mercury13
    Программист на «си с крестами» и не только
    Вы, разумеется, орудуете встроенным в Qt Creator редактором форм…
    1. Визуально: ПКМ, Go to slot…
    Программно: функцией connect, это описал AtomKrieg.
    2. Все компоненты находятся в доп. объекте ui. Когда вы делаете форму программно, им не обязательно там быть, но редактор форм делает именно так.
    if (ui->textEdit->text() == "Hi") label->setText("Hi!");
    Ответ написан
  • Как задать програмнно отобразить поверх других форм форму вызванную через Show()?

    @Mercury13
    Программист на «си с крестами» и не только
    Комментировать
  • Передача данных по ftp. Как сделать?

    @Mercury13
    Программист на «си с крестами» и не только
    Наиболее известная штука — cURL. Помимо FTP, поддерживает FTP+TLS и SFTP.
    Вот пример для FTP-закачки.
    https://curl.haxx.se/libcurl/c/ftpupload.html

    На C++ лучше использовать «плюсовые» обёртки для cURL, но код в целом такой же.
    Ответ написан
    Комментировать