Ответы пользователя по тегу Программирование
  • Как изменять значения переменных другого класса в C++?

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

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

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

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

    @Mercury13
    Программист на «си с крестами» и не только
    Думаю, ваша задача более высокого уровня такова. Пользователи разрисовывают свои имена всякими там картинками, задача — убрать их.

    Немного непонятно, с какой версией Delphi вы работаете, но, предположим, с 2010+.
    Там string эквивалентно UnicodeString, 16-битной строке неограниченной длины, управляемой подсчётом ссылок средствами Delphi.
    Юникод очень велик и будет расширяться, в идеале там может быть 1,15 млн. символов. Из них 120 тыс. уже занято.
    Поэтому лучшим решением будет делать не чёрный список символов, а белый.

    Качаем базу символов Unicode (есть где-то на unicode.org).
    Делаем из неё фильтр по каким-нибудь признакам: например, буква/цифра/знак/комбинирующий/пробел и направление письма — либо слева направо, либо адаптирующееся.
    Также для простоты исключаем символы с кодом 65536+ (с дополнительных плоскостей, они кодируются двумя WideChar).
    Вот этим белым списком и пользуемся. Проходимся по строке и убираем все лишние.
    Ответ написан
    1 комментарий
  • Как происходит "обновление" кодировок?

    @Mercury13
    Программист на «си с крестами» и не только
    UTF-8 — это кодировка, позволяющая (теоретически) 2 млрд символов.
    Ограничением Юникода сейчас является кодировка UTF-16, она кодирует только 1 млн символов.

    Чтобы устройства по всему миру показывали новые символы, надо…
    1. Консорциуму Юникода где-то среди этого миллиона нарисовать новый символ. Сейчас занято около 120 тыс., ещё 130 тыс. — небольшой диапазон в базовой плоскости и две полных плоскости по 216 шт. — объявлены пользовательскими и их может занимать кто угодно в пределах своей ОС или программы.
    2. Консорциум Юникода публикует изображение символа и обновляет таблицы свойств символа.
    • Тип: буква/цифра/пробел/знак препинания/технический знак/управляющий/комбинирующий/…
    • Положение в двунаправленном письме: слева направо/справа налево/приспосабливается/управляет. Если приспосабливается — в письме справа налево можно поменять местами, например, скобки, для этого тоже есть поле.
    • Письменность: латиница/кириллица/ноты/смайлики/символы валют…
    • Как переводят в заглавные буквы и в нормальную форму. Настройка заглавных букв может переписываться локалью, но есть и «общая юникодная» таблица.
    3. Разработчик ОС переводит таблицу во внутренний формат ОС и обновляет шрифты. С очередным обновлением ОС шрифты и таблицы придут на компьютер, и будут символы.
    4. Чаще всего «левые» символы неверно отображаются в браузере. Для этого разработчики браузеров по хитрым алгоритмам ищут на компьютере пользователя шрифт, где этот символ есть. И, допустим, на вики «рогалика» Brogue (brogue.wikia.com) на моём компьютере ранее отображались все символы монстров, сейчас — пара тотемов не показываются. Видимо, с кучей софта ранее установился подходящий шрифт, а сейчас — фигвам. А на рабочей «десятке» всё в порядке.
    Ответ написан
    1 комментарий
  • Qt. Как передавать данные между формами?

    @Mercury13
    Программист на «си с крестами» и не только
    Вариантов много, в зависимости от того, форма модальная или нет, и нужно ли каким-то моделям передавать сообщение «обновись».

    Вариант 1.
    class AddItem : public QWidget
    {
    public:
      AddItem(QWidget* aParent, QList<Institution>& aInstitutions)
          : QWidget(aParent), institutions(aInstitutions) {}
    private:
      QList<Institution>& institutions;
    };


    Во втором варианте у нас модальная форма, но редактировать можно только копию (например, институции первой формы задействованы в какой-то модели, или нужны каскадные удаления, или что-то ещё).
    class AddItem : public QDialog
    {
    public:
      int exec(QList<Institution>& aInstitutions);
    private:
      QList<Institution> institutions;
    };
    
    int AddItem::exec(QList<Institution>& aInstitutions)
    {
      institutions = aInstitutions;
      int r = QDialog::exec();
      if (r) {
         aInstitutions = std::move(institutions);
      }
      return r;
    }


    И много-много других вариантов.
    Ответ написан
    Комментировать
  • Когда ооп быстрее процедурного?

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

    Какую задачу конкретно решает ООП? Обуздать сложность разработки программ, собранных из взаимодействующих компонентов. Вот от этого и пляшем: если программа не модульная (например, какой-нибудь сложный научный расчёт), ООП мало поможет. Также ООП не поможет, если стандартная реализация ООП недостаточно эффективна по процессору или по памяти — например, в мою бытность JavaMe’шником ООП не жаловали, поскольку памяти много ел, типичный мобильник имел от 215 до 800 килобайт доступной памяти. Также плохо будет работать там, где нет взаимодействия (на типичном PHP, который выдал страничку и исчез).

    Что на PHP можно реализовать объектно?
    • Поддержку каких-то протоколов (БД, почта, какая-нибудь внешняя веб-служба наподобие VK API или Mandrill).
    • Что-нибудь из предметной отрасли, что меняет своё состояние — например, генерация картинок, звуков, архивов, PDF…
    • Может, сделаешь какой-нибудь генератор страниц, который сначала собирает каркас страницы, а затем, в зависимости от настроек и целевого устройства, обращивает его HTML-кодом.
    Ответ написан
    Комментировать
  • Картинка из картинок.Как сделать??

    @Mercury13
    Программист на «си с крестами» и не только
    Простейший вариант…
    1. Для каждой малой картинки выбрать «средний» цвет.
    2. Уменьшить исходное изображение до M×N px, и в каждый пиксель вместо сплошного цвета подставить ту картинку, которая больше всего подходит по цвету.

    Алгоритм можно совершенствовать — например, подставлять одну из 10 наиболее подходящих, а если в радиусе, скажем, 30 единиц есть куда больше 10 картинок — брать их все. А можно ещё использовать метод коррекции ошибок Флойда-Стейнберга (наиболее удачный метод при переводе картинок в N цветов)
    Ответ написан
    3 комментария
  • Есть несколько способов создания единственного экземпляра класса. Есть ли смысл использовать в многопоточной среде второй вариант (см. в теме)?

    @Mercury13
    Программист на «си с крестами» и не только
    Первый-то создаёт, однако…
    • Если во время создания напросится другой поток, будут созданы два экземпляра. В «не-мусорных» языках второй экземпляр будет «висеть» и его никак не уничтожишь.
    • При определённом устройстве среды исполнения (instance присваивается раньше, чем срабатывает конструктор) система может отдать другому потоку ссылку на неготовый экземпляр.

    От создания двух экземпляров второе точно защищает. Я не знаком с моделью памяти C# и потому не могу сказать, насколько второе защищает от неготового экземпляра; кажется, нужен ещё модификатор volatile.
    Ответ написан
    Комментировать
  • Как сделать простую многозадачность на Си?

    @Mercury13
    Программист на «си с крестами» и не только
    Это называется «кооперативная многозадачность» и такая была в Windows до 3. Если задача у нас отнимает больше, чем один квант времени, есть два варианта.
    1. Собрать кванты времени в конечный автомат. Каждый из элементов этого автомата должен сам сохранять свои регистры. Поскольку задача может быть сложная, удобно делать элементы автомата элементами структурного программирования — элемент «оператор», элемент «если», элемент «дождаться»… Мне это приходилось делать на Jav’е, с похожей целью — нужна была простейшая реализация сопрограмм с возможностью сохранения-загрузки, где мы остановились. Сложнее прикладное программирование, системное вообще не нужно.
    2. Использовать функцию Yield, которая сохраняет куда-то регистры процессора, переключает стековый сегмент, определяет, кому сейчас работать, и восстанавливает регистры нового процесса. Каждый процесс поминутно запускает этот Yield. Тут наоборот — процесс наполняется Yield’ами, и всё, а архитектуру машины надо всё же знать.

    Для подобного дела есть FreeRTOS, но как она работает — я не в курсе.
    Ответ написан
    2 комментария
  • Алгоритм генератора заявок для моделирования СМО с пуассоновским потоком?

    @Mercury13
    Программист на «си с крестами» и не только
    class Event {  //  интерфейс
    public:
      virtual double time() = 0;   // когда потребуется внимание со стороны менеджера событий
      virtual void process() = 0;  // команда обработать событие
      // virtual int type() = 0;      // можно пристроить, если по какой-то причине надо отличать кресло от генератора клиентов
    };
    
    class EventSink {  // интерфейс
      virtual void add(Event& x);
    }
    
    class Shop;
    
    class Chair : protected Event {
    private:
      double fTime;
      bool fIsOccupied;
    public:
      Shop& shop;
      virtual double time() override { return fTime; }
      virtual void process() override;
      {
         что-то типа…
         если shop.nWaiting != 0 {
            --shop.nWaiting;
            occupy(time);
         } else {
             isOccupied = false;
         }
      }
      void occupy (double aTime) {
            time = aTime + время обслуживания клиента
            shop.manager.add(*this);
       }
       bool isOccupied() { return fIsOccupied; }
    };
    
    class CustomerGenerator : protected Event {
       // Устроен аналогично Chair, служит для генерации потока клиентов
    public:
      virtual void process() override {
         если shop.nWaiting == 0 и кресло свободно {
            shop.chair.occupy(fTime);
         } else {
            ++shop.nWaiting;
         }
         fTime += экспоненциальное время ожидания;
         manager.add(*this);
      }
      void init() {
         fTime = 0;
         process();
      }
    };
    
    class Shop {
    public:
       Chair chair;  // можно несколько кресел
       CustomerGenerator generator;
       int nWaiting;  // сколько человек в очереди
       EventSink& manager;
    }
    
    class Manager : public EventSink {
       Event* events[2];   // события отсортированы по времени
       int nEvents;
    
       void add(Event& x) override {
          // вставить двоичным поиском x в нашу очередь;  тут же можно сделать ограничение
          // «обработать 1000 клиентов» или «работать 8 часов».
       }
    
       И самое главное — «жизненный цикл».
       shop.generator.init();
       Пока очередь не пуста…
       • вытащить из неё событие
       • process его!
    }


    Как оно работает?
    1. на 5-й минуте приходит посетитель. Значит, генератор вносится в очередь со временем 5 минут.
    2. Выбираем генератор из очереди. Поскольку в парикмахерской очереди нет, он садится в кресло (в список вносится кресло со временем 5+8 = 13 минут), в список вносится генератор со временем 5 + 3 = 8 минут.
    3. Из этой пары выбираем генератор (у него 8 минут, против 13 минут у кресла). Он вносит нашего товарища в очередь (теперь в очереди один), в очередь вносится генератор со временем 8+4 = 12 минут.
    4. Снова в очереди кресло и генератор, и минимальное время у генератора. Теперь в парикмахерской ждут двое, и генератор вносим в очередь на время 12 + 30 = 42 минуты.
    5. Теперь минимальное время у кресла, и оно обслуживает ещё одного посетителя, внося себя в очередь на (13 + 8 = 21 минуте.
    6. И снова минимальное время у кресла, оно вносит себя в очередь на 21 + 8 = 29 минут.
    7. Пришла 29 минута, но стричь-то некого! В очереди менеджера остался один генератор.
    8. Выбираем из очереди генератор, и так далее…

    (простите, что я написал сумбурно, ведь есть очередь событий в менеджере и очередь клиентов в парикмахерской).

    Не забудьте, что события добавляют не в хвост очереди, а куда угодно — ведь событие может, в свою очередь, каскадом вызвать другие события.
    Ответ написан
  • Как назвать переменную?

    @Mercury13
    Программист на «си с крестами» и не только
    pluralDays
    Ответ написан
    Комментировать
  • Как правильно обновлять элемент EDITTEXT?

    @Mercury13
    Программист на «си с крестами» и не только
    1. Для переноса строк использовать символ 13 (\r).

    2. ES_AUTOVSCROLL Automatically scrolls text up one page when the user presses the ENTER key on the last line.
    Так что не это тебе нужно, нужно просто ставить курсор в конец (исходники Delphi дают сообщение EM_SETSEL).

    3. Я не знаю, как ты управляешь памятью, но будь с этим предельно осторожен.

    4. strcat будет медленным, когда данных будет много, подумай про имитацию ввода (сообщение EM_REPLACESEL).
    Ответ написан
    1 комментарий
  • Как найти минимальное количество перестановок?

    @Mercury13
    Программист на «си с крестами» и не только
    Рассмотрим порядок чёт-нечет-чёт-нечет…
    Считаем, сколько чётных не на своих местах (=a).
    И сколько нечётных не на своих местах (=b).
    Если a≠b, у нас нет N чётных и N нечётных — выводим «неверный набор данных».
    А если равны, то для порядка чёт-нечет нужны a замен. Для противоположного — N-a.
    Вот и получается ответ min(a, N−a).
    Ответ написан
    7 комментариев
  • Как создать свою таблицу символов?

    @Mercury13
    Программист на «си с крестами» и не только
    В Юникоде есть области символов для внутреннего пользования (private use), специально для программ, которым нужен нестандартный символ. Есть два способа вывести такие символы на экран.
    1. Написать свой шрифт.
    2. Написать свой типографский движок. Используя элементы системного, разумеется.
    Первое, по-моему, проще, второе даст более интересный результат (например, символ может отображаться как цветная иконка).
    Ответ написан
  • Как реализовать расписание кругового турнира?

    @Mercury13
    Программист на «си с крестами» и не только
    Других методов я просто не вижу. Искать «round-robin tournament algorithm». Но, по-моему, проще поворачивать не кольцо, а схему матчей, поставив одну из команд (лучше последнюю) в центр круга.
    https://commons.wikimedia.org/wiki/File:Round-robi...
    Round-robin-schedule-span-diagram.svg
    Матчам 2-13, 3-12 и т.д. даём фиксированные направления, причём попеременно: 2-13, 12-3, 11-4…
    Направление матча 1-14 постоянно меняется.

    Если команды нумеруются от 0 до N−1, N — чётное, алгоритм получается такой.
    trans := случайная перестановка чисел 0 … N−1
    
    если N чётное
      то M := N−1
      иначе M := N
    
    цикл 2half = false…true
      цикл round = 0…M−1
        цикл shift = 1…[M/2]
          home := (round + shift) % M
          away := (round + M − shift) % M
          если (shift нечётное) xor 2half
            обменять home, away
          вывести trans[home], trans[away]
    
        если N чётное
          home := round
          away := M
          если (round нечётное) xor 2half
            обменять home, away
          вывести trans[home], trans[away]

    Для чётного N одна команда постоянно меняет поле, у остальных — единожды на круге сбивается. Для нечётного N ничего не сбивается.
    Ответ написан
    2 комментария
  • Задача по методу Эйлера, за что отвечает функция F в данном коде?

    @Mercury13
    Программист на «си с крестами» и не только
    Качество кода — на уровне студенческой лабораторной. Причём очень хреновой.

    Программа решает четыре системы.
    y = f0(t)
    y' = f1(t, y)
    y'' = f2(t, y, y')
    y''' = f3(t, y, y'')

    1. Если уж говорить о методе Эйлера — в программе ошибка.
    y[1] = y[1] + delt * y[2];
    Тут нужно старое значение y[2], а не новое.

    2. Функцию eiler стоило бы обозвать eulerStep, заодно убрав лишние параметры.

    3. Автор не знает такой концепции, как процедурный тип aka callback, поэтому работа с правой частью у него вышла вот через такую задницу.

    4. В промышленном коде метод решения ОДУ я бы вынес в отдельную процедуру, с callback’ами на правую часть и на потребителя результата. Причём внешнее (доступное пользователю библиотеки) именование должно быть такое, чтобы её пользователь мог ею воспользоваться, даже если он не читал статью, по которой библиотеку писали. Так что смотрите, какие имена являются стандартизированными, понятными по любому учебнику, а какие стоит прояснить. Внутреннее именование — это уж думайте сами, научный код обычно сложен, и его постоянно приходится сличать со статьёй. Поэтому имена как в статье — для научного кода не WTF.

    5. Не слишком удачно разделена ответственность между функцией правой части и функцией шага по Эйлеру. Это привело к ограничению — программа может решать только ОДУ y{n} = f(t, y, y', ..., y{n−1}).
    Ответ написан
    8 комментариев
  • Сложен ли язык программирования "C"?

    @Mercury13
    Программист на «си с крестами» и не только
    1. Стандартный Паскаль — без классов и прочих ништяков — даст определённое понимание об аскетизме Си. Недостаток Си именно в том, что там нет автодеструкторов — фирменной фишки C++. Даже в строках. А обработка ошибок с корректным уничтожением созданных объектов — в C++ автоматом, в Delphi/C#/Java try/finally — может намотать немало нервов.
    2. Хороших UI-библиотек с визуальным редактированием, как VCL в Delphi и WinForms в C#, на Си нет. Во многом это связано с тем, что на Си нет простого и стандартного способа хранить строки. Разумеется, невизуально никто не мешает делать интерфейс, WinAPI (кроме COM, который ориентирован под устройство класса Microsoft C++) рассчитан именно на Си.

    Язык учи, это неплохо расширит твой кругозор и даст понять, откуда берутся кое-какие фишки языков, с которыми мы постоянно имеем дело. Большинство языков в те времена писали академики. Си писал практик, писал как попало, писал для своих, и хоть некоторые его решения оказались неверными, Юникс сослужил хорошую службу как реклама Си.
    Ответ написан
  • Какая разница между параллельным и многопоточным программированием?

    @Mercury13
    Программист на «си с крестами» и не только
    Параллельное программирование — расчёт чего-либо на нескольких вычислительных ядрах.
    Многопоточное программирование — написание программ, работающих в несколько потоков.

    Параллельное, но не многопоточное: SETI@Home и прочие распределённые системы.
    Многопоточное, но не параллельное: шахматный ИИ работает независимо от интерфейса: пока человек думает, программа считает.
    Ответ написан
    Комментировать
  • В очередной раз графика в дельфи, как сделать поворот?

    @Mercury13
    Программист на «си с крестами» и не только
    Пока без возможности запустить программу вижу у тебя две проблемы.
    1. Две ошибки в повороте. а) неверная матрица вращения; б) во второй строке поворота имеет дело с новым X, а не старым.
    2. Подобные операции с целыми числами приводят к накоплению погрешностей; через несколько итераций кораблик быстро станет кособоким. С дробными, вообще-то, тоже, только не так быстро и есть шансы, что задачу выполним раньше, чем проблемы будут мало-мальски заметны.

    По поводу качества кода — я бы сделал функцию
    function RotateAround(const source, pivot : TPoint) : TPoint;
    Ответ написан
    Комментировать
  • Как вывести на NES (Dendy) статическую картинку, подключив компьютер в порт картриджа?

    @Mercury13
    Программист на «си с крестами» и не только
    :) Проще уж выпотрошить «денди» и запихнуть внутрь собственную схему (да хоть Raspberry Pi).
    Ответ написан