Задать вопрос
  • И снова clang: Почему (при оптимизации) реализация на указателях получилась хуже чем с использованием оператора [ ]?

    @Mercury13
    Программист на «си с крестами» и не только
    Интересно тут другое. Компилятор первую версию превращает во вторую — базово-индексная адресация очень быстра, а дважды прибавлять единицу — не лучший вариант. К тому же он обнаруживает параллельные циклы и устраивает им одинаковый индекс.

    Кстати, посмотри интереса ради gcc -Os.
    Ответ написан
    6 комментариев
  • Какая графика используется в игровых движках?(вектор или растр.)И как вообще устроен графический редактор в них?

    @Mercury13
    Программист на «си с крестами» и не только
    Трёхмерная графика не бывает векторной и растровой. У неё там свои разновидности, и там она используется полигональная. Текстуры, разумеется, растровые. Существуют псевдовекторные элементы вроде поля расстояний, но это именно что «псевдо-».

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

    @Mercury13
    Программист на «си с крестами» и не только
    Вы тут просто не знаете, что такое указатель. А это, грубо говоря, адрес другого объекта в памяти.
    Операция new заводит объект в «куче», вызывает конструктор (если таковой есть) и возвращает указатель на него.
    И мы можем разыменовать указатель: пройти на тот объект, куда он указывает, и сделать с ним что-то. В Си разыменование — операция ->.

    Указатели не на абстрактный класс, а на вполне конкретный, a.

    a(int) — не конструктор копирования, а просто конструктор, делающий объект из int’а. Конструктор копирования всегда a(const a&). Отличается от других конструкторов тем, что автоматика его по возможности строит, но не всегда верно. В вашем объекте с одним полем int вполне себе построит без всяких проблем.

    Обычный указатель Си никоим образом не знает, есть объект или нет, и кто этот объект уничтожает. У вас это приводит к ошибке «утечка памяти»: теряется указатель на объект, и уже никак его не освободишь. Из-за небольшого размера и линейного характера программы неопасно, но всё-таки.
    Ответ написан
    Комментировать
  • Почему МНК только при нормальном шуме?

    @Mercury13
    Программист на «си с крестами» и не только
    Не совсем так. Главное требование — симметричный шум, иначе оценка будет смещённой.
    Но в случае нормального шума МНК превращается в метод максимального правдоподобия. Просто посмотрите на формулу шума, а потом прологарифмируйте.
    Ответ написан
    Комментировать
  • Почему 150/1000 == 0?

    @Mercury13
    Программист на «си с крестами» и не только
    Потому что деление происходит int/int, то есть целочисленное.
    Надо 150.0/1000.

    Это известный глюк Си-подобных языков — a/b в зависимости от типа или деление, или неполное частное. В Паскале, например, неполное частное — a div b. В Си-подобных языках с динамической типизацией (JS) отказались от неполного частного, ибо мы тип плохо контролируем.
    Ответ написан
    8 комментариев
  • Как работает метод кодирования 4B3T?

    @Mercury13
    Программист на «си с крестами» и не только
    Начинаем с какой-нибудь суммы, например, 2.
    биты 0000, сумма 2 — по таблице 0−0, от суммы отнимаем 1, получается 1.
    Приходят снова биты 0000, сумма 1 — по таблице уже +0+, к сумме прибавляем 2, получается 3.
    Вот так мы балансируем средний ток через канал связи на уровне нуля.
    Ответ написан
    4 комментария
  • Как составить список пути используя алгоритм BFS?

    @Mercury13
    Программист на «си с крестами» и не только
    Вместо
    boolean[][] visited = new boolean[ROW][COL];

    надо сделать такое:
    static final byte DIR_UNKNOWN = 0;
    static final byte DIR_UP = 1;
    ...
    
    byte[][] bestDirection = new boolean[ROW][COL];  // изначально заполнено DIR_UNKNOWN


    for (int dir = DIR_UP; dir <= DIR_RIGHT; ++dir) {
      ...
      bestDirection[row][col] = dir;
    }

    Добравшись до финиша, делаем обратный ход. А именно: определяем, какой bestDirection у финиша, и если он, например, DIR_UP — смещаемся на 1 вниз. И так далее, пока не доберёмся до старта.

    Если финишей много — возможно, лучше будет начинать с них, внеся их в очередь в случайном порядке. А потом, когда поиск доберётся до старта, сделать обратный ход.
    Ответ написан
    Комментировать
  • Какие процессы происходят при обновлении страницы?

    @Mercury13
    Программист на «си с крестами» и не только
    Blink (именно он) странно ведёт себя, если margin/padding span’а задан в процентах. Видимо, там есть какой-то внутренний кэш шрифтов, и он для определения нужного размера span’а берёт устаревшие цифры.
    Попробуйте помасштабировать страницу, и увидите, как пляшут надписи.
    Вообще никто не говорит, как должен действовать margin в % для span’а. Но метод центровки откровенно странный и представляет собой ручную подгонку под желаемое (причём очень грубую). Я бы сделал достаточно большой блок и в нём бы отцентрировал иконку и надпись. Если какой-то рендерер не уместит надпись в одну строку — ну пускай…

    UPD. Уточняю: Blink так ведёт себя, когда в блоке есть замкнутый круг: из-за float’а его ширина зависит от вёрстки текста в нём; из-за процентных отступов вёрстка текста зависит от размера блока.
    Ответ написан
    4 комментария
  • Как правильно передавать функцию как параметр C++?

    @Mercury13
    Программист на «си с крестами» и не только
    Не забывайте, что у startManufacturing есть скрытый параметр this.

    Четыре варианта.

    1. Использовать указатель на метод App:
    Rest::function(char * function_name, int (App::* f)(String), App& object)
          // вместо App можно какой-то интерфейс, который App реализует
    …
    object.*f("string");
    ...
    bt_rest.function("", &App::startManufacturing, *this);


    2. Сделать startManufacturing static:
    class App {
      static int startManufacturing(String command)
    };


    3. Сделать обёртку с замыканием:
    Rest::function(char * function_name, int (*f)(String, void*), void*);
    
    void doStartManufacturing(String command, void* closure) {
      reinterpret_cast<App*>(closure)->startManufacturing(command);
    }
    ...
    bt_rest.function("startManufacturing", doStartManufacturing, this);


    4. «Избегай незнакомых женщин и глобальных переменных». Костыль, в общем.
    App app;
    int doStartManufacturing(String command) { return app.startManufacturing(command); }
    ...
    bt_rest.function("startManufacturing", doStartManufacturing);


    Ах да. Вы передаёте String’и по значению. Приспособлены они к такой передаче или всё же лучше по ссылке?
    Ответ написан
    6 комментариев
  • Как нарисовать линию с помощью алгоритма Брезенхема и гамма-коррекции в текстовом файле?

    @Mercury13
    Программист на «си с крестами» и не только
    Я бы работал по такой формуле:

    result = ((original / max)1 / gamma) · 255

    Original — это полученное алгоритмом Ву значение (float или хотя бы short!)
    max — максимально возможное значение original. Для short, например, это 65535.
    gamma — традиционно 2,2.
    Ответ написан
    Комментировать
  • Как работает scanf в плюсах?

    @Mercury13
    Программист на «си с крестами» и не только
    1. Для ввода строки использовать std::getline.
    2. Ну, в Си++ есть хорошо инкапсулированные строки, а в Си нет. Потому в Си очень сложно получить из потока строку неизвестной длины.
    Ответ написан
  • Почему не работает new c++?

    @Mercury13
    Программист на «си с крестами» и не только
    Есть такое понятие, как «принцип подстановки Барбары Лисков». Если подставить на место User класс Comparator, должно сойтись по типам. Но нет: User умеет сравнивать только с самим собой, а Comparator — с любым Comparator.

    Теоретически должно было бы подойти такое (так называемая контравариантность). Но не работает ни в Си++, ни в Яве.
    class ComparatorBase
    {
    public:
        virtual ~ComparatorBase() = default;
    };
    
    class Comparator : public ComparatorBase {
        public:
            virtual int compare(Comparator  *t)=0;
    };
    
    class User : public Comparator{
    public:
        int compare(ComparatorBase *u) override {
            return 1;
        }
    };

    А по возвращаемому значению (если возвращается ссылка/указатель) может быть ковариантность, и она работает и в Си++, и в Яве.
    class Father
    {
    public:
        virtual Father& foo();
        virtual ~Father() = default;
    };
    
    class Son : public Father
    {
    public:
        Son& foo() override;
    };


    Как обойти. Есть два способа.
    Способ 1. Пусть старой Явы.
    int User::compare(Comparator *u)
    {
        auto* v = dynamic_cast<User*>(u);
        if (!v)
            return false;
        return v->name > this->name;
    }


    Способ 2. Так называемый «странно рекуррентный шаблон».
    template <class T>
    class Comparator {
    public:
        virtual int compare(T *t)=0;
        virtual ~Comparator() = default;
    };
    
    class User : public Comparator<User> {
    private:
        std::string name;
    public:
        User(std::string name){this->name=name;}
        int compare(User *u);
        void showName(){std::cout<<"Name "<<this->name<<std::endl;}
    
    };
    
    int User::compare(User *u)
    {
        return u->name > this->name;
    }
    Ответ написан
    Комментировать
  • Какие есть способы перевода с одного типа данных в другой?

    @Mercury13
    Программист на «си с крестами» и не только
    1. С использованием функций преобразования типа, встроенных в Си++ или написанных пользователем. Это может делаться неявно, через C-style cast, через вызов конструктора, через операцию static_cast.
    2. С преобразованием указателя вниз по иерархии наследования, и особым поведением, если это не получилось, через операцию dynamic_cast и функцию dynamic_pointer_cast.
    3. С рассмотрением участка памяти как переменной несовместимого типа. Через union, const_cast, reinterpret_cast, C-style cast указателей.
    Ответ написан
    Комментировать
  • Что значит оформить страницу лицензии в ПДФ?

    @Mercury13
    Программист на «си с крестами» и не только
    Это значит: в какой программе вы бы ни писали лицензию, но на выходе должен получиться PDF.
    Этот PDF может быть создан виртуальным принтером, встроенным или внешним конвертером в PDF.
    Ответ написан
    Комментировать
  • Как не переноситься на следующую строку после scanf?

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

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

    @Mercury13
    Программист на «си с крестами» и не только
    center_pt = *new Point(x/size, y/size);
    Утечка памяти. Никто в «си с крестами» за вас не будет подчищать все эти new.
    Правильно:
    center_pt = Point(x/size, y/size);
    (Ну и, разумеется, я не понимаю, что значат эти x/size и y/size, но шут с ним.)

    Примерно таким образом и происходит переприсваивание объектов, если им оставили таки операцию =. То есть…
    class Geolocator {
    public:
      Point coords;
      bool isReliable;
    
      Geolocator() : coords(0,0), isReliable(false) {}
    
      void getFromSensor() {
        coords = Point(100, 100);
        isReliable = true;
      }
    };


    Вариант 2. Через указатель, создание и уничтожение. Для простоты не буду это делать «руками», а воспользуюсь указателем единоличного владения unique_ptr.
    class Geolocator {
    public:
      std::unique_ptr<Point> coords;
    
      void getFromSensor() {
        Point pt(100, 100);
        if (coords) {
          *coords = pt;
        } else {
          coords.reset(new Point(pt));
        }
        // а если и операции = у Point нет, то можно
        // coords.reset(new Point(100, 100));
      }
    
      void declareUnreliable() {
        coords.reset();
      }
    };
    Ответ написан
    6 комментариев
  • Не заканчивается программа?

    @Mercury13
    Программист на «си с крестами» и не только
    Потому что конец консоли с клавиатуры зависит от ОС, и для Windows это Ctrl+Z.
    Нажатие ввода не передаёт в поток EOF.
    Ответ написан
    6 комментариев
  • Как доказать, что не существует трех таких цифр (0-9), сумма квадратов которых равна 172?

    @Mercury13
    Программист на «си с крестами» и не только
    Перебор.
    98x — не получается
    97x — не получается
    96x — не получается
    95x — не получается
    94x — не получается
    93x — x уже великоват

    88x — не получается
    87x — не получается
    86x — не получается
    85x — x уже великоват

    77x — не получается
    76x — x уже великоват
    66x — x и подавно великоват

    Вариант 2.
    172 делится на 4. Любой квадрат делится на 4 с остатком 0 или 1 — потому у нас должны быть три чётных цифры.
    Перебор сокращается.

    88x — не получается
    86x — x уже великоват

    66x — x и подавно великоват, дальше перебирать нет смысла.
    Ответ написан
    3 комментария
  • В корпусе сбоку вентилятор должен работать на вдув или на выдув (фото)?

    @Mercury13
    Программист на «си с крестами» и не только
    На вдув + грязевик. Который периодически снимают и трясут.
    В этом месте на выдув ставить бесполезно, надо сверху или на задней стенке.
    Баланс корпусных кулеров всегда смещают в сторону вдува — тогда внутри будет меньше грязи.
    Ответ написан
    Комментировать