Задать вопрос
Ответы пользователя по тегу C++
  • Почему код не работает C++?

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

    Переводите с английского!
    Ответ написан
    8 комментариев
  • Как реализовать сумму дробей?

    @Mercury13
    Программист на «си с крестами» и не только
    Заводим структуру-сумматор. Изначально она 0/1. Что-то типа
    typedef struct {
      int num, den;
    } Fraction;
    
    …
    
    Fraction sum = { 0, 1 };

    Дальше пишу псевдокодом, НОД и НОК разберись, как реализовать самому.
    для каждой очередной дроби
      ввести(дробь)
      новыйЗнам = НОК(сумматор.знам, дробь.знам)
      множСумм = новыйЗнам / сумматор.знам
      множДробь = новыйЗнам / дробь.знам
      новыйЧисл = сумматор.числ × множСумм + дробь.числ × множДробь
      сокрНод = НОД(новыйЧисл, новыйЗнам)
      сумматор.числ = новыйЧисл/сокрНод
      сумматор.знам = новыйЗнам/сокрНод

    Можно и оптимизировать, но тогда нужна хитрая разновидность алгоритма Евклида; в учебных целях не стоит.

    И ещё. Одна из известных ошибок в написании НОК — произведение аргументов не влезает в свой тип, а НОК влезает. Поймёшь, как в такой ситуёвине избавиться от переполнения?
    Ответ написан
    Комментировать
  • Как разобратся с кодом?

    @Mercury13
    Программист на «си с крестами» и не только
    Матрица имеет вид «хребта», на котором висят массивы-строки.

    Вставка работает так.
    1. Завести новый хребет.
    2. Завести новую строку.
    3. Посадить все остальные строки на новый хребет.
    4. Перенести новую матрицу на место старой.

    Удаление работает точно так же, только без 2.

    Как избавиться от говнокода.
    1. Стоило бы разделить интерактивное удаление и собственно удаление.
    2. Стоило бы тащить this (с какой матрицей работаем). А то на данный момент работаем с одной матрицей, и точка.
    3. Если уж методы — может, стоит писать в объектном стиле?
    4. Снова-таки, утечки памяти!
    Ответ написан
  • Как передать двумерный динамический массив в другую функцию?

    @Mercury13
    Программист на «си с крестами» и не только
    Есть два способа наладить динамический 2D-массив: «хребет» и «линейный массив».

    Хребет определяется как int** a = new int*[m];
    А затем каждый элемент хребта присваиваете new.
    Доступ a[i][j].

    Линейный массив определяется int* a = new int[m*n];
    Доступ a[i*n + j].

    Ваш случай — линейный массив, то есть
    void func(int a[], int n, int m)
    …
    func(a[0], n, m);


    Советую как-то заинкапсулировать эти массивы и передавать
    void dumpArray(const Array2D& x)
    К сожалению, у инкапсулированного массива нет хорошего способа сделать a[i][j], но можно a(i,j).
    Ответ написан
    2 комментария
  • Можно ли вынести реализацию шаблонного класса в отдельный cpp файл?

    @Mercury13
    Программист на «си с крестами» и не только
    Можно в таких случаях.
    1. Если у шаблона ровно N специализаций и (N+1)-й быть не может.
    2. Если он private и его синтаксически невозможно вызвать откуда-то ещё, кроме CPP.
    3. template<> (полностью специализированная функция без шаблонных параметров). Ей место именно в CPP, если она общедоступная и не inline.

    Стек, очевидно, ни к одному из этих случаев не относится.

    Код создаёт не сам шаблон, а его расшаблонивание!
    Ответ написан
    Комментировать
  • Что означают эти строки в коде?

    @Mercury13
    Программист на «си с крестами» и не только
    1. Указатель на указатель. Мы создаём 2D-массив как кучу динамических 1D-. Если 1D-массив — указатель, то массив из таких 1D- — массив из указателей, то есть указатель на указатель.
    2. Указатель простой (создать 1D-массив из указателей, который станет «хребтом» нашего 2D-).
    Ответ написан
    5 комментариев
  • Какие dll добавить в проект Qt, чтобы на удаленном компьютере работал доступ к MySQL?

    @Mercury13
    Программист на «си с крестами» и не только
    Если с MySQL работаем напрямую, то
    plugins\sqldrivers\qsqlmysql.dll
    libmysql.dll
    Ответ написан
    4 комментария
  • Как переставить в обратном порядке элементы массива, расположенные между его минимальным и максимальным элементами?

    @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);
    Ответ написан
    Комментировать