• Почему точность вычислений в float нарушается для чисел определённой степени двойки?

    @Mercury13
    Программист на «си с крестами» и не только
    Связано, вероятно, с особенностями перевода дробных чисел в текст. Я попробовал повторить на Си++, ничего интересного не вышло. Зато методы перевода дробного в текст G++ и GRISU дают несколько разные результаты.
    Ответ написан
    Комментировать
  • В чем здесь ошибка (перегрузка операторов)?

    @Mercury13
    Программист на «си с крестами» и не только
    Вы наладили операцию String << ostream → ostream. Надо наоборот, ostream << string → ostream.

    Такую операцию можно наладить только за пределами класса (возможно, как friend).
    Ответ написан
    1 комментарий
  • Почему sizeof показывает фактический размер массива хотя по сути имя массива это указатель на первый элемент?

    @Mercury13
    Программист на «си с крестами» и не только
    Несмотря на то, что массив часто отождествляют с указателем, массив — это НЕ указатель. У него, например, другие операции приводят к неопределённому поведению.

    И самое противное в Си — это то, что в коде
    void sort(int x[5]);
    x — это не массив, а именно что указатель. Чтобы был массив, надо Си++
    void sort(int (&x)[5]);
    И компилятор даже подсвечивает, что параметр функции, отмеченный как массив — всегда указатель.
    typedef int Arr[SIZE];
    int sum(Arr arr, int n)
    // warning: 'sizeof' on array function parameter 'arr' will return size of 'int *' [-Wsizeof-array-argument]|
    Ответ написан
    Комментировать
  • Как написать визуализацию алгоритма сортировки в delphi?

    @Mercury13
    Программист на «си с крестами» и не только
    longclaps написал, как всё это дело должно выглядеть внешне.
    Внутренне это реализуется просто.
    1. В OnPaint какого-нибудь компонента (PaintBox, скажем) при определённых условиях выводим визуализацию.
    2. Блокируем весь пользовательский интерфейс (кроме какой-нибудь кнопки «Стоп»).
    3. Каждый раз, когда надо что-то увидеть, делаем paintBox.Repaint, Application.ProcessMessages и небольшую задержку.
    4. При нажатии кнопки «Стоп» ставим какую-то переменную в true. Сортировка реагирует на эту переменную и останавливает цикл: либо простым Exit, либо аварией Abort и последующей реакцией на EAbort.

    Если есть желание сравнить несколько алгоритмов сортировки, стоит сделать функцию типа DoSwap(i, j : integer), которая меняет местами элементы, устанавливает всё, что надо для визуализации, инициирует перерисовку и делает задержку.
    Ответ написан
    Комментировать
  • Что значит эта строчка?

    @Mercury13
    Программист на «си с крестами» и не только
    If the most significant bit is set, the key is down, and if the least significant bit is set, the key was pressed after the previous call to GetAsyncKeyState.

    Проверка на младший бит (сокращённая запись if ((GetAsyncKeyState(VK_F1) & 1) != 0). Он означает: с предыдущего вызова GetAsyncKeyState клавиша хоть раз нажималась. С одной стороны, этот бит нерекомендуемый (работает, когда нет других программ, вызывающих GetAsyncKeyState). С другой, возможно, младший бит GetAsyncKeyState() в современной реализации Windows работает именно так, как надо (если программа неактивна, GAKS возвращает 0).

    GAKS обычно используется в играх и прочих динамичных программах; в рабочем ПО используют оконные сообщения.
    Ответ написан
    1 комментарий
  • Как уменьшить связанность классов?

    @Mercury13
    Программист на «си с крестами» и не только
    1. Что такое Container и для чего он нужен? Возможно, от этого дела удастся избавиться или заменить интерфейсом?
    2. Не должен конструктор Graph брать в параметры Parser. Наоборот, Parser функцией parse() должен возвращать Graph.
    3. Config стоит разбить на несколько частей: одна специфична для Graph, вторая для Parser. Как их объединять — зависит от того, кому какие настройки нужны.
    Ответ написан
    2 комментария
  • Есть ли разница между двумя функциями?

    @Mercury13
    Программист на «си с крестами» и не только
    1. Будьте осторожны, перед нами динамический массив, сделанный расширением стека. Не на всех компиляторах есть, плюс стек ограничен парой мегабайт.
    Нормализацию размера лучше сделать shift %= size;
    Подпрограмма работает с локальной переменной и всё, что она делает, идёт на экран и больше никуда.
    (вообще стоит разделять обработку и вывод!)
    Время работы size.

    2. Сдвигаем на один элемент нужное количество раз. Время работы shift·size.

    3. Как за size «на месте»…
    квоПрох := НОД(shift, size)
    для i = [0..квоПрох)
      i1 := i
      tmp := a[i]
      вечный цикл
        i2 := (i1 + shift) % size
        если i2 = i
          прервать вечный цикл
        a[i1] := a[i2]    
        i1 := i2
      a[i1] := tmp
    Ответ написан
    Комментировать
  • Как создать "библиотеку" для NPC на языке C++?

    @Mercury13
    Программист на «си с крестами» и не только
    Из такого вопроса видно, что человек всё ещё нетвёрдо знает программирование, а уже пытается программить игру.
    И тут есть два варианта.

    1. Движок с нуля. Тонкая графическая прослойка наподобие SDL, оставляющая 100%-ю свободу движкописателям — это тоже «с нуля» и всячески рекомендуется даже продвинутым (не нужно писать всякие там Alt-Tab’ы и прочую дрянь, далёкую от игры). Тогда пусть начнёт с «питончика» (https://ru.wikipedia.org/wiki/Snake_(игра) ) или текстового квеста.
    А потом, когда доберётся до платформера или CRPG, он поймёт, каким образом привязать к монстру характеристики.

    Первое приближение (не слишком удобное для скриптования и подходящее для платформеров/action-RPG, но негодное в настоящих RPG) — сделать каждому компьютерному персонажу «класс» (не путать с классом ООП), включающий кол-во HP, внешний вид и прочее. А также «набор скриптов» — для поведения в диалогах, запрограммированного передвижения, превращения из «болванчика» в компьютерного врага, и т.д. Без набора скриптов он просто компьютерный враг, тупо нападающий на ПиСя.

    Если скриптовый движок чужой (тут уже не зазорно брать чужое) — вы уж смотрите, что он может и куда его впихнуть. А если хотите написать сами — лучше делайте триггеры, как в StarCraft.

    2. На чужом движке. Это уж смотрите, что движок может, какие возможности в нём «в коробке», а какие придётся дописывать своим кодом и чужими модулями. Не знаком ни с одним. Чужой движок — довольно противное дело для начинающего программиста: он автоматически формирует какую-то структуру программы, и программисту приходится не столько творить, сколько разбираться с этой структурой. С одной стороны, можно быстро написать довольно сложную игру, с другой — не так много радости «а у меня заработало».
    Ответ написан
    Комментировать
  • Как реализовать метод буквенного номера по числу?

    @Mercury13
    Программист на «си с крестами» и не только
    Вот мой действующий код на «Си с крестами». Индексы — ВНИМАНИЕ — начинаются с нуля. Сумеете перевести на Яву, и из второго оставить одни буквы? Первое действует для любой длины, второе — для длины до 3 символов, присущей Excel’ю.

    std::wstring xl::colNameW(
            size_t aIndex)
    {
        wchar_t q[21];  // more than enough even for 64-bit system :)
        wchar_t* ptr = q + 20;
        *ptr = 0;   // debug
    
        // Getting size
        size_t n = 1;
        unsigned long long pw = 26;
        while (aIndex>=pw && n<20)
        {
            aIndex -= static_cast<size_t>(pw);
            pw *= 26;
            ++n;
        }
    
        FOR_S(i, 0, n)  // макрос, означающий for (size_t i = 0; i < n; ++i)
        {
            *(--ptr) = static_cast<wchar_t>(L'A' + (aIndex % 26));
            aIndex /= 26;
        }
        return std::wstring(ptr, n);
    }
    
    namespace {
    
        bool isCap(const char* x, const char* aEnd)
        {
            return (x != aEnd && *x >= 'A' && *x <= 'Z');
        }
    
        bool isDig(const char* x, const char* aEnd)
        {
            return (x != aEnd && *x >= '0' && *x <= '9');
        }
    
    }   // anon namespace
    
    
    xl::CellCoords xl::parseCellCoords(
            const char* aStart, const char* aEnd)
    {
        enum {
            AA = 26,
            AAA = 26 + 26 * 26
        };
        xl::CellCoords r;
        // Letter
        r.col = 0;
        if (!isCap(aStart, aEnd))
            return CellCoords::bad();
        r.col = *(aStart++) - 'A';
        if (isCap(aStart, aEnd)) {
            r.col = (r.col * 26) + *(aStart++) - 'A';
            if (isCap(aStart, aEnd)) {
                r.col = AAA + (r.col * 26) + *(aStart++) - 'A';
            } else {
                r.col += AA;
            }
        }
        // Number
        r.row = 0;
        while (isDig(aStart, aEnd)) {
            size_t r0 = r.row;
            r.row = r.row * 10 + *(aStart++) - '0';
            if (r.row < r0)
                return CellCoords::bad();
        }
        if (r.row == 0 || aStart != aEnd)
            return CellCoords::bad();
        --r.row;
        return r;
    }


    Принцип действия перевода цифра → буква.
    Находим, сколько букв в нашей колонке. Допустим, три. Вычитаем из цифры номер колонки AAA (т.е. 26 + 26·26, если нумеровать с нуля, и 1 + 26 + 26·26 — если с единицы), и оставшееся переводим в 26-ичную систему счисления (A=0, B=1, C=2…).

    Принцип действия перевода буква → цифра аналогичен. Находим количество букв. Если их три, то переводим из 26-ичной системы счисления в цифру и прибавляем номер колонки AAA.
    Ответ написан
    Комментировать
  • Возникает ошибка Ошибка C4700 использована неинициализированная локальная переменная как исправить?

    @Mercury13
    Программист на «си с крестами» и не только
    #include "stdio.h"
    #include "stdlib.h"

    Лучше это писать в угловых скобках.

    double dr(double zb)
    {
        return zb = (rand() % 100) / (100 * 1.0);
    }

    Присваиваем параметру zb что-то, чтобы его похѣрить? Параметр будет жить до конца функции и НЕ ВЕРНЁТСЯ в вызвавшую программу (параметры передаются по копии).
    Кстати, параметр zb ни на что не используется: что бы вы ни передали туда снаружи, подпрограмма в этот параметр не посмотрит.

    printf("%lf", dr(double zb));
    На G++ не скомпилировалось. Ну, написал dr(0), благо параметр не используется ни на что.

    if (d == e)
    {
        printf("Win! your cash:%lf", winWay(a, b));

    C:\TestApps\ErrUninitLocal\main.cpp|30|warning: 'd' may be used uninitialized in this function [-Wmaybe-uninitialized]|
    А действительно, переменная d нигде никому не присваивается.

    И ещё одно. Я не знаю, как действует Visual C, но модификатор l для формата %f нужен для scanf, но не нужен для printf. Вот так-то всё это дело устроено.

    double a = winWay(a, b);
    }

    Что мы делаем? Присваиваем локальной переменной, чьё имя пересекается с более ранней переменной, чтобы её сразу же похѣрить? Она доживёт до ближайшей закрытой скобки.

    C:\TestApps\ErrUninitLocal\main.cpp|33|warning: 'a' may be used uninitialized in this function [-Wmaybe-uninitialized]|
    Тут вообще забавно работает. double a — считаем, что a определилась. = winWay(a, b) — считаем, что используется ОНА ЖЕ, а не более ранняя a. Естественно, неинициализированная.

    (аналогично с loseway)
    C:\TestApps\ErrUninitLocal\main.cpp|38|warning: 'a' may be used uninitialized in this function [-Wmaybe-uninitialized]|
    Ответ написан
    Комментировать
  • Как вернуть ссылку/указатель на элемент вектора?

    @Mercury13
    Программист на «си с крестами» и не только
    1.
    bool FindElement(const string& search, CElement*& result);

    2. CElement* FindElement(const string& search);
    Ответ написан
    1 комментарий
  • Что такое безсерверная обработка данных?

    @Mercury13
    Программист на «си с крестами» и не только
    Название странное. Это когда облачная платформа выделяет не сервер (виртуальную машину, контейнер), а какую-то функцию, и на каких серверах она работает — не важно.
    https://en.wikipedia.org/wiki/Serverless_computing
    Ответ написан
    Комментировать
  • Что такое 3D математика?

    @Mercury13
    Программист на «си с крестами» и не только
    Векторная алгебра (ну или векторная геометрия) в 3D.
    Векторы, матрицы, базисы, однородные координаты, видовые преобразования, кватернион поворота…
    Первый курс университета, покрывается курсом «Линейная алгебра и аналитическая геометрия».
    Дизайнеру не нужно.
    Ответ написан
    4 комментария
  • Нужно ли создавать интерфейсы для одного класса?

    @Mercury13
    Программист на «си с крестами» и не только
    1. Если из класса можно вытащить какую-то абстракцию. Например, из объекта «файл» можно вытащить абстракцию «поток». Личное — объект Project реализует интерфейс Modifiable с двумя функциями: modify() и isModified().

    2. Для упрощения юнит-тестирования при условии владения.
    Предположим, у нас есть класс «класс» (школьный) и класс «ученик». Ученик знает, в каком он классе.
    В такой ситуации получается «клубок»: если надо делать ученика, то надо делать и класс.
    Этот замкнутый круг можно разорвать, сделав интерфейс ISchoolClass и унаследовав от него класс. При юнит-тестировании заменяем класс на какую-то заглушку.
    Ответ написан
    Комментировать
  • Можно ли организовать связь между QT, mySQL и Excel?

    @Mercury13
    Программист на «си с крестами» и не только
    Qt и MySQL работают отлично и очень быстро. Маленькая подсказка: помимо DLL драйвера, который надо бросить в подкаталог plugins\sqldrivers, надо положить в РАБОЧИЙ каталог программы DLL MySQL или MariaDB (зависит от сборки Qt).

    С Excel’ем сложнее, и приходится искать любую Excel-библиотеку, имеющуюся на Си++.
    Из открытых — XLNT (кроссплатформенный) и QtXlsx (привязан к системе классов Qt).
    Мы используем частично LibXL (платный, тормозной, огромный расход памяти, но QtXlsx ещё хуже, насколько я проверял), частично свой велосипед (минимум функциональности, оптимизирован под огромные XLSX — вплоть до того, что Excel берёт большую таблицу за 10 секунд, а мы за три, а LibreOffice вообще над ней размышляет минутами).

    Но это уже собственно вопрос: а что есть для Excel’я на Си++. Может, сырой XLNT довели до ума. Может, у вас нет огромных таблиц, и того, что есть, вам хватает…

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

    @Mercury13
    Программист на «си с крестами» и не только
    Так и надо, но не хватает только одного: каким-то образом обрезать строку после всего этого.
    for (…)
      s1[i] = s1[i + s2len]
    s1.resize(s1.length() - s2len);

    Не забывайте: если длина вашей строки — это strlen, то length() в цикле вызывать запрещено!

    Да, ещё вопрос: убрать ПЕРВОЕ вхождение или ВСЕ вхождения?
    Ответ написан
  • Как нарисовать на курсоре в RunTime?

    @Mercury13
    Программист на «си с крестами» и не только
    Попробуйте Brush.Color := $FF000000 or clBlue;. Велика вероятность, что механизмы работы с 32-битными изображениями тут слабоваты.
    Ответ написан
    1 комментарий
  • Как подключиться к глобальному интернету Маска?

    @Mercury13
    Программист на «си с крестами» и не только
    Потребуется специальная антенная решётка. По предварительным расчётам, она будет по размеру с коробку от пиццы. Пока выведены два спутника, она вряд ли где-то продаётся.
    И предварительная стоимость — 50$/мес — негуманная для страны, где интернет один из лучших в мире (ой, если бы ещё не роскомнадзоры и их украинские аналоги).

    (Долго вспоминал, как называется крупная спутниковая сеть голосовой связи — Iridium. Удивительно, что она ещё работает и для работы полагается именно что на Маска.)

    Нашёл.
    https://www.reddit.com/r/Starlink/comments/7zqm2c/...
    Ответ написан
    2 комментария
  • Как понимать алгоритмы?

    @Mercury13
    Программист на «си с крестами» и не только
    Есть три специфичных вида алгоритмов.
    • Математические. Из них я могу припомнить геометрические (выпуклая оболочка) и вычислительные (метод Рунге-Кутты).
    • Связанные с особыми структурами данных.
    • Параллельные.

    Для математических алгоритмов, естественно, нужна та область математики, с которой мы имеем дело. Скажем, для геометрических — векторная геометрия, для вычислительных — какие-то куски муть-анализа. Для вычислительных также важно понимать устройство чисел с плавающей запятой.

    Из общего — те части математики, которые служат основополагающими принципами работы компьютеров. Теория множеств, булева алгебра, комбинаторика, теория автоматов… Также важно изучить символы Ландау и понятие «асимптотическая сложность алгоритма».

    Для параллельных важно понимать архитектуру параллельных систем.
    Ответ написан
    Комментировать
  • Как скомпилировать QWT готовым Qt 5.10 MinGW-w64 Dynamic?

    @Mercury13 Автор вопроса
    Программист на «си с крестами» и не только
    Например, можно скомпилировать прямо через Qt Creator.
    Ответ написан
    Комментировать