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

    @Mercury13
    Программист на «си с крестами» и не только
    Найти индекс минимального и максимального.
    Если нужно, поменять местами, чтобы один был меньше другого. ИНДЕКСЫ, не элементы.
    А теперь цикл.
    ++низИндекс
    --верхИндекс
    пока низИндекс < верхИндекс
      поменять a[низИндекс], а[верхИндекс]
      ++низИндекс
      --верхИндекс

    Если индексы беззнаковые, надо проверить как-то, что первое --верхИндекс не приведёт к «антипереполнению». Например, «если верхИндекс > 0»…
    Ответ написан
    Комментировать
  • Как подключиться к MySQL из Qt?

    @Mercury13
    Программист на «си с крестами» и не только
    Нужны две DLL’ки: libmysql.dll в каталоге с программой, и qsqlmysql.dll в каталоге plugins/sqldrivers.
    От подкаталога plugins можно избавиться, написав в программе

    QApplication a(argc, argv);   // это наша программа, обычно создано автоматом
    a.addLibraryPath(QCoreApplication::applicationDirPath());


    От sqldrivers, насколько мне известно, так нельзя.
    Ответ написан
    Комментировать
  • Как QFileDialog вывести диалог открытия файла и получить имя файла в char?

    @Mercury13
    Программист на «си с крестами» и не только
    this — это скрытый параметр каждого не-static-метода, который говорит: для какого объекта он вызван. Если этот объект не QWidget, или функция static, или вообще не метод, то или подставляйте другой QWidget (это значит: кнопка на панели задач та же, что и у этого QWidget), или ставьте NULL (завести новую кнопку на панели задач).

    В вашем случае, разумеется, NULL. Или nullptr, если работаете в Си++11.

    QString *qs = new QString("переведи меня в чары! :)");
    char const* ch = qs->toLocal8Bit().constData();

    Верно придумали, только нет нужды заводить строку в куче операцией new. Строка в Qt и так достаточно «экономная», так что хватит
    QString qs("переведи меня в чары! :)");
    char const* ch = qs.toLocal8Bit().constData();

    Только не забывайте про время жизни этого char const*: он будет жить ровно столько, сколько будет жить конкретное значение строки.
    Ответ написан
    Комментировать
  • Можно ли в C++ узнать позицию с которой начинается подстрока без перебора символов в строке?

    @Mercury13
    Программист на «си с крестами» и не только
    1. Надо проверить pSubStr на NULL. Если оно так — не найдено.
    2. Всё наоборот, pSubStr - str.
    Ответ написан
    Комментировать
  • Запуск консольного приложения при перетаскивании на него файла Drag&Drop C++?

    @Mercury13
    Программист на «си с крестами» и не только
    Перетаскивание просто запускает программу, подставив имя файла как параметр командной строки. Те самые argc и argv, передаваемые в main().

    Кроме того, очень желательно (если у вас Windows) работать в Юникоде (в MinGW настройка компилятора -municode, для других компиляторов разбирайтесь сами). Функция main меняется на _wmain, её параметры на int argc, wchar_t** argv. Хотя не обязательно, если пути не содержат расширенных символов.
    Ответ написан
    1 комментарий
  • Почему не видит функцию из библиотеки в Ардуино?

    @Mercury13
    Программист на «си с крестами» и не только
    Запомни раз и навсегда! Inline не создаёт кода, создаёт факт его использования где-либо.
    С одной стороны, inline-функция при каждом использовании должна быть определена. С другой, она не попадёт в объектный файл сама по себе.
    Потому inline держат в хедерах (кроме хитрых случаев вроде private inline, когда синтаксически нельзя эту функцию вызвать откуда попало, а хедер лучше не засорять).

    Когда доберётесь до шаблонов Си++ — они обладают теми же свойствами. Шаблон не создаёт кода, создаёт расшаблонивание. И тоже в хедерах, кроме хитрых случаев вроде private template или шаблона, у которого есть ровно N предопределённых специализаций и (N+1)-я не нужна.

    А вот полная специализация шаблонной функции типа template<> (в угловых скобках пусто, не inline) создаёт и ей место в CPP.
    Ответ написан
    4 комментария
  • Как сделать и вывести срез строки(String) C/C++?

    @Mercury13
    Программист на «си с крестами» и не только
    1.
    std::cout << text.substr(начало, длина) << std::endl;

    Поскольку перед нами учебный текст, дальше не буду подсказывать. Методом тыка выясни, что будет началом и что длиной.

    2. Ничего, что, если строка не оканчивается точкой, последнее «недопредложение» выведено не будет? Может быть, так и верно, но если задача — разделить текст по tab’ам или запятым, надо после цикла выкинуть то, что осталось.
    Ответ написан
    Комментировать
  • Удаление объекта в C++ без создания его через new, или можно ли удалять объекты взятием адреса (&)?

    @Mercury13
    Программист на «си с крестами» и не только
    > Объект BaseClassObj будет удален только по завершению программы.
    BaseClass baseClassObj;
    Здесь создаётся объект на стеке. Имя — это просто имя объекта. Никаких указателей здесь нет. Как только мы покинем блок (любым образом: штатно выйти, goto, break, выброс аварии — кроме «жёсткого» выхода из программы функциями типа exit), у объекта автоматически исполнится деструктор и прямой вызов не нужен. Блок, то есть подпрограмму BaseClassPresentation.

    BaseClass *BaseClassObjPtr = new BaseClass(2);
    Здесь BaseClassObjPtr это имя указателя (а не указатель на указатель). Объект создаётся в динамической памяти, и его придётся уничтожать вручную. Многое в Си++11 сделали для того, чтобы подобные объекты уничтожались не вручную, а всё теми же автодеструкторами.
    std::unique_ptr<BaseClass> BaseClassObjUp = new BaseClass(2);
    Это уже маленький объект со своим деструктором. А в деструкторе находится delete, и он сработает, как только программа выйдет из своего блока.

    То, что вы хотите, иногда бывает нужно, и я вижу этому две причины.
    1. Объект управляет какими-то сложными и важными ресурсами: большим количеством памяти, файлом, мьютексом… И этот важный ресурс бывает нужно освободить раньше, чем наступит деструктор. Например, у любого файлового потока есть функция close() — она закрывает файл.
    2. У нас сложное и хитрое управление памятью, когда приходится использовать placement new и прямой вызов деструктора. Скажу честно, не использовал никогда. Как и 90% программистов на Си++.
    Ответ написан
    9 комментариев
  • При компиляции VC++, Opencv 3.2 проекта не работает exe на другой системе, требует opencv_world330.dll что делать?

    @Mercury13
    Программист на «си с крестами» и не только
    Краш, вероятно, связан с другой вещью. Компилятор-то новенький, и на ту машину не успели подвезти его среду исполнения. Выясни, какие файлы нужны: MSVCR140.DLL, MSVCP140.DLL или MFC140U.DLL.
    (при условии, что сам OpenCV также скомпилирован C++2017; если нет — также нужны и файлы другого компилятора.)

    Если так и не удастся отыскать — найди программу Dependency Walker и точно найди, чего ей не хватает.
    Ответ написан
    6 комментариев
  • Как правильно из zip архива считать текстовый файл с помощью PHYSFS?

    @Mercury13
    Программист на «си с крестами» и не только
    Нужно закрыть Си-строку.
    int length = PHYSFS_fileLength(myfile)
    myBuf = new char[length + 1];
    int length_read = PHYSFS_read(myfile, myBuf, 1, length);
    myBuf[length_read] = 0;
    Ответ написан
    Комментировать
  • Как превратить то что вернет WM_CHAR в юникод?

    @Mercury13
    Программист на «си с крестами» и не только
    Recardo_Recoly,
    Понятно.
    1. Лучше использовать WM_UNICHAR, он работает и с кодами более 65535. Поддерживается как минимум WinXP.
    2. Как превратить кодовую позицию в UTF-8, есть много вариантов. Сейчас найду свой.

    enum {
        SURROGATE_MIN = 0xD800,
        SURROGATE_MAX = 0xDFFF,
        SURROGATE_LO_MIN = SURROGATE_MIN,
        SURROGATE_HI_MIN = 0xDC00,
        SURROGATE_LO_MAX = SURROGATE_HI_MIN - 1,
        SURROGATE_HI_MAX = SURROGATE_MAX,
        UNICODE_MAX = 0x10FFFF,
        U8_1BYTE_MAX = 0x7F,
        U8_2BYTE_MIN = 0x80,
        U8_2BYTE_MAX = 0x7FF,
        U8_3BYTE_MIN = 0x800,
        U8_3BYTE_MAX = 0xFFFF,
        U8_4BYTE_MIN = 0x10000,
        U8_4BYTE_MAX = UNICODE_MAX,
        U16_1WORD_MAX = 0xFFFF,
        U16_2WORD_MIN = 0x10000,
        U16_2WORD_MAX = UNICODE_MAX,
    };
    
    void str::putCpNe (char*& p, unsigned long aCp)
    {
        if (aCp <= U8_2BYTE_MAX) {  // 1 or 2 bytes, the most frequent case
            if (aCp <= U8_1BYTE_MAX) {  // 1 byte
                *(p++) = static_cast<char>(aCp);
            } else { // 2 bytes
                *(p++) = static_cast<char>((aCp >> 6)   | 0xC0);
                *(p++) = static_cast<char>((aCp & 0x3F) | 0x80);
            }
        } else {  // 3 or 4 bytes
            if (aCp <= U8_3BYTE_MAX) {  // 3 bytes
                *(p++) = static_cast<char>( (aCp >> 12)        | 0xE0);
                *(p++) = static_cast<char>(((aCp >> 6) & 0x3F) | 0x80);
                *(p++) = static_cast<char>( (aCp       & 0x3F) | 0x80);
            } else {    // 4 bytes
                *(p++) = static_cast<char>(((aCp >> 18) & 0x07) | 0xF0);
                *(p++) = static_cast<char>(((aCp >> 12) & 0x3F) | 0x80);
                *(p++) = static_cast<char>(((aCp >> 6)  & 0x3F) | 0x80);
                *(p++) = static_cast<char>( (aCp        & 0x3F) | 0x80);
            }
        }
    }
    
    void str::appendCp(std::string & s, unsigned long aCp)
    {
        char c[5];
        char* end = c;
        putCpNe(end, aCp);
        s.append(c, end);
    }

    Слово Cp у меня означает code point, кодовая позиция Юникода. Ne — no error-checking, без проверки кодовых позиций на корректность.

    В Си++ есть и штатные функции преобразования кодовых позиций Юникода в UTF-8 и UTF-16. Но страшны, как чёрт, и половина из них в C++17 deprecated :(

    И последнее, что я хочу сказать.
    Вы путаете две вещи: Юникод и его кодовые позиции, и форматы записи юникодных строк UTF-8 и UTF-16. Соотношение «один символ Юникода — один char» только в UTF-32!
    Ответ написан
    33 комментария
  • Как в С++ из INT сделать string16?

    @Mercury13
    Программист на «си с крестами» и не только
    UTF-8 — это многобайтовая кодировка и у неё нет кодов. Так что считаем, что имеем дело с кодами Юникода.
    Это только кусок моей мини-библиотеки, так что…

    Шаблон использовался, чтобы автоматически специализировать под нужную длину wchar_t, реально есть версии под 1 и 2.
    namespace str{
    
    enum {
        SURROGATE_MIN = 0xD800,
        SURROGATE_MAX = 0xDFFF,
        SURROGATE_LO_MIN = SURROGATE_MIN,
        SURROGATE_HI_MIN = 0xDC00,
        SURROGATE_LO_MAX = SURROGATE_HI_MIN - 1,
        SURROGATE_HI_MAX = SURROGATE_MAX,
        UNICODE_MAX = 0x10FFFF,
        U8_1BYTE_MAX = 0x7F,
        U8_2BYTE_MIN = 0x80,
        U8_2BYTE_MAX = 0x7FF,
        U8_3BYTE_MIN = 0x800,
        U8_3BYTE_MAX = 0xFFFF,
        U8_4BYTE_MIN = 0x10000,
        U8_4BYTE_MAX = UNICODE_MAX,
        U16_1WORD_MAX = 0xFFFF,
        U16_2WORD_MIN = 0x10000,
        U16_2WORD_MAX = UNICODE_MAX,
    };
    
    template <int Len>
    void putCpNeT (wchar_t*& p, unsigned long aCp);
    
    ///  Puts a code-point in wchar_t encoding, w/o error-checking
    ///  @param [in,out]  p     position to put to
    ///  @param [in]      aCp   code-point, surely valid
    inline void putCpNe (wchar_t*& p, unsigned long aCp)
        { putCpNeT<sizeof(wchar_t)>(p, aCp); }
    
    } // namespace str
    
    template <>
    void str::putCpNeT<2> (wchar_t*& p, unsigned long aCp)
    {
        if (aCp < U16_2WORD_MIN) {  // 1 word
            *(p++) = static_cast<wchar_t>(aCp);
        } else if (aCp <= U16_2WORD_MAX) {    // 2 words
            aCp -= U16_2WORD_MIN;
            // Hi word
            const wchar_t lo10 = aCp & 0x3FF;
            const wchar_t hi10 = aCp >> 10;
            *(p++) = static_cast<wchar_t>(0xD800 | hi10);
            *(p++) = static_cast<wchar_t>(0xDC00 | lo10);
        }
    }
    
    void str::appendCp(std::wstring& s, unsigned long aCp)
    {
        wchar_t c[5];
        wchar_t* end = c;
        putCpNe(end, aCp);
        s.append(c, end);
    }
    Ответ написан
    Комментировать
  • Можете помочь найти ошибку в коде?

    @Mercury13
    Программист на «си с крестами» и не только
    1. 1/2 = 0, надо писать 1.0/2.0 или просто 0.5.
    2. В printf немного другие правила, чем в scanf, и надо
    printf_s("max = %f\n", max);
    Ответ написан
    Комментировать
  • Может ли код(определение) в заголовочных файлах быть вынесен в shared library?

    @Mercury13
    Программист на «си с крестами» и не только
    Надо сделать CPP-файл, в которые перенести как можно больше кода из программы. И код производят:
    • Static- и глобальные переменные.
    • Нешаблонные, не-inline-функции.
    • Не-inline, полностью расшаблоненные функции template<>.
    • Не-extern объявление шаблона типа template class std::vector<int>.
    Мало того, эти четыре вещи ошибочно держать в хедерах — но этого, как ни странно, в нашей библиотеке и нет, ведь она полностью полагается на шаблоны. Но есть пара резервов.

    1. Функция в теле класса автоматически становится inline, и, я бы сказал, что-нибудь типа AsynchronousReader::init было бы ошибкой держать inline’ом. По-хорошему, его надо в CPP. Но это довольно небольшая часть кода.
    2. Можно также наиболее распространённые версии классов/функций залить в SO. Для этого их надо вынести из тел классов и поступить примерно так.
    // H
    template <int x>
    void foo () { std::cout << x << std::endl; }
    
    extern template void foo<2>();
    
    // CPP
    template void foo<2>();
    Ответ написан
    Комментировать
  • Qt+QMake: как задать настройки компиляции для конкретного файла?

    @Mercury13 Автор вопроса
    Программист на «си с крестами» и не только
    И снова приходится отвечать самому.

    #pragma GCC optimize("O1")
    #pragma GCC optimize("no-lto")
    Ответ написан
    Комментировать
  • Как посчитать количество совпадающих символов в обоих строках?

    @Mercury13
    Программист на «си с крестами» и не только
    3 тоже есть, так что правильный ответ 3. Ошибка тройная.
    for(size_t z = 0; z < b.length(); z++){
            if(a.find(b[z]) != std::string::npos){

    1. Индексы строк в STL беззнаковые, и компилятор может ругаться на сравнение знакового целого и беззнакового.
    2. На что тут 4, если есть s.length()
    3. Знак «не найдено» — std::string::npos.
    Ответ написан
    3 комментария
  • C++ QT почему не работает запрос к sql Lite DB?

    @Mercury13
    Программист на «си с крестами» и не только
    Нет, ваше решение неуниверсально и ваша ошибка — не заэкранировать идентификатор E-mail.
    Попробуйте [E-mail].
    (Часто используется экранирование `E-mail`, но в SqLite оно не катит, это специфика MySQL.)
    Ответ написан
    Комментировать
  • Зачем gcc просит подключить stdlib.h?

    @Mercury13
    Программист на «си с крестами» и не только
    Раз у вас stdlib.h закомментирован, вы, наверно, знаете, откуда malloc взялся. Попробуем раскрутить ошибки.

    note: include ‘ stdlib.h ’ or provide a declaration of ‘malloc’
    Компилятор, очевидно, знает, где этот malloc завалялся…

    warning: implicit declaration of function ‘malloc’ [-Wimplicit-function-declaration]
    …но неявно объявляет функцию.

    warning: incompatible implicit declaration of built-in function ‘malloc’
    Неявное определение int* malloc(int). Реальное void* malloc(size_t). Преобразовать (int*)malloc надо было.

    Почему всё-таки запустилось? А потому, что на целевой машине size_t = unsigned int, а размеры указателей совпадают практически всегда. После того, как функция неявно объявилась, линкер подцепил на её место стандартную, и соглашения вызова совпали.
    Ответ написан
    1 комментарий
  • Header в header'е и можно ли делать игру на одних Header'ах?

    @Mercury13
    Программист на «си с крестами» и не только
    Такой механизм называется «одна единица компиляции» и вполне имеет право на жизнь: на одном процессоре время полной сборки будет наименьшим, потому так распространяют некоторые библиотеки (SqLite, Google Test). Правда,
    игра — обычно масштабный проект, и чем больше будет кода, тем дольше нужно компилировать, чтобы проверить изменения.

    Потому код обычно разбрасывают по единицам компиляции (*.cpp) в соответствии с его внутренней логикой, и к каждой единице (кроме точки входа) приписывают хедер (*.h), который показывает, что эта единица делает. Повторяю, только описывает, что делает — весь код в CPP. И в большинстве случаев самый длинный этап сборки — линковка (особенно с оптимизацией по ходу линковки aka LTO).

    Единственное, что в 80% случаев не получается закинуть в CPP — это шаблоны.

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

    Чтобы не было циклических включений, для сохранения скорее всего потребуются два хедера: один отвечает за собственно процедуру сохранения и подключается к одному-единственному модулю — системе меню. Второй — за какие-то общие функции, которые позволяют сохраняться в абстрактный поток плиточному фону, снаряду, монстру… Называется как-нибудь SaveUtils.h и подключается повсюду.

    (Примечание. И SqLite, и Google Test разрабатывались по традиционной схеме, с проектом из кучи CPP. SqLite собирается в один большой *.c автоматикой, и я даже качал традиционный код — на 5-метровом файле некоторые версии Embarcadero вылетали с нехваткой памяти. В Google Test есть файл all.cpp или что-то подобное, в котором #include остальных CPP — пользователь подключает в проект all.cpp, и библиотека отнимает минимум его времени.
    Ответ написан
  • Почему Eclipse не подсвечивает тип данных string?

    @Mercury13
    Программист на «си с крестами» и не только
    Главная причина: int — ключевое слово Си++, а string — нет.
    Система программирования может подсвечивать стандартные контейнеры STL другим цветом. Вот, например, скриншот Code::Blocks.
    6cd9ef6d6e4346aaaac0de090af78f88.png
    Видите, ключевое слово char синее, а стандартный объект STL std::string — зелёный.
    (Да, специалисты, вижу, что на экране результат не слишком удачного рефакторинга. Для специализированной утилиты в шестьсот строк, думаю, покатит.)
    Ответ написан
    Комментировать