Задать вопрос
  • Как происходит визуализация интерфейса декстопных приложений?

    @Mercury13
    Программист на «си с крестами» и не только
    УРОВЕНЬ 1. ПРОГРАММНОЕ РИСОВАНИЕ. В экстремальном случае — программист сам рисует элементы управления, как на Canvas’е. Его опустим. Так, например, поступают в разработке игр, когда элементов мало, и они должны быть предельно стилизованы. Но и в таком случае лучше делать библиотеку объектов.

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

    УРОВЕНЬ 2. ОБЪЕКТНАЯ БИБЛИОТЕКА. Часто ОС и/или система программирования имеют свою библиотеку элементов управления. В таком случае получается что-то типа.
    program HomeMadeForm;
    
    uses
      Vcl.Forms, Vcl.StdCtrls;
    
    {$R *.res}
    
    var
      fm : TForm;
      bt : TButton;
    
    begin
      Application.Initialize;
      Application.MainFormOnTaskbar := True;
    
      fm := TForm.Create(nil);
      fm.Width := 400;
      fm.Height := 200;
      fm.Caption := 'Test';
    
      bt := TButton.Create(fm);
      bt.Parent := fm;
      bt.Caption := 'Go!';
      bt.Left := 150;
      bt.Top := 80;
    
      fm.ShowModal;
      fm.Free;
    end.


    УРОВЕНЬ 3. ВИЗУАЛЬНОЕ РИСОВАНИЕ. Наконец, существуют механизмы рисования форм: Qt Widgets, Qt Quick, VCL, WxWidgets, Windows Forms… В таком случае программист просто рисует форму, а про механизмы конструирования-позиционирования не думает. Создал форму, на неё поставил кнопку, к кнопке приделал событие OnClick — и вот уже при нажатии кнопки вызывается событие.
    5b006b57a3c2f727637474.png

    Существуют и HTML-подобные механизмы. Например, элементы HTML есть в Apache Cordova, обеих разновидностях Qt. Используют их, потому как удобно, но механизмы разбора HTML довольно сложны и потому не везде есть.
    Ответ написан
    Комментировать
  • Start xxx.bat: как сделать, чтобы не вываливалось в командную строку?

    @Mercury13 Автор вопроса
    Программист на «си с крестами» и не только
    start "32-bit" cmd /c 2.bat
    Ответ написан
    5 комментариев
  • Как запустить .EXE создаваемый Турбо Паскалем?

    @Mercury13
    Программист на «си с крестами» и не только
    Можно после запуска нажать Alt-F5, чтобы увидеть, что программа вывела.
    Есть там эта кнопка в меню — пункт не помню, а кнопку помню.
    UPD. Команда называется «User screen».
    Ответ написан
    Комментировать
  • Обьясните, что здесь происходит ++ndigi[c-'0']?

    @Mercury13
    Программист на «си с крестами» и не только
    '0' — это не число 0, а код символа «0». Во всех машинах, кроме совсем уж мамонтов, используются надмножества кодировки ASCII, и '0' = 48.

    И в ASCII, и в EBCDIC, и во внутренних кодировках, скажем, ЖК-индикаторов коды цифр идут последовательно от 0 до 9 — так что, отняв от кода цифры код символа «0», получаем числовое значение цифры.
    То есть ,
    '0' - '0' = 48 - 48 = 0
    '1' - '0' = 49 - 48 = 1
    ...
    '9' - '0' = 57 - 48 = 9
    (цифры справедливы для ASCII и его надмножеств, но в EBCDIC аналогично)

    В компьютере вообще нет понятия «символ», и что такое 48 — сорок восемь попугаев, X-координата на экране или код символа '0' — программист или компилятор должен думать сам. Так что Си (который, по сути, кроссплатформенный ассемблер), а ним и Java ставят очень эфемерную грань между одним и другим. В отличие от Паскаля, где надо писать Ord(c) - Ord('0').
    Ответ написан
  • Как решить проблему несовместимости const char* c параметром типа char* в VS?

    @Mercury13
    Программист на «си с крестами» и не только
    Есть три способа.
    1. Компилировать компилятором Си, а не Си++. Это отлично работает и даёт предупреждение в return NULL (который, впрочем, явно излишний).

    2. Проставить const-корректность. Поскольку наши структуры не управляют строками, а берут чужие, везде, где используются ключи, делать const.
    struct listnode {
      const char *key;
      int value;
    
      struct listnode *next;
    };
    И так далее, мест пять на всю программу.

    3. const_cast<char*>(someString). Иногда нужно (например, чтобы подружить std::string Си++03 и некоторые функции WinApi), но тут не наше дело.
    Ответ написан
    Комментировать
  • Что дает произведение 2х векторов в 2Д пространстве?

    @Mercury13
    Программист на «си с крестами» и не только
    В 2D существуют два произведения векторов (x,y) и (x',y').
    • Скалярное xx' + yy'. Проекция одного на другой, помножить на длину другого. Равна нулю, если векторы пперпендикулярны.
    • Косое xy' − x'y. Площадь параллелограмма на этих векторах. Равна нулю, если векторы коллинеарны.
    Ответ написан
    Комментировать
  • Как называется такая задача?

    @Mercury13
    Программист на «си с крестами» и не только
    Если считать, что любую передачу можно смотреть только целиком — это будет задача о заявках (=activity-selection problem).
    Решается жадным алгоритмом в таком виде. Берутся самые приоритетные передачи и решается классическая задача о заявках: берём ту, которая кончается раньше всех, затем ту, которая кончается раньше всех и не противоречит имеющейся… В «окна» тем же алгоритмом вставляют менее приоритетные, и т.д.

    Если считать, что можно бросать недосмотренные передачи — всё просто. При наступлении более приоритетной передачи переключаемся на неё.
    Ответ написан
    Комментировать
  • Что означает эта строка(модификатор в макросе)?

    @Mercury13
    Программист на «си с крестами» и не только
    Тут есть два модификатора.

    1. extern "C" — говорит, что функцию НЕ надо «козявить» на манер Си++, кодируя в имени её параметры наподобие h(int) → _Z1hi. Используется для доступа из Си++ к функциям, которые скомпилированы другим компилятором (Паскалем, Си…), а также для всяких там функций, которым надо дать фиксированное имя — например, функций DLL.

    2. __declspec(dllimport). Это нужно для доступа к функциям DLL: линкер будет брать функции прямо из DLL, без создания *.lib или *.a (как минимум MinGW так работает). Языки, сильно привязанные к определённой ОС (например, Delphi) могут создавать свои ключевые слова для доступа, например, к DLL или COM.
    procedure DoSomething(x : integer); cdecl;  external 'something.dll';

    Застандартизированный Си вынуждает полагаться на ключевые слова, начинающиеся с двух подчерков.
    Ответ написан
    Комментировать
  • Зачем нужен указатель на void?

    @Mercury13
    Программист на «си с крестами» и не только
    void* используется как указатель на сырые байтовые данные, не имеющие конкретного типа.
    Обычно это используется…
    1. В чтении-записи в файлы и на устройства, когда мы можем писать туда абсолютно любые типы.
    2. В «многоликих» функциях, которые могут принимать данные разных типов (malloc/calloc, часть функций WinAPI и ODBC).
    3. Как дескриптор — указатель, который запрещается разыменовывать. В Си для этого также часто используют указатель на недоопределённый тип, в Паскале с другими правилами эквивалентности типов — на пустой record. Но только пока не появится очередная многоликая функция вроде CloseHandle.
    4. Для обеспечения т.н. замыкания — передачи callback’у контекста, откуда была вызвана функция, вызвавшая callback.
    BOOL WINAPI EnumWindows(
      _In_ WNDENUMPROC lpEnumFunc,
      _In_ LPARAM      lParam
    );
    
    BOOL CALLBACK EnumWindowsProc(
      _In_ HWND   hwnd,
      _In_ LPARAM lParam
    );

    Вот этот LPARAM, который обычно определяется как какой-то указатель, и есть замыкание. Функция EnumWindows обещает передать его в функцию lpEnumFunc без изменений.
    (В Си++ для этого также используют виртуальные интерфейсы, но такой метод, сами понимаете, языкозависим и не годится для межъязыкового API.)

    Что происходит на стороне функции? Одно из двух (считаем, функция написана на ЯВУ).
    1. Либо вызывается некая функция устройства, которая говорит: «записать 100 байт», и дальше уже работает железо.
    2. Либо мы преобразуем void* в нужный нам тип и работаем с ним.

    Типы указателям дают по трём причинам.
    1. Вы забыли про операцию «разыменовать указатель». Чтобы его разыменовать, он должен иметь тип!
    2. Чтобы не ошибаться и не переприсвоить несовместимые указатели.
    3. Для полиморфизма — в Си++, давая delete x, мы даже можем не хранить, сколько байтов в блоке, поскольку мы знаем длину типа. (Есть ещё и виртуальные классы, но это другой вопрос.)
    Ответ написан
    Комментировать
  • Что за WINAPI, CALLBACK перед названиями функций?

    @Mercury13
    Программист на «си с крестами» и не только
    На x86 оба они — макроопределения для нестандартного соглашения вызова __stdcall.
    На ARM они ничего не делают.

    Соглашение вызова — это…
    • как на уровне регистров мы вызываем функцию;
    • кто подчищает стек за вызывающим;
    • кто отвечает за восстановление регистров, если они менялись (или есть риск, что они менялись).

    stdcall — вызов через стек, справа налево, за очистку стека отвечает функция, результат в eax (rax), функция отвечает за восстановление сегментных регистров, esp и ebp, программа за остальные.

    На ARM используется соглашение cdecl. То же самое, но за очистку стека отвечает программа (что там на ARM с регистрами, я не в курсе).
    Ответ написан
    Комментировать
  • Почему не совпадает сложность алгоритма?

    @Mercury13
    Программист на «си с крестами» и не только
    Это так называемая асимптотическая сложность — сложность при n→∞.

    Что никто не упомянул — так называемые символы Ландау.
    a(n) = o(b(n)), (читается «о малое», «меньшего порядка чем»), если lim{n→∞}a/b = 0
    a(n) = O(b(n)), (читается «о большое», «не большего порядка чем»), если a/b ограничено сверху (для дискретного n этого хватит, для непрерывного надо добавить «для какого-то n>N»).

    Два символа Дональда Кнута дополняют символы Ландау.
    a(n) = Ω(b(n)), если b(n) = O(a(n)). «Не меньшего порядка чем»
    a(n) = Θ(b(n)), если a(n) = O(b(n)) и b(n) = O(a(n)). «Такого же порядка».

    Ну а дальше идут простые пределы.
    • axn + bxn−1 + … = O(cxk + dxk−1 + …), если n ≤ k;
    • те же два многочлена o(·), если n < k.
    • те же два многочлена Θ(·), если n = k.
    Константа не важна: во-первых, при n→∞ меньшая сложность рано или поздно перевесит меньшую константу. Во-вторых, особенности реализации того или иного алгоритма на том или ином компиляторе/железе (больше/меньше команд, лучше/хуже с кэшем) эту константу могут варьировать в широких пределах;

    А значит, многочлен n(n−1)/2 = n²/2 − n/2 = Θ(n²).

    Да, и ещё: вы спутали асимптотический порядок самогó многочлена и асимптотическую сложность его вычисления. Первое, как я уже сказал, n². Сложность вычисления в лоб — n+const = O(n). А «не в лоб» — «за константу» , O(1).
    Ответ написан
    Комментировать
  • Зачем в абстрактном базовом классе создавать конструктор?

    @Mercury13
    Программист на «си с крестами» и не только
    Абстрактные классы делят на интерфейсы и частично реализованные. Грань между ними такова:
    • Интерфейс не имеет данных.
    • У интерфейса все неабстрактные виртуальные методы представляют собой или эталонное поведение, или самую частую реализацию. В обоих случаях, если что, их надо не расширять, а переписывать с нуля.

    Так вот, для интерфейсов таких конструкторов, разумеется, не нужно.

    Например, между абстрактным потоком и файлом Win32 может быть такая иерархия: Stream → HandleStream → File. Stream — интерфейс, даже если там есть что-то типа
    // virtual
    unsigned long long Stream::remainder() const { return size() - pos(); }


    HandleStream содержит уже данные (дескриптор Win32), и это уже частично реализованный класс, который крутится вокруг этого дескриптора: в деструкторе вызов CloseHandle, конструктор может принимать дескриптор, полученный каким-то «левым» образом.
    HandleStream::HandleStream(HANDLE aHandle) : fHandle(aHandle) {}
    HandleStream::~HandleStream() { close(); }
    
    void HandleStream::close()
    {
      if (Handle != INVALID_HANDLE)  { // не помню, как там эта константа в Win32
        CloseHandle(fHandle);
        fHandle = INVALID_HANDLE;
      }
    }

    Вот в таких полуреализованных классах, разумеется, конструктор может инициализировать те данные, которые там есть.
    Ответ написан
  • Как найти площадь объединения двух кругов(то что зеленым цветом)?

    @Mercury13
    Программист на «си с крестами» и не только
    Это сумма двух сегментов.
    Для каждого вычисляем угол, а дальше — ½R²(θ − sinθ).
    Ответ написан
    Комментировать
  • Законно парсить порно сайты?

    @Mercury13
    Программист на «си с крестами» и не только
    Какую информацию вы будете драть с сайтов?
    Если сам не очень легальный контент, то вы как минимум нарушаете авторские права владельцев порнухи.
    Ответ написан
  • Регрессия к среднему. Как найти коэффициент детерминации?

    @Mercury13
    Программист на «си с крестами» и не только
    Коэффициент детерминации тут ни к чему.
    Чтобы получить коэффициент детерминации, нужно много статистики и зависимость y(x).
    Этот товарищ, насколько я понял, использовал как модель единичный лаг. Взял много команд и футбольных сезонов, модель — сколько очков получено в прошлый год, зависимая переменная — сколько очков в этот год.
    Ответ написан
    Комментировать
  • Регрессия к среднему. Что за формула?

    @Mercury13
    Программист на «си с крестами» и не только
    R² — это так называемый коэффициент детерминации. Как он работает?
    Изначальная дисперсия переменной y будет D1.
    Наладили модель — дисперсия модели D2, которая, надо полагать, меньше D1 (особенно если вся выборка обучающая, без экзаменационной; здравствуй, переобучение!).
    Тогда R² = 1 − D2/D1 = (D1 − D2) / D1.

    Дисперсия, как известно, измеряется в квадратных попугаях. И, кроме того, для независимых величин D(x+y) = Dx+Dy. Таким образом, √(D1 − D2) ~ √R² — это тот разброс, который мы объяснили моделью.

    Но он, по-видимому, натягивает сову на глобус. В его модели объяснённый разброс — 0,780 (ещё и округлять не умеет), необъяснённый — √D2 ~ √(1 − R²) = 0,626, и в зависимости от того, что хочешь доказать, можно манипулировать статистикой в ту или иную сторону. Вот так я могу сказать, что с такими разбросами всего на 0,780 / (0,780+0,626) = 55% умение, и на 45% — удача. Так что нет, коэффициент детерминации, и точка. Повторяю, для независимых величин один разброс частично компенсируется другим, и D(x+y) = Dx+Dy. В квадратных попугаях.
    Ответ написан
    2 комментария
  • Как изменить систему счисления из 0-f в 0-z-Z?

    @Mercury13
    Программист на «си с крестами» и не только
    Скорее всего, какой-то вариант BASE64.
    Ответ написан
    Комментировать
  • Как найти число которое будет делиться без остатка на все элементы массива?

    @Mercury13
    Программист на «си с крестами» и не только
    Берём НОК. При расчёте НОКа случилось переполнение ((a · b) div b ≠ a) → нет такого.
    Дальше (MAX_UNSIGNED_LONG div НОК) · НОК.

    UPD. Поставил новый код обнаружения переполнений при умножении; старый явно ошибочный: 11·11 = 121, и при двух десятичных знаках будет 21 > 11.
    UPD2. В курсе, как считают переполнение-устойчивый НОК? НОК(x,y) = (x div НОД(x,y)) * y
    Ответ написан
    Комментировать
  • Матрица поворота плоскости изображения или вектора на центр камеры относительно осей координат?

    @Mercury13
    Программист на «си с крестами» и не только
    Первое. То есть в какую сторону смотрит объектив и как он повёрнут вокруг оси.
    Второе (указатель на центр камеры) — это вектор c.
    Ответ написан
    Комментировать
  • Решение уравнения 5 класса в Си?

    @Mercury13
    Программист на «си с крестами» и не только
    Это дело сложное. И я бы разделил его на три перекрывающихся этапа.
    1. Увидеть в строке уравнение от одной переменной. Например, в таком виде.
    5ac73cfdb0af3347885965.png
    2. Увидеть в том, что получилось, линейное уравнение.
    3. Запустить модуль «Линейное уравнение», который приведёт подобные слагаемые и высчитает ответ.
    Ответ написан
    Комментировать