• Как сделать двойное условие в SQL запросе?

    @Mercury13
    Программист на «си с крестами» и не только
    AND всегда приоритетнее, чем OR. Надо так.
    WHERE (`categories_id` = '17' OR `categories_id_2` = '17' ...)
      AND (`categories_id` = '1' OR `categories_id_2` = '1' ...)

    Может, как говорит, oleg_ods, сработает связь 1:∞, может, и не сработает — но быстрое исправление запроса такое.
    Ответ написан
    1 комментарий
  • Как реализовать кастомный тип данных в c++ без использования нативной системой типов?

    @Mercury13
    Программист на «си с крестами» и не только
    На самом деле такое возможно единственным методом: через ассемблерные вставки. Чем-нибудь типа
    mov ecx, [data]
    mov byte ptr[ecx], 5

    Штатные типы позволяют, в числе прочего, интерпретировать те или иные байтовые данные разными методами. Вернёмся к одному байту. Он может быть…
    • числом
    • восемью флагами
    • четырёхбитовым числом и четырьмя флагами
    Ответ написан
    Комментировать
  • SOLID.LSP + ООП.Полиморфизм = противоречиe?

    @Mercury13
    Программист на «си с крестами» и не только
    LSP предписывает наследникам сохранять поведение (контракт) базового класса.

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

    Например, интерфейс Stream позволяет мультиплексированные потоки (то есть потоки, где мы не можем считать записанное, чтение и запись идёт по разным каналам и никак не связаны друг с другом — например, COM-порты), а какой-нибудь BufferedStream ограничивается только потоками, где мы пишем в какую-нибудь цепочку байтов (например, файл), и читаем из неё же, без мультиплексирования.
    Ответ написан
    2 комментария
  • Обьясните кто то про регистры в Ассемблере?

    @Mercury13
    Программист на «си с крестами» и не только
    У меня нет линукса, чтобы проверить, но, кажется, программа в корне неверна. Вы используете 32-битное соглашение вызова на 64-битной машине.
    https://www.informatik.htw-dresden.de/~beck/ASM/sy...
    https://blog.rchapman.org/posts/Linux_System_Call_...

    Откуда 32-битный вызов на x64 — дайте пруфлинк, может, в вашем линуксе так и есть.

    Регистры — это маленькие и очень быстрые ячейки памяти, встроенные в процессор. Их ограниченное количество, и у них конкретные чётко зафиксированные названия.

    Часто для работы с данными малых разрядностей и совместимости с ранним кодом процессор даёт доступ и к половинкам регистров. Так, нижняя половина регистра rax — eax, нижняя четверть — ax, половины ax (соответственно восьмушки rax) называются al и ah. Сами понимаете: когда процессор был 16 бит, регистр назывался ax = al + ah. Сделали 32 бита — стал eax. Сделали 64 бита — стал rax.

    Для вызова системных функций Linux используется такое соглашение вызова. Все функции висят на прерывании 0x80, rax — название функции, остальные параметры рассовываются по регистрам.

    Насчёт int, char, double. Знаковость (signed/unsigned) определяется инструкциями ассемблера (например, ja = jump if above для unsigned, jg = jump if greater для signed). Длина — задействованным куском регистра (rax = long long, eax = int/long, ax = short, al = char). С дробными числами работает отдельный блок процессора, т.н. сопроцессор, со своими регистрами (в первых x86 он был отдельной микросхемой, существовавшей не во всех компьютерах, отсюда название).
    Ответ написан
    4 комментария
  • Почему используют interface a не abstract class?

    @Mercury13
    Программист на «си с крестами» и не только
    И первое, и второе имеет право на жизнь.

    Второе действительно используется чаще: у нас есть готовая или полуготовая кнопка, и надо добавить в неё функциональность Нашей Крутой Кнопки™. К тому же слова вроде Clickable лучше подходят для названий интерфейса, чем Button.
    class Button {
      protected void paint(Canvas aCanvas) {}
    }
    
    class MyButton extends Button {
      @Override
      protected void paint(Canvas aCanvas) {}
    }


    А первое — например, мы хотим с Нашей Крутой Кнопкой™ работать как с кнопкой неизвестной функциональности, которая умеет только нажиматься и говорить, в каком она состоянии.
    interface Button {
      void press();
      boolean state();
      void addListener(ButtonListener x);
    }
    
    class GameObject {
      void paint(Renderer renderer);
    }
    
    class MyButton extends GameObject implements Button {
    }
    
    class FridgeGame implements ButtonListener {  // помните, такая была в «Братьях Пилотах»?
      Button buttons[][] = new MyButton[4][4];  
    }
    Ответ написан
    Комментировать
  • Как исправить ошибку err::name_not_resolved?

    @Mercury13
    Программист на «си с крестами» и не только
    Дождись, пока обновится провайдерский кэш DNS.
    Проблема в том, что DNS не может найти IP-адрес для этого домена, и обычно это связано с кэшированием этого самого DNS.
    Пока вы задавали вопрос, а он дошёл до меня, у Киевстара и какого-то открытого DNS (не помню, почему переписал обычный DNS Ланета) всё нормально закэшировалось.
    Ответ написан
    Комментировать
  • Погрешность чисел в c++?

    @Mercury13
    Программист на «си с крестами» и не только
    #include <iostream>
    #include <iomanip>
    
    int main()
    {
        double q = 1.0 / 6.0;
        std::cout << std::setprecision(9) << q << std::endl;
        return 0;
    }


    Float не годится, поскольку не даёт такой погрешности.
    Ответ написан
    Комментировать
  • Как подключить 2 монитора VGA к 1 компьютеру?

    @Mercury13
    Программист на «си с крестами» и не только
    Мы уже выяснили, что у вас есть разъём DVI и можно подключить второй монитор. ЕСТЬ ДВА ВАЖНЫХ МОМЕНТА.

    1. Встроенные и дешёвые видяхи обычно не могут выводить на два монитора, там один RAMDAC (или как сейчас эта деталь называется?) и разъёмы просто запараллелены. СМОТРИТЕ СПЕЦИФИКАЦИЮ.

    2. Есть два вида DVI, я их называю DVI+ и DVI−, по виду крестика на разъёме.
    Если крестик полный, в DVI есть VGA-линии, и покатит любой пассивный переходник, который можно купить за сотню на компоразборках или выпросить у знакомого сисадмина (если ты в Киеве — приходи, дам, остался один).
    Если неполный — нужны активные переходники вроде такого.

    https://ru.aliexpress.com/item/32884792319.html?sp...

    Сам удивился, что они на Али дёшевы, думал, 10…20$ стоят.

    Допустим, на моей старенькой 750Ti есть два DVI: один DVI−, другой DVI+. Так что если сменю карточку, а старую отдам брату — видимо, он сможет подключить её к старому монитору. Но только к одному: хочет второй — только DVI/HDMI. Или через активный переходник. Кстати, там четыре разъёма, но спецификации говорят: до 3 мониторов.
    Ответ написан
    3 комментария
  • Как законно использовать код который распространяется под MIT?

    @Mercury13
    Программист на «си с крестами» и не только
    В любом доступном месте About или сопроводительной документации.
    Если текстовая документация — любят делать файл «copying» с указанием всех, чей код позаимствован.
    Если система в вебе — лицензию должен видеть вебмастер (например, в файле «.copying», который не показывается сервером), а не конечный пользователь.
    В клиентском вебе достаточно где-то в .js сделать закомментированную ссылку на лицензию.
    Ответ написан
  • Как сделать графическую оболочку для консольного приложения?

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

    spoiler
    class ConStream : public st::Stream
    {
    public:
        ConStream();
        ~ConStream() override;
        bool open(
                const std::wstring& aFname,
                const std::wstring& aCmdLine,
                const std::wstring& aLog);
    
        // Console does not have remainder.
        st::Pos remainder() override { return 0; }
        // Only when we bumped into end.
        size_t eof() override { return fIsEof; }
        size_t readNe (void* aBuf, size_t aSize) override;
        size_t writeNe(const void* aBuf, size_t aSize) override;
        void flush() override;
        bool isOpen() override { return fIsOpen; }
    
        bool readln(std::string& s);
        void endInput();
    
        // Shall we implement close?
        //void close() override {}
    
        // Implemented capabilities
        unsigned long caps() const override
            { return st::cRead | st::cWrite | st::cMultiplex | st::cRealtime
                | st::cSizeUnaware; }
    private:
        st::AsyncFile fLog;
        bool fIsOpen = false;
        bool fIsEof = false;
        bool fFoundCr = false;
        STARTUPINFO si;
        PROCESS_INFORMATION pi;
    
        HANDLE hStdOutInside, hStdOutOutside;
        HANDLE hStdInInside, hStdInOutside;
        //HANDLE hStdErrInside, hStdErrOutside;
        //bool readln(std::string& s);
    };
    
    
    ConStream::ConStream()
    {
        SECURITY_ATTRIBUTES sa;
          // Security attributes
        sa.nLength = sizeof(SECURITY_ATTRIBUTES);
        sa.lpSecurityDescriptor = nullptr;
        sa.bInheritHandle = true;  // Help says the handle will be inherited
    
        SECURITY_DESCRIPTOR sd;
        if (isWinNT()) {       // security initialization for Windows NT
            InitializeSecurityDescriptor(&sd, SECURITY_DESCRIPTOR_REVISION);
            SetSecurityDescriptorDacl(&sd, true, nullptr, false);
            sa.lpSecurityDescriptor = &sd;
        }
    
        // Stdout pipe
        // read = outside, write = inside
        CreatePipe(&hStdOutOutside, &hStdOutInside, &sa, 0);
        SetHandleInformation(hStdOutOutside, HANDLE_FLAG_INHERIT, 0);
    
        // Stderr pipe
        // read = outside, write = inside
        //CreatePipe(&hStdErrOutside, &hStdErrInside, &sa, 1024*64);  // enough for stderr?
        //SetHandleInformation(hStdErrOutside, HANDLE_FLAG_INHERIT, 0);
    
        // Stdin pipe
        // read = inside, write = outside
        CreatePipe(&hStdInInside, &hStdInOutside, &sa, 1024*10);
        SetHandleInformation(hStdInOutside, HANDLE_FLAG_INHERIT, 0);
    }
    
    
    void ConStream::endInput()
    {
        if (hStdInOutside != INVALID_HANDLE_VALUE) {
            CloseHandle(hStdInOutside);
            hStdInOutside = INVALID_HANDLE_VALUE;
        }
    }
    
    
    ConStream::~ConStream()
    {
        if (fIsOpen) {
            if (WaitForSingleObject(pi.hProcess, 2000) == WAIT_TIMEOUT) {
                TerminateProcess(pi.hProcess, 0);
            }
    
            CloseHandle(pi.hThread);
            CloseHandle(pi.hProcess);
        }
        CloseHandle(hStdInInside);
        endInput();
        //CloseHandle(hStdErrOutside);
        //CloseHandle(hStdErrInside);
        CloseHandle(hStdOutOutside);
        CloseHandle(hStdOutInside);
    }
    
    
    bool ConStream::open(
            const std::wstring& aFname,
            const std::wstring& aCmdLine,
            const std::wstring& aLog)
    {
        if (fIsOpen)
            return false;
    
        // Fill startup info
        ZeroMemory(&si, sizeof(si));
        si.cb = sizeof(si);
        size_t n = aFname.length() + aCmdLine.length() + 10;
    
        si.dwFlags |= STARTF_USESTDHANDLES | STARTF_USESHOWWINDOW;
        si.hStdOutput = hStdOutInside;
        si.hStdError = GetStdHandle(STD_ERROR_HANDLE);
        si.hStdInput = hStdInInside;
        si.wShowWindow = SW_HIDE;
    
        std::wstring ws;
        ws.reserve(n);
        ws += L'"';
        ws += aFname;
        ws += L"\" ";
        ws += aCmdLine;
    
        fIsOpen = CreateProcess(
                nullptr,        // lpApplicationName
                &*ws.begin(),   // lpCommandLine
                nullptr,        // lpProcessAttributes
                nullptr,        // lpThreadAttributes
                TRUE,           // bInheritHandles
                0,              // dwCreationFlags
                nullptr,        // lpEnvironment
                nullptr,        // lpCurrentDirectory
                &si,            // lpStartupInfo
                &pi );          // lpProcessInformation
    
        if (fIsOpen && !aLog.empty())
            fLog.open(aLog.c_str(), st::File::omNew);
    
        return fIsOpen;
    }
    
    
    void ConStream::flush()
    {
    
    }
    
    
    size_t ConStream::readNe (void* aBuf, size_t aSize)
    {
        if (!fIsOpen)
            return 0;
    
        DWORD nRead;
        if (!ReadFile(hStdOutOutside, aBuf, static_cast<DWORD>(aSize), &nRead, nullptr))
            return 0;
    
        if (fLog.isOpen())
            fLog.write(aBuf, nRead);
    
        return nRead;
    }
    
    
    // Implemented write
    size_t ConStream::writeNe(const void* aBuf, size_t aSize)
    {
        if (!fIsOpen)
            return 0;
    
        DWORD nWritten;
        if (!WriteFile(hStdInOutside, aBuf, static_cast<DWORD>(aSize), &nWritten, nullptr))
            return 0;
        return nWritten;
    }
    
    
    bool ConStream::readln(std::string& s)
    {
        if (!fIsOpen)
            return false;
    
        s.clear();
        enum { SZ = 256, TIME = 30 };
        char buf[SZ + 2];
        DWORD nRead, nm1, nm2;
    
        while (true) {
            if (!PeekNamedPipe(hStdOutOutside, buf, SZ, &nRead, &nm1, &nm2))
                throwWinError();
            // Read nothing — maybe, the program has finished?
            if (nRead == 0) {
                if (WaitForSingleObject(pi.hProcess, TIME) == WAIT_OBJECT_0) {
                    // Try again
                    if (!PeekNamedPipe(hStdOutOutside, buf, SZ, &nRead, &nm1, &nm2))
                        throwWinError();
                    if (nRead == 0)
                        return !s.empty();
                    // otherwise fall out
                }
            }
            const char* start = buf;
            const char* end = buf + nRead;
            if (fFoundCr && *start == '\n') {
                ++start;
                fFoundCr = false;
            }
            for (const char* p = start; p != end; ++p) {
                switch (*p) {
                case '\r':
                    fFoundCr = true;
                    // fall through
                case '\n':
                    s.append(start, p);
                    // Read until CR
                    ++p;
                    skipRead(p - buf);
                    return true;
                default: ;
                }
            }
            // Copy the entire buffer and go on
            s.append(start, end);
            skipRead(end - buf);
        }
    }
    Ответ написан
  • Почему CharToOemW преобразует не все символы?

    @Mercury13
    Программист на «си с крестами» и не только
    А такое будет работать?

    inline const char* wtc(const WCHAR *from)
    {
      //Используется буффер -- статическая переменная
      static char buf[1024] = { 0 };
      size_t nChars = std::min<size_t>(wcslen(from), 1024 - 1);
      if (!CharToOemBuffW(from, buf, nChars)) {
        cout << GetLastError();
        exit(-1);
      }
      buf[nChars] = 0;
      return buf;
    }
    Ответ написан
  • Как отправить POST запрос с помощью C#?

    @Mercury13
    Программист на «си с крестами» и не только
    На самого себя.

    Если, например, страница example.com/test.php, то эта страница и будет action.
    Ответ написан
  • Сколько бит(байт) занимают типы данных с плавающей запятой в C++?

    @Mercury13
    Программист на «си с крестами» и не только
    Например, int занимает 4 байта

    По современному консенсусу, да. Но иногда может занимать 2 байта (меньше — вроде нет).

    В случае с double можно задать абсолютно любое число

    double x = 1e500;
    Ответ статического анализатора Clang: magnitude of floating-point constant is too large for type 'double'; maximum is 1.79…E+308

    На число 1.23456789012345678901234 не жалуется, но учите матчасть — относительная точность double 52 двоичных цифры (исключая головную единицу), или около 16 десятичных.

    для чего в конце приписывают 'f' ,когда пользуются типом данных float?

    Чтобы расчёт float x; return x + 12.34f вёлся в менее точном типе float, а не double.
    А вот коду float x = 12.34; это совершенно не нужно, компилятор и сам поймёт, что преобразование double → float можно сделать при компиляции.

    Сколько бит(байт) занимают типы данных с плавающей запятой в C++?

    Зависит от машины, но по выработанному консенсусу — float 4, double 8.
    Нестандартная (присущая x86) реализация long double имеет 10 значащих байтов, но 12 или 16 вместе с выравниванием.
    Ответ написан
    Комментировать
  • Что означают данные строки?

    @Mercury13
    Программист на «си с крестами» и не только
    Перед нами вариативный шаблон Си++11.

    Функция printTypes действует так. Для первого параметра подбираем подходящую перегрузку функции NameOf. Второй и далее — снова подставляем в функцию printTypes.

    types... t — это любое количество параметров любых типов. Которые, в свою очередь, можно рекурсивно подставить в шаблон printTypes.

    DEF_TYPENAME(float) — это использование препроцессора Си++ (никакой уже не 11), чтобы объявить несколько стандартных специализаций одного шаблона.
    Ответ написан
  • Как правильно называть переменные в заголовке функции (параметры или аргументы)?

    @Mercury13
    Программист на «си с крестами» и не только
    Одна сатана. В терминологии одних языков принято parameter, других argument.
    Ответ написан
    Комментировать
  • Посимвольный i/o vs i/o в строку (буфер)?

    @Mercury13
    Программист на «си с крестами» и не только
    Очень-очень верно! Даже на чём-то типа istringstream виртуальный вызов занимает довольно много времени, и ОЧЕНЬ желательна буферизация своими силами.
    Подтверждаю, приходилось писать код скоростного разбора XML.
    Ответ написан
    Комментировать
  • Почему нельзя передавать лямбду как аргумент шаблона?

    @Mercury13
    Программист на «си с крестами» и не только
    #include <iostream>
    
    template <class Body>
    void call(const Body& body) {
        body();
    };
    
    void test() {
      std::cout << "function" << std::endl;
    }
    
    int main() {
      call(test);
      call([]() {
        std::cout << "lambda" << std::endl;
      });
      return 0;
    }


    Дело в том, что лямбда — это объект неизвестного класса с операцией (). И только так её вызывают.
    Ответ написан
    1 комментарий
  • Правилен ли такой подход к разбиению C приложения на модули?

    @Mercury13
    Программист на «си с крестами» и не только
    Смотря в чём задача.
    Возможно, нет никаких проблем.
    Возможно, удастся вытащить общую функциональность в defines.h.
    Возможно, удастся каким-то образом разорвать порочный круг. Например, в ООП это можно делать через интерфейс.
    Ответ написан
    Комментировать
  • Как отловить момент, когда в QComboBox создаётся редактор?

    @Mercury13 Автор вопроса
    Программист на «си с крестами» и не только
    Опять приходится отвечать своими силами.
    void TimedWideComboBox::connectToEditor()
    {
        if (!lineEdit())
            return;
        connect(lineEdit(), &QLineEdit::textEdited, this, &This::origDataChanged);
    }
    
    bool TimedWideComboBox::event(QEvent* ev)
    {
        bool b = Super::event(ev);
        switch (ev->type()) {
        case QEvent::ChildAdded: {
                auto ev1 = static_cast<QChildEvent*>(ev);
                if (ev1->child() == lineEdit()) {
                    connectToEditor();
                    return true;
                }
            } break;
        default:;
        }
        return b;
    }
    Ответ написан
  • Как сделать так, чтобы CodeBlocks не ставил знаки?

    @Mercury13
    Программист на «си с крестами» и не только
    Settings → Editor → General Settings (стоит по умолчанию) → Editor Settings (стоит по умолчанию) → Indent Options → Brace completion

    5cfa263e49d5b731760499.png
    Ответ написан
    Комментировать