• Что такое асинхронное копирование файлов?

    @Mercury13
    Программист на «си с крестами» и не только
    В WinAPI асинхронное копирование файлов — это использование так называемого «асинхронного ввода-вывода» (Overlapped I/O), механизма, который не поднимает новых потоков (по крайней мере явно), но позволяет параллельно с вводом-выводом делать что-то другое. В данном случае — читать и записывать одновременно.

    Что это даёт?
    1. Уменьшает простои программы и этим ускоряет копирование.
    2. Если копирование в пределах одного механического AHCI-диска (из каталога в каталог, с раздела на раздел)— это позволяет оптимизировать маршруты головки на уровне драйвера или контроллера.
    3. Если копирование между разными накопителями — накопители будут действовать параллельно.
    Ответ написан
    Комментировать
  • Как затереть ссылку возврата?

    @Mercury13
    Программист на «си с крестами» и не только
    Для чего это нужно? А для того, чтобы вы знали, как хакеры вас ломают. Простейший способ для этого — устроить переполнение буфера.
    void foo()
    {
      void* a[1];
      a[1] = (void*)&bar;
    }

    Может быть, придётся подменить не a[1], а a[2] или a[3].
    Если так поступить, bar-то будет вызван, но по выходу из него, скорее всего, программа упадёт. Как сделать, чтобы не упала — оставлю домашним заданием. Высший пилотаж — завести в main() пару переменных, а потом через std::cout показать: вот они, целые и невредимые (компилируйте без оптимизации, макс. оптимизация может их просто заменить константами). Но тут уже придётся знать соглашение вызова и читать дизассемблерный листинг: от этого зависит, как вернуть стек в подходящее состояние.

    UPD. Простите за моё незнание синтаксиса Си.
    Ответ написан
    5 комментариев
  • Как представляется отрицательное число в дополнительном коде?

    @Mercury13
    Программист на «си с крестами» и не только
    Во-первых, вы ошиблись. В беззнаковом типе 1111.1111 = 255 (а не 256!), в знаковом типе 1111.1111 = −1 (а не −127).
    1000.0000 — соответственно −128 и 128.
    256 не передашь одним байтом — ни в знаковом типе, ни в беззнаковом.

    Ну и ответ на ваш главный вопрос.
    > Как ЭВМ понимает, какое число положительное, а какое отрицательное?
    Если заведомо известно, что в ячейке знаковое число — как сказано выше, по верхнему биту (1 — минус, 0 — ноль или плюс). А различить знаковое и беззнаковое число — работа, вообще-то, не машины, а программиста и компилятора, и если просто дана ячейка неизвестного типа — никак не узнаешь, signed там, unsigned, дробное, указатель или символ.
    • Сложение и вычитание работает одинаково для знаковых и беззнаковых чисел.
    • Проверка переполнений и сравнение. Используются три флага: флаг равенства (zf, zero), флаг знакового переполнения (of, overflow) и флаг беззнакового переполнения (cf, carry). Каждая из арифметических функций заполняет и знаковые, и беззнаковые флаги, и есть отдельные функции ветвления для беззнаковых чисел (above/below — например, ja, jbe = jna…) и для знаковых (greater/less — jg, jle = jng). Jump if above, jump if below or equal, и т.д.
    • Умножение и деление — также разные функции, беззнаковая mul/div и знаковая imul/idiv.

    Кстати, по этой причине компилятор ругается, если нужно сравнивать signed и unsigned. Единственный способ надёжно сделать это, например, для 4-байтовых чисел — расширить до 8-байтового signed, чтобы уместился и тот, и другой.
    Ответ написан
    3 комментария
  • Qt: кто владеет createStandardContextMenu() и как его уничтожать?

    @Mercury13 Автор вопроса
    Программист на «си с крестами» и не только
    Исходники Qt говорят: владелец — редактор.
    02405 #endif
    02406     d->actions[QLineEditPrivate::ClearAct]->setEnabled(!d->readOnly && !d->text.isEmpty() && d->hasSelectedText());
    02407     d->actions[QLineEditPrivate::SelectAllAct]->setEnabled(!d->text.isEmpty() && !d->allSelected());
    02408 
    02409     QMenu *popup = new QMenu(this);
    02410     popup->setObjectName(QLatin1String("qt_edit_menu"));
    02411     popup->addAction(d->actions[QLineEditPrivate::UndoAct]);
    02412     popup->addAction(d->actions[QLineEditPrivate::RedoAct]);
    02413     popup->addSeparator();

    Ну разумеется. Хотя причиной оказался механизм signal-slot — во время обработки сигнала исчез его инициатор! Объясню вкратце, что пришлось сделать.
    1. От греха подальше действие создавал каждый раз новое, владелец — меню.
    2. Как только вызывается действие, владение меню переносится в другое место.
    3. После exec() меню уничтожается без всяких условий.
    Ответ написан
    Комментировать
  • Как подключить libcurl к Qt?

    @Mercury13
    Программист на «си с крестами» и не только
    Подключать надо libcurldll.a в таком виде.
    -LC:\Qt\curl-7.49.0-win32-mingw\lib -lcurldll

    Вот кусок, взятый из реального проекта.
    win32|win64: LIBS += -lws2_32 -lshlwapi -lodbc32 -lpsapi -lcomdlg32 \
                         -L$$PWD/../../Common/cURL/lib/ -lcurldll -lole32 \
                         -loleaut32


    Кроме того, тебе не хватает OpenSSL — найди libeay32.dll и ssleay32.dll, лучше скомпилированные старой версией MSVC и не требующие новых runtime’ов, которые есть не везде. Ах да, есть версии libcurl, которые скомпилированы без SSL — им этого, разумеется, не нужно.

    Подожди, сейчас посмотрю, что будет, если вкомпилировать в программу библиотеку cURL статически, без DLL.

    UPD. Попробовал. Почти работает, но надо разобраться, как подключить winsock и OpenSSL — раньше-то ими занимался тот, кто компилирует DLL, а сейчас это будет моя забота.
    Ответ написан
  • Как поместить "нетривиальный" объект в стуктуру?

    @Mercury13
    Программист на «си с крестами» и не только
    Одно из полей (в данном случае data в реализации item<Edge>) не имеет конструктора по умолчанию. Есть три пути.

    РАЗ. Придумать, как сделать, чтобы конструктор всё-таки был.
    class Edge : public EdgeBase
    {
    public:
      Edge (Point* firstPoint, Point* secondPoint) { init(firstPoint, secondPoint); }
      Edge () { init(NULL, NULL); }
      void init (Point* firstPoint, Point* secondPoint)
      {
        this->firstPoint = firstPoint;
        this->secondPoint = secondPoint;
      }
    private:
      Point* firstPoint;
      Point* secondPoint;
    };


    ДВА. Если объект копируется/переносится, можно воспользоваться такой штукой. С вашего позволения, упрощу задачу и вместо Edge заведу другой класс — ImmutableInt. Правда, этот код — попытка совместить ежа с ужом (непонятно, какую концепцию должен поддерживать Payload), но, тем не менее, работает.
    #include <iostream>
    
    class ImmutableInt
    {
    public:
        explicit ImmutableInt(int x) : fData(x) {}
        int data() const { return fData; }
    private:
        int fData;
    };
    
    template <class Payload>
    class ListItem
    {
    public:
        Payload payload;
        ListItem* next;
    
        ListItem() : next(NULL) {}
        ListItem(const Payload& x) : payload(x), next(NULL) {}
    };
    
    // Так писать нельзя — эта конструкция расшаблонивает все функции,
    // а конструктора по умолчанию как не было, так и нет!
    //template class ListItem<ImmutableInt>;
    
    int main()
    {
        ListItem<ImmutableInt> li(ImmutableInt(42));
        std::cout << li.payload.data() << std::endl;
        return 0;
    }


    ТРИ. Воспользоваться переменными шаблонами (variadic templates) C++11.
    #include <iostream>
    
    class ImmutableInt
    {
    public:
        explicit ImmutableInt(int x) : fData(x) {}
        int data() const { return fData; }
    private:
        int fData;
    };
    
    template <class Payload>
    class ListItem
    {
    public:
        Payload payload;
        ListItem* next = nullptr;
    
        template<class... Args>ListItem(Args... args) : payload(args...) {}
    };
    
    int main()
    {
        ListItem<ImmutableInt> li(42);
        std::cout << li.payload.data() << std::endl;
        return 0;
    }


    P.S. Хотя ImmutableInt — семантически тот же int и теоретически explicit не надо, всё-таки отметил — просто чтобы показать, что во втором случае мы передаём параметром ImmutableInt<42>, а в третьем — 42.

    P.P.S. Я упомянул слово «концепция». Это набор требований к типу. Что-то типа интерфейса — но, во-первых, никак не связано с ООП и его динамическим полиморфизмом, и, во-вторых, не столь жёсткое: как ты интерфейсом из Java наладишь концепцию «есть конструктор копирования» или «может делить себя на число и что-то выходит»? Синтаксическая поддержка концепций откладывается на C++17, но уже в C++03 было несколько концепций: InputIterator, DefaultConstructible, CopyAssignable и другие. А пока… концепция не поддерживается — ошибка компиляции где-то в страшенном стандартном хедере.

    P.P.P.S. Написав код
    template<typename type_t>
    struct item
    {
      item* next;
      type_t data;
    };

    вы автоматически потребовали от type_t концепцию DefaultConstructible (есть конструктор по умолчанию)
    Ответ написан
    1 комментарий
  • Как создать эффект камеры?

    @Mercury13
    Программист на «си с крестами» и не только
    У меня по этому поводу целый перевод есть.
    Первая часть: https://habrahabr.ru/post/272933/
    Вторая часть: https://habrahabr.ru/post/273397/

    Именно по поводу того, как камерой вести персонажа.
    Ответ написан
    1 комментарий
  • Как программно скачать несколько файлов с сайта?

    @Mercury13
    Программист на «си с крестами» и не только
    1. Заполучить принцип, по которому строятся ссылки. Возможно, для этого придётся разбирать код самого сайта.
    2. Использовать любую библиотеку HTTP: Indy (Delphi), cURL (DLL с большим количеством привязок) или что-нибудь другое. С другими я, к сожалению, не работал. Ну или просто запускать подходящий EXE-загрузчик (wget, curl…).
    3. Обойти анти-DDoS’овские меры. Многие сети раздачи контента проверяют, похож ли клиент на легитимный браузер — наш бот должен все эти меры обойти.

    Знаю, что слабость последних версий Indy — ориентация на .NET и вытекающие оттуда ограничения; также Indy «слишком вумный» и сложные REST-службы не работают, так как строишь тело, вычисляешь имитовставку — а служба говорит, что они друг другу не соответствуют; видимо, Indy что-то подстроил. Кстати, когда я понял, что запросы без тела работают, а с телом — ни в какую, первым тестом стал curl.exe, и только потом подключил libcurl через собственную Delphi-привязку.

    Слабость cURL — тонкости протоколов (скажем, заголовки и кодировки) остаются за прикладными программистом; ориентирован на FILE* и на всех языках, кроме Си, запись в файл слегка затруднена; ориентирован на vararg и если работать без типобезопасной обёртки, надо быть предельно осторожным.
    Ответ написан
    Комментировать
  • Delphi 7, как сделать обработчик события нажатия клавиш CtRL+V?

    @Mercury13
    Программист на «си с крестами» и не только
    Вариант первый — отреагировать в событии OnKeyDown.
    Вариант второй — создать TActionList, в нём установить действие на Ctrl+V.

    Что лучше — зависит от того, что нужно. По всей форме должна действовать клавиша Ctrl+V или нет?

    Да, и не забудь про команду-заменитель, Shift+Ins. Должна действовать точно так же.
    Ctrl+X = Shift+Del
    Ctrl+C = Ctrl+Ins
    Ответ написан
    Комментировать
  • Как решить данную задачу за O(log(n)*n)?

    @Mercury13
    Программист на «си с крестами» и не только
    Создадим массив на 2N событий. Событие — эти тип («начало»/«конец»), № круга и координата. Каждый круг создаёт два события: начало на i−R и конец на i+R.
    Массив сортируем по X, с таким уточнением, если X равны.
    • Если касание считать пересечением, начало < конец (т.е. для точки X идут начала, затем концы). В такой ситуации нам не важны номера кругов.
    • Если нет — сначала номера кругов (aka x-координаты центров) по возрастанию, затем начало < конец.
    Заводим счётчик кругов. Проходимся по массиву.
    • Если видим начало — к результату +счётчик, к счётчику +1.
    • Если видим конец — к счётчику −1.

    В нашем примере:
    Счётчик 0, результат 0
    Начало №1 на x=−4: результат 0, счётчик 1
    Начало №0 на x=−1: результат 1, счётчик 2
    Начало №2 на x=0: результат 3, счётчик 3
    Начало №4 на x=0: результат 6, счётчик 4
    Конец №0 на x=1: счётчик 3
    Начало №3 на x=2: результат 9, счётчик 4
    Затем аж два конца на x=4, счётчик опустился до 2
    Начало №5 на x=5: результат 11, счётчик 3
    Конец №5 на x=5: счётчик 2
    И ещё два конца сбрасывают счётчик до 0.

    UPD. Уточнил для случая, если касание — не пересечение.
    Ответ написан
    Комментировать
  • Будет ли нарушение авторских прав в приложении?

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

    Что будет — это зависит от жадности правоторговцев. По огромной куче знаменитых фильмов — гарантированно ничего. По одному конкретному — как правило, ничего; загугли «movie quiz» и увидишь кучу всякого добра.
    Ответ написан
  • Как на Delphi сделать эмуляцию ввода русских букв?

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

    В Win2K+ у этой команды есть режим, имитирующий ввод текста неклавиатурными методами — скажем, голосом или рукописным вводом (KEYEVENTF_UNICODE). Вам нужен этот режим.
    Ответ написан
    Комментировать
  • Как изменять значения переменных другого класса в C++?

    @Mercury13
    Программист на «си с крестами» и не только
    Не буду говорить о качестве кода, const-корректности и прочей бяке. Конкретная ваша ошибка
    int& operator [](int i) // именно ссылка!

    У вас возвращается значение — временный объект, которому, разумеется, невозможно присвоить что бы то ни было.
    Ответ написан
  • Как добавить/вычесть необходимое количество периодов и ряд для арктангенска больше 1?

    @Mercury13
    Программист на «си с крестами» и не только
    Если x > 0, то 90° − arctg 1/x.
    Если <0, думай сам, школьная математика.

    Для синуса — делишь на 2pi, берёшь целое-«пол», отнимаешь 2pi·n, и в зависимости от того, в каком диапазоне то, что осталось, работаешь.
    Ответ написан
    Комментировать
  • Как удалить элемент из вектора, а затем добавить несколько новых?

    @Mercury13
    Программист на «си с крестами» и не только
    У вас могут быть две проблемы.
    1. Неверно написана операция «присвоить» или «переместить».
    2. Забыл, что в std::vector при операции «добавить» или «удалить» возможно физическое перемещение объекта и ссылки на него больше недействительны.

    Ну и IsEnded лучше писать вот так.
    bool IsEnded(const Query &aVar) { return (aVar.id == NO_ID); }
    Ответ написан
    2 комментария
  • Что будет содержать абстрактный класс?

    @Mercury13
    Программист на «си с крестами» и не только
    Вариант один вы предложили. Всё пишу на C++03, без шаблонов. C++11 и шаблоны, разумеется, дадут больше вариантов.
    class Object {
    public:
        virtual ~Object() {}
    };
    
    class List {    // interface
    protected:
        virtual Object& getAt(size_t i) = 0;
    public:
        virtual size_t size() const = 0;
        inline Object& at(size_t i) { return getAt(i); }
        inline const Object& at(size_t i) const
            { return const_cast<List*>(this)->getAt(i); }
        virtual ~List() {}
    };

    Вариант 2. С ним пользователю не так просто, но если к нему ещё добавить лямбда-функции C++11 — вообще бомба будет!
    class ListCallback {    // interface
    public:
        virtual void act(size_t index, Object& object) = 0;
        virtual ~ListCallback() {}
    };
    
    class ListConstCallback {   // interface
    public:
        virtual void act(size_t index, const Object& object) = 0;
        virtual ~ListConstCallback() {}
    };
    
    class List2 {   // interface
    public:
        virtual size_t size() const = 0;
        virtual void enumerate(ListCallback& body) = 0;
        virtual void enumerate(ListConstCallback& body) const = 0;
    };

    Например, для динамического массива, у которого быстрый доступ по номеру, будет такое тело
    void DynArray::enumerate(ListConstCallback& body) const {
       size_t sz = size();
       for (size_t i = 0; i < sz; ++i)
           body(i, operator[](i));
    }

    Разумеется, если вы нагрузкой сделаете не абстрактный Object, а что-то окончательное, dynamic_cast не нужен будет.

    Вариант 3 принят в Java. Один недостаток — мого кода писать для const-корректности, так что с вашего позволения опущу.
    class VirtualListIterator { // interface
    public:
        virtual bool next() = 0;
        virtual Object& value() = 0;
        virtual ~VirtualListIterator() {}
    };
    
    class ListIterator {   // Назван так для красоты, по сути это умный указатель
    private:
        VirtualListIterator* ptr;
        // Запретим копирование и op=, но при желании можно реализовать и их
        ListIterator(ListIterator&) {}
        void operator=(const ListIterator&) {}
    public:
        ListIterator() : ptr(NULL) {}
        ListIterator(VirtualListIterator* value) : ptr(value) {}
        ~ListIterator() { delete ptr; }
        bool next() { return ptr->next(); }
        Object* operator->() const { return &ptr->value(); }
        Object& operator*() const { return ptr->value(); }
    };
    
    class List3 {   // interface
    public:
        virtual size_t size() const = 0;
        virtual VirtualListIterator* enumerate() = 0;
    };
    
    class Number : public Object {
    public:
        int value;
    };
    
    // И пользоваться этим так...
    void doSmth(List3& aList) {
        ListIterator it(aList.enumerate());
        while (it.next()) {
            std::cout << dynamic_cast<Number&>(*it).value << std::endl;
        }
    }


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

    Да, и из вас будет хороший инженер, если вы сразу же задумываетесь о производительности.
    Ответ написан
    Комментировать
  • Как создать динамический массив из объектов класса?

    @Mercury13
    Программист на «си с крестами» и не только
    Операция присваивания или перемещения есть? Пускай даже созданная автоматически? Если есть — вот, смотрите.
    #include <iostream>
    #include <vector>
    
    class Test {
      int k;
    public:
      Test(int _i) {k = _i; }
    
      void put_k(int i) {k = i; }
      int get_k() {return k; }
    };
    
    
    struct TestWrapper {
        Test payload;
        TestWrapper() : payload(0) {}
        TestWrapper(int i) : payload(i) {}
        TestWrapper(const Test& i) : payload(i) {}
    };
    
    int main()
    {
        Test test(10);
        std::vector<TestWrapper> v;
        v.push_back(test);
        std::cout << v[0].payload.get_k() << std::endl;
        return 0;
    }


    Если нет — тогда динамический массив так просто работать не может (фишка динамического массива — заводить новый массив и копировать информацию из старого). Только использованием умных указателей.
    #include <iostream>
    #include <vector>
    #include <memory>
    
    
    class Test {
      int k;
    public:
      Test(int _i) {k = _i; }
      Test& operator=(const Test&) = delete;
      Test& operator=(Test&&) = delete;
    
      void put_k(int i) {k = i; }
      int get_k() {return k; }
    };
    
    
    int main()
    {
        std::vector<std::unique_ptr<Test>> v;
        v.push_back(std::unique_ptr<Test>(new Test(10)));
        std::cout << v[0]->get_k() << std::endl;
        return 0;
    }
    Ответ написан
  • Косое произведение в координатах для R=3?

    @Mercury13
    Программист на «си с крестами» и не только
    В 2D есть два произведения: скалярное (проекция) и косое (ориентированная площадь).
    В 3D есть три произведения: скалярное (проекция), векторное (ориентированная площадь) и смешанное (ориентированный объём).
    Думаю, в 4D уже четыре штуки.

    По поводу формулы. Почему не будет работать? Будет, однако вы неправильно написали, чему равняется [e1e2]. Оно в 3D равняется не единичке, а e3.
    Ответ написан
  • Как реализовать изменение размера файла на Си?

    @Mercury13
    Программист на «си с крестами» и не только
    Чтобы увеличить файл, надо дописать в конец.
    Libc — fopen(..., "wa");
    WinApi — CreateFile с нужными правами, затем SetFilePointer в конец и дописывай на здоровье.

    Чтобы уменьшить файл
    В Libc этого нет, есть функции POSIX truncate/ftruncate, в Win32 — _chsize.
    WinApi — SetEndOfFile.
    Ответ написан
    Комментировать
  • Что такое Stylus Bearing?

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